Python 的类里提供的,两个下划线开始,两个下划线结束的方法,就是魔法方法,魔法方法在恰当的时候就会被激活,自动执行。
一、__new__()方法
类名() 创建对象时,在自动执行 __init__()方法前,会先执行 object.__new__方法,在内存中开辟对象空间并返回;
如果Person类中没有__new__()方法,会执行父类object中的__new__()方法;
class Person():
def __init__(self, name):
self.name = name
print('执行init方法...')
def __new__(cls, *args, **kwargs):
print('执行new方法...')
# pass # 此时返回的是None
return object.__new__(cls)
yuan = Person('sxm')
print(yuan)
print(yuan.name)
通过重写__new__()方法实现类的单例模式:
# 单例模式
class Person():
mem = None
def __new__(cls, *args, **kwargs):
print('new方法...')
if not cls.mem:
cls.mem = object.__new__(cls)
return cls.mem
p1 = Person()
p2 = Person()
print(p1 == p2)
二、__str__()方法
改变对象的字符串显示。可以理解为使用print函数打印一个对象时,会自动调用对象的__str__
方法;
# __str__方法
class Person(object):
def __init__(self, name, age):
print("__init__方法执行")
self.name = name
self.age = age
def __str__(self):
# return object.__str__(self) # 返回实例对象的内存地址
return self.age #必须要返回字符串,返回非字符串时,会报错
# return self.name
yuan1 = Person("yuan", 23)
print(yuan1)
三、__repr__()方法
如下是在python终端命令中的执行效果:
>>> class Person():
... def __init__(self.name,age):
File "<stdin>", line 2
def __init__(self.name,age):
^
SyntaxError: invalid syntax
>>> class Person():
... def __init__(self,name,age):
... print('init...')
... self.name=name
... self.age=age
... def __str__(self):
... return self.name+self.name
... def __repr__(self):
... return self.name
...
>>> yuan1 = Person('sxm',12)
init...
>>> yuan2 = Person('sjj',13)
init...
>>> print(yuan1) #执行的是__str__()方法
sxmsxm
>>> yuan1 # 执行的是__repr__()方法
sxm
>>> print(yuan2)
sjjsjj
>>> yuan2
sjj
问:__str__()方法与__repr__()方法的区别
1.在python终端命令下执行print(instance)等同于执行__str__()方法;str返回的结果可读性更强
2.在python终端命令下输入实例对象名并执行等同于__repr__()方法;repr目的在于调试,便于开发使用;
# 案例二
>>> import datetime
>>> now = datetime.datetime.now()
>>> print(now)
2022-02-10 16:23:04.661556
>>> now
datetime.datetime(2022, 2, 10, 16, 23, 4, 661556)
# 案例三
>>> s = 'hello'
>>> s
'hello'
>>> print(s)
hello
四、__del__()方法
析构方法,当对象在内存中被释放时,自动触发执行。
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
# __del__()方法
class Person(object):
def __init__(self, name, age):
print("__init__方法执行")
self.name = name
self.age = age
def __del__(self):
print('del方法,删除%s' % self.name)
sxm1 = Person('ss',13)
sxm2 = Person('xx',14)
print('111')
# del sxm1 # 程序执行结束时,垃圾回收机制会自动触发del命令删除实例对象;所以该行注释掉时,也会执行del sxm1
# del sxm2
# 案例二
class A():
def open(self):
self.f = open('a.txt','w')
def __del__(self):
print('文件关闭')
self.f.close()
a = A()
a.open()
五、__eq__()方法
拥有__eq__
方法的对象支持相等的比较操作
# __eq__()方法
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def __eq__(self, obj):
print('eq方法...')
print(self.name)
print(obj.name)
return self.name == obj.name
# return object.__eq__(self, obj)
yuan = Person("yuan", 23)
alvin = Person("alvin", 23)
print(yuan == alvin)
六、__len__()方法
# __len__()方法
class G(object):
def __len__(self):
print('len...')
return 100
g=G()
print(len(g)) # 执行的是__len__()方法
# 案例二
l = [1,2,3,4,5]
print(len(l)) # 等同于l.__len__()
七、item系列
# item系列
class Person():
def __init__(self, name, age):
print('init...')
self.name = name
self.age = age
def __getitem__(self, item):
print('getitem...')
return self.__dict__.get(item)
def __setitem__(self, key, value):
print('setitem...')
print(key)
print(value)
self.__dict__[key] = value
def __delitem__(self, key):
print('delitem...')
self.__dict__.pop(key)
p1 = Person('sxm',13)
# print(p1.name) # 句点表示法
print(p1['name']) # 取值操作:执行的是__getitem__()方法
p1['gender'] = 'famale' # 赋值操作:执行的是__setitem__()方法
print(p1['gender'])
del p1['gender'] # 删除操作:执行的是__delitem__()方法
print(p1.__dict__) # 以dict格式返回实例对象的属性和属性值
print(dir(p1)) # 以list格式返回实例对象的所有属性名,包含许多魔法方法属性
八、attr系列
# attr系列
class Person(object):
def __init__(self, name, age):
print('init...')
self.name = name # 执行的是__setattr__()方法
self.age = age
def __getattr__(self, item):
print('getattr...')
def __setattr__(self, key, value):
print('setattr...')
print(key)
print(value)
self.__dict__[key] = value
def __delattr__(self, item):
print('delattr...')
self.__dict__.pop(item)
p1 = Person('sxm', 14)
# print(p1.name)
# print(p1.xxx) # 句点表示法:取值操作,执行的是__getattr__()方法;获取不存在的属性时执行的是Person类中重写的__getattr__()方法
p1.gender = 'male' # 句点表示法:复制操作:执行的是__setattr__()方法;
# print(p1.gender)
del p1.gender # 句点表示法;删除操作;执行的是__delattr__()方法
print(p1.__dict__)