4.魔法函数
4.1 __new__
、__init__
、__call __
、__del__
__new__
实例化对象(1.创建对象 2.分配内存)
__init__
构造方法,实例化对象时自动调用(1.可以没有 2.如果有方法必须返回None,默认不写return语句)
__call __
对象可以被调用时触发执行
__del__
析构方法,当对象被回收时触发执行(程序结束、对象引用计数为零称为垃圾时)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| class MyClass(object):
def __init__(self): print("__init__ is running...")
def __new__(cls): print("__new__ is running...") return super().__new__(cls)
def __call__(self, *args, **kwargs): print("__call__ is running...")
def __del__(self): print("__del__ is running...")
MyClass() print("----------------------")
a = MyClass() assert hasattr(a, "__del__") print(callable(a)) assert hasattr(lambda x, y: x + y, "__call__") print(callable(lambda x, y: x + y))
|
4.2 __str__
和 __repr__
两个方法都只是为了自定义对象的打印信息
对象被打印时执行,一般默认先找str, str没有则使用repr
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class A(object):
def __init__(self): self.name = "李四"
def __str__(self): print("__str__ is running ...") return "str"
def __repr__(self): print("__repr__ is running ...") return ""
print(A())
|
4.3 compare系列
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class Student: def __init__(self, age): self.age = age
def __eq__(self, other): print("__eq__ is running ... 可自定义比较逻辑") if isinstance(other, Student): return self.age == other.age return False
print(Student(18) == Student(18)) print(Student(18) != 18) print(dir(Student(18)))
|
4.4 attr系列
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 31 32 33
| class MyClass(object):
def __init__(self, name, age): self.name = name self.age = age
def __getattr__(self, item): print("getattr 获取不存在的对象属性时触发") return self.__dict__.get(item)
def __setattr__(self, key, value): print("setattr 设置修改对象属性时触发") super().__setattr__(key, value)
def __delattr__(self, item): print("delattr 删除对象属性时触发") if item == "name": pass else: super().__delattr__(item)
def __getattribute__(self, name): print("__getattribute__ called") return super().__getattribute__(name)
a = MyClass("李四", 18) print(a.id) del a.age print(f"查看对象属性:{a.__dict__}")
|
4.5 item系列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Person(object):
def __setitem__(self, key, value): print("setitem []设置值时触发") setattr(self, key, value)
def __getitem__(self, item): print("getitem []取值时触发") return getattr(self, item)
def __delitem__(self, key): print("delitem del p[key]时触发", key)
p = Person() p['id'] = 1 print(p['id']) del p['id']
|
4.6 __enter__
和 __exit__
上下文管理器: 支持”上下文管理协议”的对象,包含 enter() 和 exit() 方法
with 可以操作一个 支持上下文管理协议的对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class MyOpen: def __init__(self, file_name: str, mode="r"): self.file = open(file_name, mode)
def __enter__(self): print("进入with语句块时触发") return self.file
def __exit__(self, exc_type, exc_val, exc_tb): print("退出with语句块时触发,不论with语句块是否有异常报错,__exit__都会被执行") self.file.close()
with MyOpen("test", "w") as f: f.write("hello world")
|
4.7 __slots__
该类实例只能创建__slots__中声明的属性,否则报错, 具体作用就是节省内存
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 31 32 33 34 35 36 37 38 39 40 41 42
| from memory_profiler import profile
class Test(object): __slots__ = ['a', 'name']
def __init__(self, name): self.name = name
Test.c = 3 t = Test("xx") t.a = 1 print(t.c)
class TestA(object): __slots__ = ['a', 'b', 'c']
def __init__(self, a, b, c): self.a = a self.b = b self.c = c
class TestB(object): def __init__(self, a, b, c): self.a = a self.b = b self.c = c
@profile def func_02(): temp = [TestA(i, i + 1, i + 2) for i in range(10000)] del temp temp = [TestB(i, i + 1, i + 2) for i in range(10000)] del temp
func_02()
|
4.8 __add__
、 __dict__
、 __bases__
、 __all__
__add__
: 手动实现相加操作
__dict__
: 获取对象的属性
__bases__
: 获取类继承的元素
__all__
: 当其它文件以“from 模块名 import *”的形式导入该模块时,该文件中只能使用 __all__
列表中指定的成员
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| class MyClass(object):
def __init__(self, value): self.value = value
def __add__(self, other): return self.value + other.value
a = MyClass(10) print(a + MyClass(20)) print(MyClass.__dict__)
class A(object): pass
print(A.__bases__)
__all__ = ["MyClass"]
|