python中的魔术方法
魔法方法(Magic Method)是python内置方法,格式为:“__方法名__”,不需要主动调用,存在的目的是为了给python的解释器进行调用,几乎每个魔法方法都有一个对应的内置函数,或者运算符,当我们对这个对象使用这些函数或者运算符时就会调用类中的对应魔法方法,可以理解为重写这些python的内置函数。
1.init()魔术方法:
对象初始化时执行__init__
class Test: def __init__(self, name, age): self.name = name self.age = age print("名字:" + self.name) print("年龄:" + self.age) if __name__ == '__main__': a = Test("小李", "18") -------输出结果--------- 名字:小李 年龄:18
上面示例会发现:__init__方法会在类实例化的时候自动调用,无需手动执行;
2、new()魔术方法
对象初始化时执行__new__,目的是为该对象分配内存空间。
对象初始化时一般先执行__new__,再执行__init__,看下面示例:
class Test: def __new__(cls, *args, **kwargs): print("我是__new__方法") obj = object.__new__(cls) print(obj) return obj def __init__(self): print(self) print("我是__init__方法") if __name__ == '__main__': a = Test() -------输出结果--------- 我是__new__方法 <__main__.Test object at 0x123902f70> <__main__.Test object at 0x123902f70> 我是__init__方法
上面示例会发现:
1)__new__魔术方法返回的就是self的内存地址;
2)如果不在__new__方法里面调object的__new__方法就不会创建对象,__init__不会被执行;
3)如果不在__new__方法里面return创建好的对象,__init__不会被执行;
3、str()魔术方法
打印一个对象的时候,默认调用
class Test: def __init__(self): pass def __str__(self): return "test_name" if __name__ == '__main__': a = Test() print(a) -------输出结果--------- test_name
上面示例会发现:
1)操作类实例的时候自动化调用__str__,即print对象时,对象输出的样子;
2)还有一个魔术方法__repr__,与__str__类似,当同时出现时,str__优先级高于__repr;
4、del()魔术方法
对象被删除的时候调用该方法
class Test: def __init__(self): print("初始化对象") def __del__(self): print("对象被删除了") if __name__ == '__main__': a = Test() print("end") -------输出结果--------- 初始化对象 对象被删除了
上面示例会发现:
1)对象在内存中被释放时,自动触发执行;
2)此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以__del__()的调用是由解释器在进行垃圾回收时自动触发执行的
5、call()魔术方法
对象当作函数执行时会被默认自动调用
class Test: def __call__(self, *args, **kwargs): print("调用了__call__") if __name__ == '__main__': a = Test() a() -------输出结果--------- 调用了__call__
上面示例会发现:把类实例当成函数执行的时候会触发__call__方法,对于 call 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
6、len()魔术方法
调用len()函数的时候自动调用
class Test: def __init__(self, name, age): self.name = name self.age = age def __len__(self): # 实例有自己的__dict__属性,__dict__是一个字典,键是属性名,值为属性值 return len(self.__dict__) if __name__ == '__main__': t = Test("狗子", 22) print(len(t)) -------输出结果--------- 2
上面示例会发现:调用len()函数的时候自动调用,用来计算对象的长度
7、eq()魔术方法
调用相等判断的时候自动调用
class Test: def __init__(self, name, age): self.name = name self.age = age def __eq__(self, other): print(self.age) print(other.age) return self.age == other.age if __name__ == '__main__': t1 = Test("狗子", 22) t2 = Test("小李", 23) print(t1 == t2) -------输出结果--------- 22 23 False
8、hash()魔术方法
调用hash()方法时自动调用
class Test: def __init__(self, name, age): self.name = name self.age = age def __hash__(self): return hash(self.name) if __name__ == '__main__': t = Test("狗子", 22) print(hash(t)) -------输出结果--------- 902838481588431200
注意:只有不可变数据类型才有哈希值
9、getitem()魔术方法
获取实例属性的时候自动调用
class Test: def __init__(self, name, age): self.name = name self.age = age def __getitem__(self, item): return self.__dict__[item] if __name__ == '__main__': t = Test("狗子", 22) print(t['name']) -------输出结果--------- 狗子
10、setitem()魔术方法
用于设置对象属性
class Test: def __init__(self, name): self.name = name def __setitem__(self, key, value): self.__dict__[key] = value if __name__ == '__main__': t = Test("狗子") print(t.__dict__) t['age'] = 22 print(t.__dict__) -------输出结果--------- {'name': '狗子'} {'name': '狗子', 'age': 22}
11、delitem()魔术方法
删除对象属性时调用
class Test: def __init__(self, name): self.name = name def __setitem__(self, key, value): self.__dict__[key] = value def __delitem__(self, key): self.__dict__.pop(key) if __name__ == '__main__': t = Test("狗子") print(t.__dict__) t['age'] = 22 print(t.__dict__) del t['name'] print(t.__dict__) -------输出结果--------- {'name': '狗子'} {'name': '狗子', 'age': 22} {'age': 22}
12、delattr()魔术方法
class Test: def __init__(self, name): self.name = name def __setitem__(self, key, value): self.__dict__[key] = value def __delattr__(self, item): self.__dict__.pop(item) if __name__ == '__main__': t = Test("狗子") print(t.__dict__) t['age'] = 22 print(t.__dict__) del t.name print(t.__dict__) -------输出结果--------- {'name': '狗子'} {'name': '狗子', 'age': 22} {'age': 22}
注意:__delitem__和__delattr__都是删除对象的属性,但是其用法不一样,注意看上面2个示例。