__class__
见__name__
__name__
1)当前模块名,直接运行的模块的__name__为’__main__‘,其他的模块为’模块名’或’包名.模块名’
# tmpPkg.tmp.py
print(f'tmp.py {__name__}')
# main.py
import tmpPkg.tmp
print(f'main.py {__name__}')
> python .\main.py
tmp.py tmpPkg.tmp
main.py __main__
2)对象类名 或 函数名
class TestC:
pass
def testM():
pass
print(type(TestC()))
print(TestC().__class__)
#
#
print(type(TestC()).__name__)
print(TestC().__class__.__name__)
# TestC
# TestC
print(testM.__name__)
# testM
__call__
(self[, args…])class Test:
def __call__(self, __x, __y):
return f'{__x} + {__y} = {__x + __y}'
t = Test()
print(t(3, 5))
# 3 + 5 = 8
__new__
(cls[, …])见__del__
(self)
__init__
(self[, …])见__del__
(self)
__del__
(self)new 创建对象,静态方法(此处特殊,不用标记@staticmethod)
*new方法需要返回cls的一个实例,一般写作:return super().new(cls, *args, *kwargs),否则__init__
函数将不会执行)
init 初始化对象,同样注意调用父类的__init__
方法
del销毁对象(不推荐使用):当引用数为0销毁对象时调用,若父类包含del方法注意调用父类的del方法(object类无del方法)
执行顺序:代码块 new方法 init方法 … del方法
class Test:
print('执行代码块')
def __new__(cls, *args, **kwargs):
print('执行new')
return super().__new__(cls, *args, **kwargs)
def __init__(self):
print('执行init')
super(Test, self).__init__()
def __del__(self):
print('执行del')
# 若父类包含del方法注意调用父类的del方法(object类无del方法),故此处不调用
# super(Test, self).__del__()
Test()
# 执行代码块
# 执行new
# 执行init
# 执行del
__repr__
(self)见__str__
(self)
__str__
(self)__repr__
:描述对象的’正式字符串’,通常用于调试,因此表示信息丰富且明确。
__str__
:描述对象的’非正式字符串’,通常打印,因此表示信息简介方便。若__str__
未实现但__repr__
实现,则__str__
将使用__repr__
返回的字符串
class Test:
def __repr__(self):
return 'aaa'
def __str__(self):
return 'bbb'
t = Test()
print(repr(t))
print(str(t))
print(t)
# 未实现__repr__,未实现__str__
# <__main__.Test object at 0x000002056CEEF588>
# <__main__.Test object at 0x000002056CEEF588>
# <__main__.Test object at 0x000002056CEEF588>
# 实现__repr__,未实现__str__
# aaa
# aaa
# aaa
# 未实现__repr__,实现__str__
# <__main__.Test object at 0x00000228D90B8608>
# bbb
# bbb
# 实现__repr__,实现__str__
# aaa
# bbb
# bbb
__bytes__
(self)见__bool__
(self)
__bool__
(self)__bytes__
:将对象转为bytes,通过bytes(x)调用
__bool__
:返回True/False,若__bool__
未实现,则调用__len__
方法,故[](空列表)、()(空元组)、‘’(或"",空字符串)、{}(空集合或空字典)的值均为False,除此之外的已经定义好的假值有False(标准真值)、None、0。
class Test:
def __bytes__(self):
return b'x01x02'
def __bool__(self):
return True
# 实现__bytes__
t = Test()
print(bytes(t))
# b'x01x02'
print(bool(t))
# True
__fspath__(self)
返回对象所在文件系统的路径str
import os
class Test:
def __fspath__(self):
return 'home/malloclu/TestObject'
print(os.fspath(Test()))
# home/malloclu/TestObject
copy(浅)复制、deepcopy深复制
from copy import copy, deepcopy
# 基本数据类型
a = 1.2
# 1. 引用
b1 = a
# 2. (浅)复制
b2 = copy(a)
# 3. 深复制
b3 = deepcopy(a)
a = 3.4
# 由于基本数据类型只有赋值没有引用,所以 3种方法 值均没有发生变化
print(f'{b1}\n{b2}\n{b3}\n')
# 1.2
# 1.2
# 1.2
# 简单对象(例如单层容器)
a = [1, 2, 3]
# 1. 引用
b1 = a
# 2. (浅)复制
b2 = copy(a)
# 3. 深复制
b3 = deepcopy(a)
a[1] = 4
# 仅 引用 方法值发生了变化,因为它和a指向的是内存中同一个对象
print(f'{b1}\n{b2}\n{b3}\n')
# [1, 4, 3]
# [1, 2, 3]
# [1, 2, 3]
# 多层容器(例如多层容器,字典嵌套列表)
a = {'k': [1, 2, 3]}
# 1. 引用
b1 = a
# 2. (浅)复制
b2 = copy(a)
# 3. 深复制
b3 = deepcopy(a)
a['k'][1] = 4
# 引用b1 和 (浅)复制b2 值发生了变化。其中b1因为和a指向的是内存中同一个对象,b2是因为浅复制生成的字典key引用到了a的[1, 2, 3]上,而b3因为深复制生成的字典key引用到了新生成的[1, 2, 3]上。
print(f'{b1}\n{b2}\n{b3}\n')
# {'k': [1, 4, 3]}
# {'k': [1, 4, 3]}
# {'k': [1, 2, 3]}
memo字典中保留了内存id到对象的对应关系,以便完美地重构复杂的对象图。(若不想获知该对应关系,则使用deepcopy(x, memo={})时该参数可以不使用)
from copy import deepcopy
a = {'k': [1, 2, 3]}
memo={}
b = deepcopy(a, memo=memo)
print(memo)
# {2092202719048: [1, 2, 3],
# 2092195593896: {'k': [1, 2, 3]},
# 2092195593976: [[1, 2, 3], {'k': [1, 2, 3]}]}
(浅)复制和深复制要分别实现__copy__(self)
和__deepcopy__(self, memodict={})
方法
from copy import copy, deepcopy
class Test:
def __init__(self, val):
self.val = val
def __copy__(self):
return Test(self.val)
def __deepcopy__(self, memodict={}):
return Test(deepcopy(self.val, memodict))
def __str__(self):
return str(self.val)
# 简单对象(例如单层容器)
a = Test([1, 2, 3])
# 1. 引用
b1 = a
# 2. (浅)复制
b2 = copy(a)
# 3. 深复制
b3 = deepcopy(a)
a.val[1] = 4
# 引用b1 和 (浅)复制b2 值发生了变化。其中b1因为其和a指向的是内存中同一个对象,b2因为b2.val和a.val指向的是内存中同一个对象,而b3因为b3.val指向新生成的[1, 2, 3]。
print(f'{b1}\n{b2}\n{b3}\n')
# [1, 4, 3]
# [1, 4, 3]
# [1, 2, 3]
符号 | 运算 | 反运算 | 增量赋值运算(例如+= 、-= 等) | 备注 |
---|---|---|---|---|
+ | __add__(self, other) | __iadd__(self, other) | __radd__(self, other) | |
- | __sub__(self, other) | __isub__(self, other) | __rsub__(self, other) | |
* | __mul__(self, other) | __imul__(self, other) | __rmul__(self, other) | |
@ | __matmul__(self, other) | __imatmul__(self, other) | __rmatmul__(self, other) | numpy类型实现了该方法,即矩阵乘法,基本数据类型和list未实现 |
/ | __truediv__(self, other) | __itruediv__(self, other) | __rtruediv__(self, other) | 除以 |
// | __floordiv__(self, other) | __ifloordiv__(self, other) | __rfloordiv__(self, other) | 整除以 |
% | __mod__(self, other) | __imod__(self, other) | __rmod__(self, other) | |
divmod(__x, __y) | __divmod__(self, other) | __rdivmod__(self, other) | 返回(商, 余数) | |
** | __pow__(self, other[, modulo]) | __ipow__(self, other[, modulo]) | __rpow__(self, other[, modulo]) | self的other次方 或 self的other次方对modulo取余 |
<< | __lshift__(self, other) | __ilshift__(self, other) | __rlshift__(self, other) | 左移 |
>> | __rshift__(self, other) | __irshift__(self, other) | __rrshift__(self, other) | 右移 |
& | __and__(self, other) | __iand__(self, other) | __rand__(self, other) | 按位与 |
^ | __xor__(self, other) | __ixor__(self, other) | __rxor__(self, other) | 按位异或 |
` | ` | __or__(self, other) | __ior__(self, other) | __ror__(self, other) |
< | __lt__(self, other) | |||
<= | __le__(self, other) | |||
== | __eq__(self, other) | |||
!= | __ne__(self, other) | |||
> | __gt__(self, other) | |||
>= | __ge__(self, other) |
以+为例,A + B,要求 A重载了__add__
运算符 或 B重载了__radd__
运算符 (若均重载,则使用A的__add__运算符
)【代码1】
在重载的运算符方法中,应该对另一个操作数的类型进行判断,没有针对该类型编写代码时手动抛出异常【代码2】
(例如A+B,A属于classA,B属于classB,A重载了__add__
方法。当执行A+C(C属于classC)也能调用A的__add__
方法,但A的__add__
函数体是针对classB编写的,所以很可能执行失败出现各种异常情况。故推荐在A的__add__
函数体中先判断另一个操作数的类型,针对不同的类型编写不同的操作,没有被考虑到的类型手动抛出异常)
class TestA:
def __add__(self, other):
return f'add TestA + {type(other).__name__}'
class TestB:
pass
class TestC:
def __radd__(self, other):
return f'radd {type(other).__name__} + TestC'
# 左操作数重载了__add__,将被调用,对右操作的重载情况无要求
print(TestA() + TestA())
print(TestA() + TestB())
print(TestA() + TestC())
print(TestA() + 1)
# add TestA + TestA
# add TestA + TestB
# add TestA + TestC
# add TestA + int
# 左操作数未重载__add__,若右操作重载__radd__将被调用,否则将报错
print(TestB() + TestA())
print(TestB() + TestB())
print(TestB() + TestC())
print(TestB() + 1)
# TypeError: unsupported operand type(s) for +: 'TestB' and 'TestA'
# TypeError: unsupported operand type(s) for +: 'TestB' and 'TestB'
# radd TestB + TestC
# TypeError: unsupported operand type(s) for +: 'TestB' and 'int'
# 不推荐
class TestA:
def __add__(self, other):
if isinstance(other, int):
return f'add TestA + {type(other).__name__}'
print(TestA() + 1)
print(TestA() + 'tmp')
# add TestA + int
# None
# **推荐**
class TestB:
def __add__(self, other):
if isinstance(other, int):
return f'add TestA + {type(other).__name__}'
raise TypeError(f"unsupported operand type(s) for +: 'TestA' and '{type(other).__name__}'")
print(TestB() + 1)
print(TestB() + 'tmp')
# add TestA + int
# TypeError: unsupported operand type(s) for +: 'TestA' and 'str'
class TestA:
def __init__(self, val):
self.val = val
def __add__(self, other):
if isinstance(other, TestA):
return TestA(self.val + other.val)
raise TypeError(f"unsupported operand type(s) for +: 'TestA' and '{type(other).__name__}'")
A = TestA(1)
B = TestA(2)
C = A + B
print(C.val)
class TestB:
def __init__(self, val):
self.val = val
def __iadd__(self, other):
if isinstance(other, TestB):
return TestB(self.val + other.val)
raise TypeError(f"unsupported operand type(s) for +: 'TestB' and '{type(other).__name__}'")
A = TestB(4)
B = TestB(5)
A += B
print(A.val)
符号 | 方法 | 备注 |
---|---|---|
- | __neg__(self) | 取正,返回类型任意 |
+ | __pos__(self) | 取负,返回类型任意 |
abs(__x) | __abs__(self) | 绝对值,返回类型任意 |
~ | __invert__(self) | 按位取反,返回类型任意 |
complex(__x) | __complex__(self) | 转换为复数,返回复数类型例如1+2j |
int() | __int__(self) | 转换为整数,返回整数类型例如3 |
float() | __float__(self) | 转换为浮点数,返回浮点数类型例如4.5 |
自动调用 | __index__(self) | 在需要整数的位置自动调用该函数将对象转换为整数类型,例如作为列表切片的索引时。 |
round(__x, ndigits=0) | __round__(self[, ndigits]) | 就近取整,返回类型任意。已经实现的int类型结果为10^(-ndigits)的整数倍(ndigits默认为0,结果默认为1的整数倍即取整),round(0.5)为0,round(0.50001)为1。 |
math.trunc(__x) | __trunc__(self) | 截断取整,返回类型任意。已经实现的int类型math.trunc(-2.3)为-2。 |
math.floor(__x) | __floor__(self) | 向下取整,返回类型任意。已经实现的int类型math.floor(-2.3)为-3。 |
math.ceil(__x) | __ceil__(self) | 向上取整,返回类型任意。已经实现的int类型math.ceil(-2.7)为-2。 |
import math
class Test:
def __neg__(self):
return 'a'
def __pos__(self):
return 'b'
def __abs__(self):
return 'c'
def __invert__(self):
return 'd'
def __complex__(self):
return 1 + 2j
def __int__(self):
return 3
def __float__(self):
return 4.5
def __index__(self):
return 1
def __round__(self, n=None):
return 'e'
def __trunc__(self):
return 'f'
def __floor__(self):
return 'g'
def __ceil__(self):
return 'h'
print(-Test())
print(+Test())
print(abs(Test()))
print(~Test())
# a
# b
# c
# d
print(complex(Test()))
print(int(Test()))
print(float(Test()))
# (1+2j)
# 3
# 4.5
testlist = ['aa', 'bb', 'cc']
print(testlist[Test()])
print(testlist[Test():Test()])
# bb
# []
print(round(Test()))
print(math.trunc(Test()))
print(math.floor(Test()))
print(math.ceil(Test()))
# e
# f
# g
# h
__next__
返回迭代器对象的下一个值(如果没有抛出StopIteration异常),实现了该方法则该对象可以作为next(__x)
的参数不断返回下一个值
__iter__
返回一个迭代器对象(该对象所属的类已经实现__next__
方法),实现了该方法则该对象可在for循环中迭代不断返回下一个值
class Fibs:
def __init__(self):
self.a = 0
self.b = 1
def __next__(self):
self.a, self.b = self.b, self.a + self.b
return self.a
def __iter__(self):
return self
>>>fibs = Fibs()
>>>next(fibs)
1
>>>next(fibs)
2
>>>for f in fibs:
... if f > 1000:
... print(f)
... break
1597
cle/details/111863037)
__next__
返回迭代器对象的下一个值(如果没有抛出StopIteration异常),实现了该方法则该对象可以作为next(__x)
的参数不断返回下一个值
__iter__
返回一个迭代器对象(该对象所属的类已经实现__next__
方法),实现了该方法则该对象可在for循环中迭代不断返回下一个值
class Fibs:
def __init__(self):
self.a = 0
self.b = 1
def __next__(self):
self.a, self.b = self.b, self.a + self.b
return self.a
def __iter__(self):
return self
>>>fibs = Fibs()
>>>next(fibs)
1
>>>next(fibs)
2
>>>for f in fibs:
... if f > 1000:
... print(f)
... break
1597