前言
python有很多魔术方法,用的时候到处查,就想着写个博客记录一下吧
文章目录
魔术方法
init
这个方法我认为就相当于构造方法,用于初始化类,在实例化的时候调用
,传入的参数一般就是对应的对象的属性
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p = Person('cgy', 19)
print(p.name, p.age) # cgy 19
del
这个方法就是析构方法,在对象被销毁的时候调用
(1. del关键字 2. 程序结束后)
del
class Person:
def __del__(self):
print('对象被销毁')
p = Person()
del p # 对象被销毁
print('flag')
会发现在打印flag之前,会打印"对象被销毁",就是说,在del p的时候,对象确实被销毁了
程序结束时
这里用到了一个atexit模块,他可以在程序结束时做一些事情
import atexit
atexit.register(lambda x: print(x), '程序结束了')
class Person
def __del__(self):
print('对象被销毁')
p = Person()
会发现打印顺序是1. 程序结束了,2. 对象被销毁,就是说程序结束之后在清空程序用到的内存的时候,才打印出了“对象被销毁”这句话
getitem
在像字典一样获取元素时调用
setitem
在像字典一样设置属性时调用
delitem
在像字典一样删除元素时调用
这三个魔术方法可以让对象跟字典一样使用,而字典类似于js里面的对象,所以我觉得就是使得python的对象能够跟js里面的对象有共同的表现形式的方法。
class Animal(object):
def __getitem__(self, item):
print('__getitem__ ', item)
return self.__dict__.get(item)
def __setitem__(self, key, value):
print('__setitem__', key, ': ', value)
self.__dict__[key] = value
def __delitem__(self, key):
print('__delitem__')
del self.__dict__[key]
a = Animal()
a['name'] = 'cgy'
print(a['name'])
del a['name']
在上面的代码中,除了实例化的a = Animal()
,其他三行代码分别调用了__setitem__、__ getitem__、__delitem __。而且只有在像字典一样使用这个对象的时候,才会调用这几个方法,如果是a.name = 'cgy'
、print(a.name)
、del a.name
,这样子是不会调用这几个方法的。但是如print(a.name)
是可以获取到cgy这个字符串的。
然后,我个人认为就是,__delitem__
这个方法,是可以保证程序正常运行的一个方法,使得我们在错误删除属性的时候,程序还是可以正常运行,可以在里面使用try…except…语句,然后抓住异常,进行处理,即:如果没有这样的属性名,打印提示信息
def __delitem__(self, key):
try:
del self.__dict__[key]
except KeyError as e:
print('there is no key called', e)
getattr
获取属性的时候,如果对象没有这个属性,调用这个方法
setattr
每次设置属性的时候,调用这个方法
,包括__init__
delattr
删除属性的时候,调用这个方法
class Animal:
def __init__(self, name):
self.name = name
def __getattr__(self, item):
# 在获取__没有定义__的属性的时候,调用这个方法
print(f'you want attribute "{item}", but "{item}" is not defined')
def __setattr__(self, key, value):
# 设置属性的时候,调用这个方法
print('__setattr__ ', key, ': ', value)
self.__dict__[key] = value
def __delattr__(self, item):
print('__delattr__')
try:
del self.__dict__[item]
except KeyError as e:
print('there is no key called', e)
a = Animal('cgy')
a.age = 19
print(a.age)
del a.name
上面这段程序,在实例化的那一行,执行了__init__构造方法,会调用一次__setattr__;a.age = 19
会再一次调用__setattr__;在print(a.age)
因为获取了a.age,所以会调用一次__getattr__;最后的del a.name
会调用__delattr__
我觉得需要区分的是,如果这个类中也有__setitem__等魔术方法,我们像字典一样操作对象的时候,这些__setattr__等方法是不会被调用的。