基本结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Animal:
count = 0 # 函数外使用静态变量

# 构造函数, __xxx__ 为特殊成员函数, 具有官方指定的特殊用途, 非私有
def __init__(self, name: str):
self.name = name # 公有成员变量
self._name = name # 受保护成员变量, 使用 _ 开头, python 不强制受保护只是用户约定
self.__name = name # 私有成员变量, 使用 __ 开头
Animal.count += 1 # 函数内使用静态变量

# 公有成员函数
def get_name(self) -> str:
return self.__name

# 受保护成员函数, 使用 _ 开头, python 不强制受保护只是用户约定
def _get_name(self) -> str:
return self.__name

# 私有成员函数, 使用 __ 开头
def __get_name(self) -> str:
return self.__name

# 静态成员函数
@staticmethod
def getCount() -> int:
return count

# 析构函数
def __del__(self):
Animal.count -= 1

多态、虚继承、多继承

python 对多态、虚继承、多继承均支持。

重载类行为

构造与析构

函数声明 描述 用户调用示例 实际调用示例
__init__(self, ...) 构造函数 animal = Animal(...) Animal.__init__(animal, ...)
__del__(self) 析构函数 del animal animal.__del__()
__new__(cls, ...) -> cls 构造函数 animal = Animal(...) Animal.__init__(animal, ...)

注意: __new____init__ 都是构造函数,但两者略有不同。__new__ 是类级的,__init__ 是实例级的。构造对象时,如果用户未定义 __new__ ,将继承 object 类的 __new__ 调用 __init__ 构造。__new__ 是类级的,可以完成 __init__ 无法完成的一些工作,如创建单例、继承不可变类型。

重载运算符

算数运算函数 描述 用户调用示例 实际调用示例
__add__(self, x) 重载加法 x + y X.__add__(x, y)
__sub__(self, x) 重载减法 x - y X.__sub__(x, y)
__mul__(self, x) 重载乘法 x * y X.__mul__(x, y)
__div__(self, x) 重载除法 x / y X.__div__(x, y)
__floordiv__(self, x) 重载整除 x // y X.__floordiv__(x, y)
__mod__(self, x) 重载取余 x % y X.__mod__(x, y)
__pow__(self, x) 重载幂运算 x ** y X.__pow__(x, y)

注意:

  • 在重载运算符中 __ixxx__ 用于重载自运算。例如:x += y 有比 x = x + y 更好的解决方案时,可以实现 x += y 运算。未定义时,__ixxx__ 运算调用 __xxx__ 运算。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    class Int:
    def __init__(self, x):
    self.x = x

    def __add__(self, y):
    return self.x + y.x

    def __iadd__(self, y):
    self.x += y.x
    return self


    a = Int(2)
    b = Int(3)
    print(id(a))
    print(id(a + b))
    a += b
    print(id(a))
  • 在重载运算符中 __rxxx__ 用于重载反向运算。例如:X.__sub__(x, y)Y.__rsub__(y, x) 都对应 x - y 运算,在需要实现内置类型或第三方类型与自定义类型的运算时需要实现该方法。

单目运算函数 描述 用户调用示例
__neg__(self) 取负 -self
__pos__(self) 取正 +self
__invert(self) 位反 ~self
比较运算函数 描述 用户调用示例
__cmp__(self, x) -> bool 比较方法 3.x 弃用
__lt__(self, x) -> bool <,排序通常调用它 self < x
__le__(self, x) -> bool <= self <= x
__eq__(self, x) -> bool == self == x
__ne__(self, x) -> bool != self != x
__gt__(self, x) -> bool > self > x
__ge__(self, x) -> bool >= self >= x

注意: 另有一些运算符如:位运算符、比较运算符,在此不一一列出。

重载函数调用

函数声明 描述 用户调用示例
__abs__(self) abs(self)
__round__(self, ndigits = 0) round(self, ndigits = 0)
__len__(self) -> int len(self)
函数声明 描述 用户调用示例
__int__(self) -> int 类型转换 int(self)
__float__(self) -> float 类型转换 float(self)
__bool__(self) -> bool 类型转换 bool(self)
__bytes__(self) -> bytes 类型转换 bytes(self)

注意: 重载函数调用方法非常多而复杂,无法一一列举。

字符串行为

函数声明 描述 用户调用示例
__str__(self) -> str 非正式文本形式 str(self)
__repr__(self) -> float 正式文本形式 repr(self)
__format__(self, *args) 格式化方法 self.format(*args)

注意: 当用户未定义非正式文本形式时,__str__ 将调用 __repr__ 方法;但当用户为定义正式文本形式时,__repr__ 不会调用 __str__。一些方法使用 __str__,一些方法使用 __repr__,因此当不区分正式时推荐重载 __repr__

迭代行为

函数声明 描述 用户调用示例
__iter__(self) 获取迭代器,可以兼用自身作迭代器返回 self,也可返回专用迭代器 iter(self)
__next__(self) 从迭代器获取下一迭代,在迭代结束时需抛出 StopIteration next(self)
__reversed__(self) 返回反向迭代器 reversed(self)

事实上 Python 中的 for 语句实际就是 iternext 函数的组合使用,例如以下两份代码是相同:

1
2
for x in ls:
print(x)
1
2
3
4
5
6
7
it = iter(ls)
while True:
try:
x = next(it)
print(x)
except StopIteration:
break

序列行为

序列拥有一套特有的语法,如访问、遍历、删除、插入等。在定义序列时通常需要重载序列行为。

函数声明 描述 用户调用示例
__len__(self) -> int 序列大小 len(self)
__contains__(self, key) -> bool 包含元素 key in self
__getitem__(self, key) 访问元素 val = self[key]
__setitem__(self, key, val) 修改元素 self[key] = val
__delitem__(self, key) 删除元素 del self[key]
__missing__(self, key) 元素缺失行为,通常继承时使用 val = self[key](备选)

计算属性

通常一个属性与一个变量绑定,而计算属性被虚拟而不占用物理空间,在需要时计算它的值,按照用户设定逻辑 “更改” 它的值。计算属性通常用于两个场景:

  • 大量数据冗余,而无需经常访问。
  • 数据安全需要,不宜直接存储。

事实上计算属性可以使用 getxxx()setxxx() 一对函数取缔,但计算属性语法将其虚拟为属性,更便于用户使用。

函数声明 描述 用户调用示例
__getattr__(self, attr) 访问计算属性 val = self.attr
__setattr__(self, attr, val) 修改计算属性 self.attr = val
__delattr__(self, attr) 删除计算属性 del self.attr
__dir__(self) 查看所有成员(字符串形式) dir(self)

其他行为

函数声明 描述 用户调用示例
__hash__(self) -> int 哈希函数(字典、集合) 作哈希表键时调用