Python | 魔法方法整理
前言:
魔法方法(Magic Method)是Python内置方法,格式为:“__方法名__
”,不需要主动调用,存在的目的是为了给python的解释器进行调用,几乎每个魔法方法都有一个对应的内置函数,或者运算符,当我们对这个对象使用这些函数或者运算符时就会调用类中的对应魔法方法,可以理解为重写这些python的内置函数。例如构造函数(__init__
)、字符串表示(__str__
, __repr__
)或算术运算符(__add__
/__mul__
)。其实还有许多你可能没有听说过的但是却很好用的方法,在这篇文章中,我们将整理这些魔法方法!
__init__
函数
__init__(self)
:构造方法,在创建对象时调用。
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__方法会在类实例化的时候自动调用,无需手动执行。
__new__
函数
__new__(cls, *args, **kwargs)
:为该对象分配内存空间,对象初始化时执行。
对象初始化时执行__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__
不会被执行;
__len()__
函数
__len__(self)
:返回对象的长度。
调用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()
函数的时候自动调用,用来计算对象的长度。
__getitem()__
函数
__getitem__(self, key)
:返回对象的项,例如obj[key]
。
获取实例属性的时候自动调用。
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'])
-------输出结果---------
狗子
__setitem__
函数
__setitem__(self, key, value)
:设置对象的项,例如obj[key] = value
。
用于设置对象属性。
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}
__delitem__
函数
__delitem__(self, key)
:删除对象的项,例如del obj[key]
。
删除对象属性时调用。
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}
__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个示例。
__version__
函数
__call__
函数
__call__(self, *args, **kwargs)
:对象的函数调用,例如obj(*args, **kwargs)
。
对象当作函数执行时会被默认自动调用。
class Test:
def __call__(self, *args, **kwargs):
print("调用了__call__")
if __name__ == '__main__':
a = Test()
a()
-------输出结果---------
调用了__call__
上面示例会发现:把类实例当成函数执行的时候会触发__call__
方法,对于 call 方法的执行是由对象后加括号触发的,即:对象()
或者 类()()
。
__main__
函数
__length_hint__
函数
__init_subclass__
函数
__all__
函数
__add__(self, other)
:对象的加法,例如obj + other
。
__dict__
函数
__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
注意:只有不可变数据类型才有哈希值。
__str__
函数
__str__(self)
:返回一个可读字符串表示。
打印一个对象的时候,默认调用。
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__
;
__repr__
函数
__repr__(self)
:返回一个可读字符串表示,通常用于调试。
__del__
函数
对象被删除的时候调用该方法。
class Test:
def __init__(self):
print("初始化对象")
def __del__(self):
print("对象被删除了")
if __name__ == '__main__':
a = Test()
print("end")
-------输出结果---------
初始化对象
对象被删除了
上面示例会发现:
1)对象在内存中被释放时,自动触发执行;
2)此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以__del__()
的调用是由解释器在进行垃圾回收时自动触发执行的
__add__
函数
运算符执行计算时调用。
class Test:
def __init__(self, age):
self.age = age
def __add__(self, other):
return self.age + other.age
if __name__ == '__main__':
t1 = Test(22)
t2 = Test(23)
print(t1 + t2)
__sub__
函数
__sub__(self, other)
:对象的减法,例如obj - other
。
运算符执行计算时调用。
class Test:
def __init__(self, age):
self.age = age
def __sub__(self, other):
return self.age - other.age
if __name__ == '__main__':
t1 = Test(22)
t2 = Test(23)
print(t1 - t2)
__mul__
函数
__mul__(self, other)
:对象的乘法,例如obj * other
。
__truediv__
函数
__truediv__(self, other)
:对象的除法,例如obj / other
。
__lt__
函数
__lt__(self, other)
:小于运算符,例如obj < other
。
__le__
函数
__le__(self, other)
:小于等于运算符,例如obj <= other
。
__eq__
函数
__eq__(self, other)
:等于运算符,例如obj == other
。
调用相等判断的时候自动调用。
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
__ne__
函数
__ne__(self, other)
:不等于运算符,例如obj != other
。
__gt__
函数
__gt__(self, other)
:大于运算符,例如obj > other
。
__ge__
函数
__ge__(self, other)
:大于等于运算符,例如obj >= other
。
__iter__
函数
__iter__(self)
:返回一个迭代器。
__next__
函数
__next__(self)
:返回迭代器的下一个项。
创建自己魔法方法
我们可以创建自己的方法和属性吗?是的,你可以,但你不应该这么做。
双下划线名称是为Python语言的未来扩展保留的,不应该用于自己的代码。如果你决定在你的代码中使用这样的名称,那么将来如果它们被添加到Python解释器中,这就与你的代码不兼容了。所以对于这些方法,我们只要记住和使用就好了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)