__getattr__
from datetime import date
class User:
def __init__(self, name, birthday):
self.name = name
self.birthday = birthday
if __name__ == '__main__':
u = User('shell', date(year=1996, month=1, day=1))
print(u.birthday)
print(u.age)
显然我们访问age属性会报错因为没有age属性,实际上是先访问__getattr__魔法方法
from datetime import date
class User:
def __init__(self, name, birthday):
self.name = name
self.birthday = birthday
def __getattr__(self, item):
print(item)
if __name__ == '__main__':
u = User('shell', date(year=1996, month=1, day=1))
print(u.birthday)
print(u.age)
print(u.hight)
1996-01-01
age
None
hight
None
__getattr__方法会获取不存在的属性名(age,hight)并保存在item中。
注意打印一个没有返回值的函数结果都是None,所以会有两个None
getattaribute
__getattaribute__是属性访问拦截器,当这个累的属性被实例访问时,会自动调用类的__getattaribute__方法。注意,不要轻易的重写__getattaribute__方法。
参考:https://blog.csdn.net/qq_26442553/article/details/82467777
属性描述符
- __get__
- __set__
- __del__
实现上述中任意一个魔法方法即可称为属性描述符,若只实现__get__称为非数据属性描述符,若同时实现__get__,__set__称为数据属性描述符。
class IntField:
def __get__(self, instance, owner):
print(instance)
print(owner)
print('__get__')
def __set__(self, instance, value):
print(instance)
print(value)
print('__set__')
class User:
age = IntField()
u = User()
u.age = 30
print(u.age)
<__main__.User object at 0x00000218759585F8>
30
__set__
<__main__.User object at 0x00000218759585F8>
<class '__main__.User'>
__get__
None
传入30后,先调用age对象的__set__,打印后调用__get__。instance都是User对象的内存地址,value是传入的值,owner是User类。
class IntField:
# 数据描述符
def __get__(self, instance, owner):
return self.values
def __set__(self, instance, value):
if not isinstance(value, int):
raise TypeError('类型错误')
self.values = value
# class NonDataIntField:
# # 非属性描述符
# def __get__(self, instance, owner):
# return self.value
class User:
age = IntField()
u = User()
u.age = 30
print(u.age)
参考文章:https://www.cnblogs.com/xyz2b/p/10529068.html