当前位置: 首页 > news >正文

Python之面向对象和类

一.类

1.类的定义:

                class 类名:

                       “”“注释 ”“”

                        pass

2.实例的创建:

实例 = 类名(parameterlist)
parameterlist:定义类时__init__()方法的参数,如果该方法只有一个self参数,parameterlist可以省略

class Goose():"""定义了鹅类"""passgoose =  Goose()
print(goose)#<__main__.Goose object at 0x00000229213C6900>

3.创建类的构造函数方法:__init__()方法

        定义类时,通常会包含一个__init__()方法。该方法是构造函数方法,每当创建一个类的新实例时,Python都会自动执行它。
1.__init__()方法用来初始化新创建对象,在一个对象被创建以后会立即调用。
2. __init__()方法必须包含一个self参数并且必须是第一个参数self参数是一个指向实例本身的引用,用于访问类中的属性和方法。(相当于JAVA中的this)

       3.当__init__()方法只有一个参数时,在创建类的实例时,不需要指定实际参数。
4.__init__()方法的名称是以两个连续下划线开头和结尾,这是一种约定,用于区分Python默认方法和普通方法。

        5._init_()方法可以分为无参构造方法和有参构造方法。当使用无参构造方法创建对象时,所有对象的属性都有相同的初始值;当使用有参构造为法创建对象时,对象的属性可以有不同的初始值;

        6.如果你写多个构造方法,但是你在调用的时候,后写的构造方法会取代前面的构造方法(无论这两者参数上是否有区别),这点与JAVA不一样,所以一般一个类只有一个构造方法。

        7.一般来说,构造方法里面写初始化内容

class Goose():def __init__(self):print ("self:",self) #self: <__main__.Goose object at 0x0000022CD8766900>print("type of self:",type(self))#type of self: <class '__main__.Goose'>print("我是鹅类,我会自动执行该语句")           
g=Goose()

在__init__()方法中,除了self参数外,还可以自定义一些参数,参数间使用逗号“,”进行分隔。

class Goose:'''鹅类'''def __init__(self,beak,wing,claw):print("我是鹅类!我有以下特征:")print(beak)print(wing)print(claw)
beak_1 = "喙的基部较高,长度和头部的长度几乎相等"
wing_1 = "翅膀长而尖"
claw_1 = "爪子是蹼壮的"
wildGoose = Goose(beak_1,wing_1,claw_1)

当然,也可以不用构造函数(一般不推荐这样)

class Rect1():def getPeri(self,a,b):print("周长为:",(a+b)*2)def getArea(self,a,b):print("面积为:",a*b)
r1=Rect1()
r1.getPeri(3,4)
r1.getArea(3,4)
print(r1.__dict__)class Rect2():def __init__(self,a,b):self.a=aself.b=bdef getPeri(self):print("周长为:",(self.a+self.b)*2)def getArea(self):print("面积为:",self.a*self.b)
r2=Rect2(5,6)
r2.getPeri()
r2.getArea()
print(r2.__dict__)

二.类的成员

1.类的成员,静态定义

定义属性并访问
数据成员是指在类中定义的变量,即属性,根据定义位置,又可以分为类属性和实例属性。
① 类属性
类属性是指定义在类中,并且在函数体外的属性。
类属性可以在类的所有实例之间共享值,也就是在所有实例化的对象中公用。
类属性可以通过类名称或者实例名访问。

class Goose:'''鹅类'''neck = "脖子较长"wing = "振翅频率高"leg = "腿位于身体的中心支点,行走自如"def __init__(self):print("我属于鹅类!我有以下特征:")print(self.neck)print(self.wing)print(self.leg)
geese = Goose()

2.动态添加属性

在Python中除了可以通过类名称访问类属性,还可以动态地为类和对象添加属性

class Goose:'''鹅类'''neck = "脖子较长"wing = "振翅频率高"leg = "腿位于身体的中心支点,行走自如"def __init__(self):print("我属于鹅类!我有以下特征:")print(Goose.neck)print(Goose.wing)print(Goose.leg)geese = Goose()
#在类外,动态的为对象添加属性
geese.beak = "喙的基部较高,长度和头部的长度几乎相等"
print("鹅的喙:",geese.beak)

3.实例属性


实例属性,在JAVA中类似于对象的属性(官方不是这个叫法),实例属性是指在类的方法中的属性,就是__init__()构造方法中的参数,只作用于当前实例中。

class Goose:'''鹅类'''neck = "脖子较长"wing = "振翅频率高"leg = "腿位于身体的中心支点,行走自如"def __init__(self,name):self.name = nameprint("我属于鹅类!我有以下特征:")print(self.neck)print(self.wing)print(self.leg)print("实例属性,geese特有:",name)geese = Goose("娃哈哈")

4.实例属性和类属性的区别

class Dog:# 类属性(所有狗共享)species = "Canis familiaris"def __init__(self, name):# 实例属性(每个狗独立)self.name = name# 创建两个实例
dog1 = Dog("Buddy")
dog2 = Dog("Max")# 访问类属性(通过类名或实例名)
print(Dog.species)          # 输出: Canis familiaris
print(dog1.species)         # 输出: Canis familiaris# 访问实例属性(只能通过实例名)
print(dog1.name)            # 输出: Buddy
print(dog2.name)            # 输出: Max# 尝试通过类名访问实例属性(报错!)
#print(Dog.name)             # AttributeError: type object 'Dog' has no attribute 'name'# 修改类属性
Dog.species = "Canis lupus"
print(dog1.species)         # 输出: Canis lupus(所有实例同步更新)
print(dog2.species)         # 输出: Canis lupus# 通过实例修改"类属性"(实际是创建同名实例属性)
dog1.species = "Golden Retriever"
print(dog1.species)         # 输出: Golden Retriever(仅影响dog1)
print(dog2.species)         # 输出: Canis lupus(dog2不受影响)# 类属性本身未被修改
print(Dog.species)          # 输出: Canis lupus

总结如下:

特性类属性实例属性
定义位置类内部,__init__ 方法之外通常在 __init__ 方法内
归属属于类属于实例
访问方式类名或实例名均可访问只能通过实例名访问
共享性所有实例共享每个实例独立
修改影响修改后影响所有实例修改仅影响当前实例

5.访问限制

        为了保证类内部的某些属性或方法不被外部所访问,可以在属性或方法名前面添加单下划线(_foo)、双下划线(__foo)或首尾加双下划线(__foo__),从而限制访问权限。
其中,单下划线、双下划线、首尾双下划线的作用如下:
首尾双下划线表示定义特殊方法,一般是系统定义名字,如__init__(),一般自定义不推荐这种定义
以单下划线开头的表示protected(保护)类型的成员,只允许类本身和子类进行访问,但
不能使用“from module import *”语句导入
双下划线表示private(私有)类型的成员,只允许定义该方法的类本身进行访问,而且也
不能通过类的实例进行访问
,但是可以通过“类的实例名._类名_xxx”方式访问。

class MyClass:def __init__(self):self.public_value = "Public"       # 公开属性,可任意访问self._protected_value = "Protected"  # 保护属性(单下划线开头)self.__private_value = "Private"    # 私有属性(双下划线开头)def public_method(self):print("This is a public method.")def _protected_method(self):print("This is a protected method.")def __private_method(self):print("This is a private method.")def __special_method__(self):print("This is a special method (magic method).")class SubClass(MyClass):"""继承MyClass类"""def show_protected(self):print("接受保护属性 :", self._protected_value)def try_private(self):# 直接访问私有属性会报错# print(self.__private_var)  # 报错:AttributeError# 但可以通过 _类名__私有属性 的方式访问print("Accessing private from subclass:", self._MyClass__private_var)# 实例化
obj = MyClass()
sub_obj = SubClass()# 1. 公开成员(无下划线)
print(obj.public_value)            # 输出: Public
obj.public_method()              # 输出: This is a public method.# 2. 保护成员(单下划线开头)
print(obj._protected_value)        # 输出: Protected(可以访问但不推荐)
obj._protected_method()          # 输出: This is a protected method.
sub_obj.show_protected()         # 输出: Accessing protected from subclass: Protected# 3. 私有成员(双下划线开头)
# print(obj.__private_var)       # 报错:AttributeError
# obj.__private_method()         # 报错:AttributeError
print(obj._MyClass__private_var) # 输出: Private(通过名称重整访问)
obj._MyClass__private_method()   # 输出: This is a private method.
sub_obj.try_private()            # 输出: Accessing private from subclass: Private# 4. 特殊方法(首尾双下划线)
obj.__special_method__()         # 输出: This is a special method (magic method).

三.类的方法

1.实例方法

        实例方法是指在类中定义的函数。该函数是一种在类的实例上操作的函数。同__init__()方法一样,实例方法的第一个参数必须是self,并且必须包含一个self参数.

语法:

def 方法名(self,参数1,参数2....):
方法内容

调用形式:

        只能通过类名.方法名(参数)

class Goose:def __init__(self,beak,wing,claw):print("我是鹅类!我有以下特征:")print(beak)print(wing)print(claw)def fly(self,state):print(state)
'''*******************调用方法**********************'''
beak_1 = "喙的基部较高,长度和头部的长度几乎相等"
wing_1 = "翅膀长而尖"
claw_1 = "爪子是蹼壮的"
wildGoose = Goose(beak_1,wing_1,claw_1)
wildGoose.fly("我飞行的时候,一会排成个人字,一会排成个一字")

2.类方法:

在该方法前面必须加上@classmethod(注解,装饰器),来表明这是一个类方法,且必须带一个参数cls(跟类方法的self一样,但是为了区分两者,这里要写作cls)

调用方式:

        推荐     类名.方法名调用,

        不推荐   对象名.方法名

作用

  • 用于操作类属性(而不是实例属性)

  • 常用于工厂方法(创建类的不同实例)。

class Dog:"""species为一个类属性@classmethod后的类方法一般为了操作类属型(调用修改等等)"""species = "Canine"  # 类属性def __init__(self, name):self.name = name@classmethoddef get_species(cls):return cls.species  # 访问类属性@classmethoddef from_birth_year(cls, name, birth_year):age = 2025 - birth_yearreturn cls(name)  # 返回一个新的 Dog 实例,并将name传给新的实例(毕竟建造一个实例需要参数)# 通过类名调用类方法
print(Dog.get_species())  # 输出: Canine# 类方法作为工厂方法创建实例
dog = Dog.from_birth_year("Max", 2018)
print(dog.name)  # 输出: Max

注意:return cls(name)意味着

# 返回一个新的 Dog 实例,并将name传给新的实例(毕竟建造一个实例需要参数)

3..静态方法

在该方法前面必须加上@staticmethod(注解),来表明这是一个静态方法,可以无参数,

调用方式:

        推荐     类名.方法名调用,

        不推荐   对象名.方法名

  • 作用

    • 与类相关,但不依赖类或实例的状态(即不访问 self 或 cls)。

    • 类似于普通函数,但逻辑上属于类。

class MathUtils:@staticmethoddef add(a, b):return a + b@staticmethoddef multiply(a, b):return a * b# 通过类名调用静态方法
print(MathUtils.add(3, 7))  # 输出: 10# 也可以实例化后调用(但不推荐,静态方法不依赖实例)
utils = MathUtils()
print(utils.multiply(2, 4))  # 输出: 8

4.特殊方法:

(1)析构方法__del__()


Python中的垃圾回收主要采用的是引用计数。引用计数是一种内存管理技术,它通过引用计数器记录所有对象的引用数量,当对象的引用计数器数值为0时,就会将该对象视为垃圾进行回收

        getrefcount()函数是 sys模块中用于统计对象引用数量的函数,其返回结果通常比预期的结果大1。这是因为getrefcount()函数也会统计临时对象的引用。当一个对象的引用计数器数值为0时,就会调用_del__()方法,这个方法就是类的析构方法。系统就会销毁这个对象,收回对象所占用的内存空间。
所以析构方法(即__del_()方法)是用于销毁对象时系统自动调用的方法。每个类中也都默认有一个__del__()目方法,可以显式地定义析构方法。
        注意:析构方法不是销毁方法,而是在销毁之前释放资源,销毁方法是靠py底层代码来完成

(2)__str__()

简单来说就是相当于JAVA中的toString方法

若是不重写,就会用py自带的方法

class Person:def __init__(self, name, age):self.name = nameself.age = agep = Person("Alice", 25)
print(p)  # 输出: <__main__.Person object at 0x7f8b1c1b3d90>

若是重写:

class Person:def __init__(self, name, age):self.name = nameself.age = agedef __str__(self):return f"Person(name={self.name}, age={self.age})"p = Person("Alice", 25)
print(p)  # 输出: Person(name=Alice, age=25)

四.继承:

跟Java一样有object类为总的父类

1.单继承

基本语法:

        class 子类名(父类名)

# 父类
class Animal:def speak(self):print("动物发出声音")def eat(self):print("父类动物在吃东西")# 子类
class Dog(Animal):  # Dog继承Animaldef speak(self):  # 重写父类方法print("汪汪汪!")# 使用
animal = Animal()
animal.speak()  # 输出:动物发出声音dog = Dog()
dog.speak()     # 输出:汪汪汪!
dog.eat()       #子类继承父类方法eat

        

super关键字编程super方法,用法相同

2.多继承

1.在职研究生继承了Student和staff类

2.两者都有showinfo方法,调用对象.方法名,会优先调用第一个继承的父类 的方法,这里即Student类的showinfo方法

  • 若想调用Teacher的方法,可以:

    1. 调整继承顺序:class Person(Teacher, Student)

    2. 直接指定:Teacher.showinfo(p)

    3. 在子类中重写方法并手动选择调用哪个父类的方法是

3. 方法重写(Override)

子类可以重写父类的方法以改变其行为

# 父类
class Animal:def speak(self):print("动物发出声音")def eat(self):print("父类动物在吃东西")# 子类
class Dog(Animal):  # Dog继承Animaldef speak(self):  # 重写父类方法print("汪汪汪!")# 使用
animal = Animal()
animal.speak()  # 输出:动物发出声音dog = Dog()
dog.speak()     # 输出:汪汪汪!

4. super()函数

# 父类
class Animal:def speak(self):print("动物发出声音")def eat(self):print("父类动物在吃东西")# 子类
class Dog(Animal):  # Dog继承Animaldef speak(self):  # 重写父类方法print("汪汪汪!")super().eat()# 使用
dog = Dog()
dog.speak()     # 输出:汪汪汪!

5.强制转换

        对于Python继承机制

class Animal:def eat(self):print("动物吃东西")class Dog(Animal):  # Dog继承自Animaldef eat(self):print("狗吃骨头")def bark(self):print("汪汪叫")class Cat(Animal):def eat(self):print("猫吃鱼")
# 向上转型(自动) - 子类转父类
animal = Dog()  # 狗是动物(自动转换)
animal.eat()    # 输出: 狗吃骨头def trans(animal,obj):if isinstance(animal, obj):dog = animal  dog.bark()    else:print("不能将动物转为动物子类")trans(animal,Dog)
"""狗吃骨头
汪汪叫
"""
dog = Dog()
cat = Cat()
trans(cat,Dog)#不能将动物转为动物子类

        动物= 狗可以,动物=猫 可以,但是不能   狗=  动物

        要想狗 = 动物必须强制转换,狗 = (狗)动物

class Animal:def __init__(self, name):self.name = nameclass Dog:def __init__(self, animal):  # 构造函数中实现转换self.name = animal.namedef bark(self):print(f"{self.name}在汪汪叫")animal = Animal("旺财")
dog = Dog(animal)  # 强制将Animal转为Dog
dog.bark()         # 输出: 旺财在汪汪叫

五.多态

首先Python中的多态根JAVA不一样,JAVA的多态必须要在继承的基础之上,但是py的多态,根本不关心你是不是继承,是不是相同的数据类型。只要不同的类中有相同的方法,即可实现多态。

所以要定义一个接口,实现类的多态化。

class Animal:def eat(self):print("人吃五谷杂粮")class Dog:def eat(self):print("狗吃骨头")class Cat:    def eat(self):print("猫吃鱼")def jiekou(obj):obj.eat()# 创建实例
animal = Animal()
dog = Dog()
cat = Cat()# 多态调用
jiekou(animal)  # 输出: 人吃五谷杂粮
jiekou(dog)     # 输出: 狗吃骨头
jiekou(cat)     # 输出: 猫吃鱼

 

http://www.dtcms.com/a/270237.html

相关文章:

  • NFT,Non-Fungible Token,非同质化代币
  • openEuler2203sp4-vg磁盘组中剔除磁盘
  • 浅谈——数据采集爬虫
  • 实战:Android 15 (API 35) 适配 构建踩坑全记录
  • 板凳-------Mysql cookbook学习 (十一--------5)
  • 《每日AI-人工智能-编程日报》--2025年7月8日
  • Softhub软件下载站实战开发(十六):仪表盘前端设计与实现
  • 香港风水(原生)林地的逻辑分类器
  • 缺乏项目进度预警机制,如何建立预警体系
  • 从零开始手写嵌入式实时操作系统
  • 【c++八股文】Day4:右值,右值引用,移动语义
  • 使用协程简化异步资源获取操作
  • qt-C++语法笔记之Stretch与Spacer的关系分析
  • Python Web应用开发之Flask框架高级应用(三)——蓝图(Blueprints)
  • openssl 生成国密证书
  • 北京-4年功能测试2年空窗-报培训班学测开-第四十五天
  • [附源码+数据库+毕业论文]基于Spring+MyBatis+MySQL+Maven+vue实现的供电公司安全生产考试管理系统,推荐!
  • 【OD机试题解法笔记】跳马
  • MySQL8.0.40.0MSI安装教程
  • [特殊字符] AlphaGo:“神之一手”背后的智能革命与人机博弈新纪元
  • 汽车功能安全系统阶段开发【技术安全方案TSC以及安全分析】5
  • TypeScript 接口全解析:从基础到高级应用
  • Crazyflie无人机集群控制笔记(一)通过VRPN实时对接Crazyswarm2与NOKOV度量动捕数据
  • 数据湖技术之Iceberg-03 Iceberg整合Flink 实时写入与增量读取
  • Linux文件描述符与标准I/O终极对比
  • BabelDOC,一个专为学术PDF文档设计的翻译和双语对比工具
  • C#使用Semantic Kernel实现Embedding功能
  • 解决GitHub仓库推送子文件夹后打不开的问题
  • C++高频知识点(六)
  • vue3使用inspira-ui教程【附带源码】