python是一种面向对象的语言,面向对象有三大特性:封装、继承、多态。
本篇主要介绍python类的定义、构造、析构函数,以及属性、方法的辨析。稍后会更新封装、继承、多态的实现。
一、类、实例对象、类对象
类是将事物抽象总结成的概念,如:人、植物、动物等概念。
实例对象是由类创建的具体的对象,如:人—xuzf,植物—竹子等。
类对象是与类唯一对应的数据结构。Python解释器在解释完类定义的代码时,在当前作用域会创建一个类对象用来表示该类,并使用类名指向该类对象。
- 通过关键字
class
可以定义类。类被定义以后,默认会创建一个类对象。
class DemoClass:
pass
# 定义类,同时创建类对象
- 实例化:由类对象创建实例对象的过程称为实例化
demo1 = DemoClass()
# 类对象DemoClass()在内存中实例化了一个实例对象,demo1作为引用指向这个实例对象
二、类的属性辨析
属性是对象包含的数据成员,python中有两种属性——类属性、实例属性。
类属性:与类对象绑定的属性,被类对象和所有的实例对象共享。
- 类属性的绑定:可以在类定义时,也可以在运行时任意时刻
class DemoClass:
attri1 = 0 # 类定义时绑定类属性
DemoClass.attri2 = 1 # 运行时绑定类属性
print("attri1:", Democlass.attri1, " attri2:", DemoClass.attri2)
# out: attri1:0 attri2:1
- 类属性的调用:
class DemoClass:
attri = 0
# 类名.属性名 调用类属性
print(DemoClass.attri) # out: 0
# 实例对象调用类属性
demo1 = DemoClass()
demo1.attri += 1
print(demo1.attri) # out: 1
# 实例对象共享类属性
demo2 = DemoClass()
demo2.attri += 1
print(demo2.attri) # out: 1
实例属性:与实例对象绑定的属性,被实例对象独享。
- 实例属性的绑定:可以在类定义时,也可以在运行时任意时刻
- 实例属性的调用:先到实例对象中查找属性,再到类属性中查找属性
class DemoClass:
# 类属性
attri1 = 0
# 类的构造函数
def __init__(self, attri1):
self.attri1 = attri1 # 实例属性绑定
demo1 = DemoClass(1)
demo1.attri2 = 2 # 实例属性绑定
print(demo1.attri1, demo.attri2) # out: 1 2
三、类的方法辨析
方法是对象具有的功能和行为,通过绑定函数实现。
类有五种方法:实例方法、类方法、自由方法、静态方法、保留方法
类型 | 特点 |
---|---|
实例方法 | 实例对象的方法,由实例对象独享。需要包含self参数,self是正在调用方法的实例的引用 |
类方法 | 1. 由类对象和实例对象共享。需要包含cls参数,cls是调用方法的类对象。 2. 类方法只能调用类方法和类属性,不能调用实例方法和实例属性。 |
自由方法 | 可以调用类属性和类方法,不能调用实例属性和实例方法,由类所在命名空间管理,类对象独享 |
静态方法 | 在自由方法的基础上,添加能被实例对象调用的功能。 |
保留方法 | 保留方法由双下划线开始和结束的方法,保留使用 |
实例方法:
class DemoClass:
def __init__(self, name):
self.name = name
def print_name(self): # 实例方法 添加 self 参数
print(self.name)
demo1 = DemoClass("xuzf")
demo1.print_name()
# 只能通过 实例对象名.方法名() 方法调用
类方法:
class DemoClass:
age = 0
@classmethod # 类方法的装饰器
def print_age(cls, temp): # 传入 cls 参数
cls.age += temp
print(cls.age)
demo1 = DemoClass()
demo1.print_age(20)
# 或者 DemoClass.print_age(1)
# 可以通过类名.方法名 or 对象名.方法名调用
自由方法:
class DemoClass:
count = 0
def __init__(self):
DemoClass.count += 1
def func():
print(DemoClass.count)
demo1 = DemoClass()
DemoClass.func() # out: 1
demo2 = DemoClass()
DemoClass.func() # out: 2
# 自由方法只能通过 类名.方法名 调用
# 自由方法本质上与类无关,不能成为方法,而是函数,也可以写在类的外面
静态方法:
class DemoClass:
count = 0
def __init__(self):
DemoClass.count += 1
@staticmethod # 静态方法的装饰器
def func():
print(DemoClass.count)
demo1 = DemoClass()
DemoClass.func() # out: 1
demo2 = DemoClass()
demo2.func() # out: 2
# 静态方法可以通过 类名.方法名 or 对象名.方法名 调用
# 本质上和自由方法相同
保留方法:也称作魔术方法,主要是为了能使类和关键字配合使用
class DemoClass:
# 构造函数也是一个保留方法
def __init__(self, name):
self.name = name
# __len__函数
def __len__(self):
return len(self.name)
# __gt__函数
def __gt__(self, other):
return len(self) > len(other)
print( DemoClass("xuzf") > DemoClass("zf")) # out: True
# 魔法函数类似于C++中的运算符重载,使得类能够沿用一部分python内置函数
四、类的构造和析构函数
构造函数:
python的类中有一个保留方法 __init__()
;这个方法是类的构造函数。在通过类对象实例化对象时,会调用这个方法。
析构函数:
python解释器具有垃圾回收机制,能够自动的管理内存,一般不需要自己写析构函数。当一个对象那个的引用数为0时,系统会自动释放对象占用的内存。
如果需要自己设计析构函数,可以使用保留方法 __del__()
。通过 del obj_name
的形式手动析构对象。
对象的析构函数真正被调用的时间为:对象的引用数为0 or 程序结束运行。
class DemoClass:
def __init__(self):
self.attri = 1
def __del__(self):
print("destructor called")
demo1 = DemoClass()
demo2 = demo1 # demo1和demo2引用同一个对象
del demo1
print(demo2.attri)
# 1
# destructor called
# 当对象没有引用或者程序结束时,真正调用析构函数