python魔术函数
1、__repr__函数
- 通常__repr__函数是应用于实例化类中
- print(实例化类),直接打印出对应函数返回值
- 没有自定义__str__函数时,str(实例化类) 可以调用__repr__
- repr(实例化类),调用__repr__
class A:
def __repr__(self):
# print("哈哈哈")
return "输出repr"
B = A()
C = repr(B)
print(C)
# 输出repr
C1 = str(B)
print(C1)
# 输出repr
print(B)
# 输出repr
2、__str__函数
- 同时定义__repr__和__str__,print(实例化类) 时,调用的是__str__方法
- __str__可以被str(实例化类)调用,不能被repr(实例化类)函数调用
class A:
def __repr__(self):
return "输出repr"
def __str__(self):
return "输出str"
B = A()
C1 = str(B)
print(C1)
# 输出str
print(B)
# 输出str
3、__iter__函数 和__next__函数
- __iter__和__next__一般用于共同实现一个迭代器
- __iter__的作用主要是先变成一个迭代器对象,调用下一个元素是调用__next__的函数,当是最后一个函数时,必须抛出StopIteration来结束迭代
- __iter__加yield 也可以生成一个迭代器来迭代
__iter__ 加 __next__
class A:
def __iter__(self):
self.a = 0
return self
def __next__(self):
self.a += 1
if self.a > 10:
raise StopIteration
return self.a
B = A()
for i in B:
print(i)
1
2
3
4
5
6
7
8
9
10
__iter__ 加 yield
class A:
def __init__(self):
self.field = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
def __iter__(self):
for f in self.field:
yield f
B = A()
for i in B:
print(i)
1
2
3
4
5
6
7
8
9
10
4、__getitem__函数
- 让类可以像字典一样访问
class A:
def __init__(self):
self.field = {"name": "张三", "age": 18}
def __getitem__(self, key):
return self.field[key]
B = A()
print(B["age"])
18
print(B["name"])
张三
- 构建可迭代对象,用for循环调用时,自动调用__getitem__并且传入index
class A:
def __init__(self):
self.field = ['yi', 'er', 'san']
def __getitem__(self, index):
return self.field[index]
B = A()
for i in B:
print(i)
5 module/doc/name 魔术函数
- doc 打印出三元注释信息
- name 当前对象的名称
- module 当前对象属于那个模块,如果属于执行文件,那么结果是__main__ 否则就是所在的文件名称命名
class A:
"测试类"
pass
print(A.__doc__)
测试类
print(A.__name__)
A
print(A.__module__)
__main__
两个文件示例
- 当执行test.py文件时,可以发现导入te11时,就执行te11.py文件
- 此时A.__name__显示的便是te11文件名称
te11.py
class A:
"测试类"
pass
print(A.__doc__)
print(A.__name__)
print(A.__module__)
test.py
from te11 import *
import sys
print(sys.modules[__name__], 'apps')
print(hasattr(sys.modules[__name__], "apps"))
测试类
A
te11
<module '__main__' from 'D:/projectdir/ForwardPro/test.py'> apps
False
6、__getattr__函数
- 调用对象没有的属性时,会触发__getattr__函数
class A:
def __init__(self):
self.name = '张三'
self.money = 19
# 调用不存在的属性,属性会传参到__getattr__,item就是没有的属性名称
# 比如当调用B.age时,item就是age
def __getattr__(self, item):
print(item)
return 10
B = A()
print(B.age)
print(B.name)
print(B.money)
age
10
张三
19
7、__getattribute__函数
- 如果自定义了 getattribute,调用对象的属性都会走__getattrubute__这个函数,而不会管真实的属性值是什么
class A:
def __init__(self):
self.name = '张三'
self.money = 19
def __getattribute__(self, item):
print(f'{item}')
return f"{item}-01"
B = A()
print(B.age)
print(B.name)
print(B.money)
age
age-01
name
name-01
money
money-01
8 new/init/call 魔术方法
- new 通常在实例化类时,先走__new__方法,创建新的内存对象
- init 实例化类时,走完__new__方法,需要走__init__方法,初始化参数
- call 实例对象 后面加括号时,会调用其类的__call__方法
class A:
def __init__(self):
print("2、再来初始化")
self.name = '张三'
self.money = 19
# 因为new是创建的实例对象,所以输入的不应该是self代表实例对象
# 应该输入cls 表示A类
def __new__(cls):
print(id(cls))
print(cls.__name__)
print("1、先创建对象")
obj = super().__new__(cls)
print(id(obj))
return obj
def __call__(self):
print(id(self))
print("调用__call__方法")
B = A()
print(B.name)
print(id(B))
B()
1966830241088
A
1、先创建对象
1966290785856
2、再来初始化
张三
1966290785856
1966290785856
调用__call__方法