类的基本构建
-
使用class保留字定义类
class <类名>:
[类描述 documentation string]
<语句块>
类定义不限位置,可以包含在分支或其他从属语句块中,执行时存在即可。
类的名字:可以是任何有效标识符。建议采用大写单词的组合。
如ClassName, SortTest, MyModule …
类的描述:在类定义首行,以字符串定义。定义后通过<类名>.__doc__
属性来访问class DemoClass: "This is a DemoClass for Python" pass print(DemoClass.__doc__)
输出
:This is a DemoClass for Python
-
类对象 Class Object
- 类定义完成后,默认生成一个类对象
- 每个类唯一对应一个类对象,用于存储这个类的基本信息
- 类对象是type类的实例,表达为type类型
class DemoClass: "This is a DemoClass for Python" print("Hello, DemoClass!") print(DemoClass.__doc__) print(type(DemoClass))
输出
:Hello, DemoClass!
This is a DemoClass for Python
<class ‘type’>类对象内直接包含的语句会被执行,因此一般不在类内直接包含执行语句,一般放在类的方法中。
类的使用
-
通过创建实例对象(Instance Object)使用类的功能
<对象名> = <类名>([<参数>])
进一步采用<对象名>.<属性名>和<对象名>.<方法名>()
体现类的功能class DemoClass: "This is a DemoClass for Python" print("Hello, DemoClass!") print(type(DemoClass)) dc = DemoClass() print(type(dc))
输出
Hello, DemoClass!
<class ‘type’>
<class ‘main.DemoClass’>实例对象是Python类的最常用方式
类对象全局只有一个,而实例对象可以生成多个
类的构造函数
-
Python使用预定义的
__init__()
作为构造函数class <类名>: def __init__(self, <参数列表>): <语句块> ...
class DemoClass: def __init__(self, name): print(name) dc1 = DemoClass('老李') dc2 = DemoClass('老王')
输出
老李
老王
通过构造函数__init__()可以为Python对象提供参数 -
__init__
的使用说明- 参数:第一个参数约定是
self
,表示类实例自身,其他参数是实例参数
你一定会在想python如何给self赋值,以及为何你不必给它一个值。下面举个简单的例子:假设你有一个MyClass
的类,这个类下有个实例myobject
。当你调用一下这个对象的方法,如myobject.method(arg1, arg2)
时,python将会自动将其转换成MyClass.method(myobject, arg1, arg2)
。这就是self的神奇所在。
- 参数:第一个参数约定是
-
函数名:python解释器内部定义,由双下划线(__)开始和结束
-
返回值:构造函数没有返回值,或返回None,否则产生TypeError异常
类的属性
-
属性是类内部定义的变量
- 类属性:类对象的属性,由所有实例对象所共享
访问:<类名>.<类属性> 或<对象名>.<类属性>
- 实例属性:实例对象的属性,由各实例对象所独享
访问:<对象名>.<实例属性>
class <类名>: <类属性名> = <类属性初值> def __init__(self, <参数列表>): self.<实例属性名> = <实例属性初值> ...
class DemoClass: count = 0 def __init__(self, name, age): self.name = name self.age = age DemoClass.count += 1 dc1 = DemoClass('老李', 45) dc2 = DemoClass('老王', 50) print('总数:', DemoClass.count) print(dc1.name, dc2.name) print(dc1.age, dc2.age)
输出
总数: 2
老李 老王
45 50类属性 直接在类中定义或赋值
统一用<类名>.<属性名>访问实例属性
在类内部 用self.<属性名>访问
在类外部 用<对象名>.<属性名>访问 - 类属性:类对象的属性,由所有实例对象所共享
类的方法
方法是类内部定义的函数
-
实例方法:实例对象的方法,由各实例对象独享,最常用的形式。
class <类名>: def <方法名>(self, <参数列表>): ...
实例方法采用
<对象名>.<方法名>(<参数列表>)
方式使用class DemoClass: def __init__(self, name): self.name = name def lucky(self): s = 0 for c in self.name: s += ord(c) % 100 return s dc1 = DemoClass('老李') dc2 = DemoClass('老王') print(dc1.name, "的幸运数字是", dc1.lucky()) print(dc2.name, "的幸运数字是", dc2.lucky())
输出
老李 的幸运数字是 115
老王 的幸运数字是 148实例方法的定义 第一个参数是self
-
类方法:类对象的方法,由所有实例对象共享。
- 类方法至少包含一个参数,表示类对象,建议用cls
@classmethod
是装饰器,类方法定义所必须- 类方法只能操作类属性和其他类方法,不能操作实例属性和实例方法
class DemoClass: count = 0 def __init__(self, name): self.name = name DemoClass.count += 1 @classmethod def getChrCount(cls): s = '零一二三四五六七八九十' return s[DemoClass.count] dc1 = DemoClass('老李') dc2 = DemoClass('老王') print(dc1.getChrCount()) print(DemoClass.getChrCount())
输出
二
二 -
自由方法:类中的普通函数,由类所在命名空间管理,类对象独享。
class <类名>: def <方法名>(<参数列表>): ...
自由方法采用
<类名>.<方法名>(<参数列表>)
方式使用,<类名>表示命名空间
- 自由方法不需要self和cls这类参数,可以没有参数
- 自由方法只能操作类属性和类方法,不能操作实例属性和实例方法
- 自由方法的使用只能使用<类名>
class DemoClass: count = 0 def __init__(self, name): self.name = name DemoClass.count += 1 def foo(): DemoClass.count *= 100 return DemoClass.count dc1 = DemoClass('老王') print(DemoClass.foo())
-
静态方法:类中的普通函数,由类对象和实例对象共享。
class <类名>: @staticmethod def <方法名>(<参数列表>): ...
静态方法采用
<类名>.<方法名>(<参数列表>)或<对象名>.<方法名>(<参数列表>)
方式使用- 静态方法可以没有参数,可以理解为定义在类中的普通函数
@staticmethod
是装饰器,静态方法定义所必须- 静态方法只能操作类属性和其他类方法,不能操作实例属性和实例方法
- 相比于自由方法,静态方法能够使用<类名>和<对象名>两种方式使用
class DemoClass: count = 0 def __init__(self, name): self.name = name DemoClass.count += 1 @staticmethod def foo(): DemoClass.count *= 100 return DemoClass.count dc1 = DemoClass('老王') print(DemoClass.foo()) print(dc1.foo())
输出
100
10000
-
保留方法:由双下划线开始和结束的方法,保留使用,如
__len__()
。class <类名>: def <保留方法名>(<参数列表>): ...
保留方法一般都对应类的某种操作,操作产生时调用
class DemoClass: count = 0 def __init__(self, name): self.name = name DemoClass.count += 1 def __len__(self): return len(self.name) dc1 = DemoClass('老王') dc2 = DemoClass('诸葛亮') print(len(dc1)) print(len(dc2))
输出
2
3当对类执行
len()
方法时,将会执行类的__len__()
保留方法,我们只需要在保留方法中编写代码即可执行相应的操作。
类的析构函数
- Python使用预定义的
__del__()
函数作为析构函数
析构函数在真实删除实例对象时被调用class <类名>: def __del__(self): <语句块> ...
使用del删除对象且对象被真实删除时调用析构函数class DemoClass: def __init__(self, name): self.name = name def __del__(self): print("再见!", self.name) dc1 = DemoClass('老王') del dc1
__del__()
__del__()
的使用说明:-
函数名和参数:Python解释器内部约定,
保留方法
-
调用条件:当实例对象被
真实删除
时,才调用该函数内部语句 -
真实删除:当前对象的引用数为0或当前程序退出(垃圾回收)
class DemoClass: def __init__(self, name): self.name = name def __del__(self): print("再见!", self.name) dc1 = DemoClass('老王') dc2 = dc1 del dc1 print(dc2.name)
输出
老王
再见!老王由于删除dc1对象时,还存在dc2这个引用,因此并未真实删除对象,所以析构函数未被调用,当程序执行完,dc2这个引用被自动销毁,此时再调用析构函数,输出”再见!老王“。一般不需要写析构函数,让Python的垃圾回收机制去处理。这里了解就可以~
Python类的内存管理- 在删除对象前,Python解释器会检查引用次数
- 引用次数不为0,则仅删除当前引用;0,则删除对象
- 如果程序退出,则由垃圾回收机制删除对象
-