前言
python语言的五个魔术方法,他们都与Python属性相关,涉及获取、删除和修改。
__getattribute__方法
源码如下:
实战演练:
①首先定义一个类并访问类的对象属性:
class User:
def __init__(self, name, sex):
self.name = name
self.sex = sex
u1 = User(name='li', sex='male')
print(u1.name)
运行结果:
②接着在该类中加入 __getattribute__
class User:
def __getattribute__(self, item):
return '无论对象是否存在该属性,都会返回此值'
def __init__(self, name, sex):
self.name = name
self.sex = sex
u1 = User(name='li', sex='male')
print(u1.name)
print(u1.age)
运行结果:【因为User类中的 __getattribute__ 魔方方法重写了基类object类的方法,所以此时的 __getattribute__
__getattribute__
①触发时间:在访问对象成员属性的时候触发,无论对象的成员属性是否存在。
②作用:对属性进行一些处理。
③参数:
- self为当前对象;
- item是访问属性名称的字符串。
④返回值:对象的属性值。
【注意】
① __getattribute__方法的是返回值千万不能用 self.name
例如:
class User:
def __getattribute__(self, item):
return self.name
def __init__(self, name, sex):
self.name = name
self.sex = sex
u1 = User('li', 'male')
print(u1.name)
运行结果:
②可以使用 object.__getattribute__
例如:
class User:
def __getattribute__(self, item):
return object.__getattribute__(self, item)
def __init__(self, name, sex):
self.name = name
self.sex = sex
u1 = User('li', 'male')
print(u1.name)
运行结果:
__getattr__方法
- 触发时间:在访问不存在的对象属性的时候触发。
- 作用:访问不存在的属性时候,不会报错。
- 参数:self为当前对象,item是访问属性名称的字符串。
- 返回值:属性值。
我们举个简单例子,就是用户可能会输出属性名称,那我们都统一返回name属性。
class User:
def __getattr__(self, item):
return self.name
def __init__(self, name, sex):
self.name = name
self.sex = sex
u1 = User('li', 'male')
print(u1.na2me)
li
__setattr__方法
- 触发时间:添加和修改对象属性的时候触发。
- 作用:限制添加和修改对象属性的操作。
- 参数:self为当前对象,key为设置对象属性名称, value为设置的值。
- 返回值:无。
例如,我们让用户可以改name,不能改sex。
__delattr__方法
- 触发时间:删除对象属性的时候触发。
- 作用:限制添加和修改对象属性的操作。
- 参数:self为当前对象,item为删除对象属性名称。
- 返回值:无。
例如:我们可以让用户删除sex,但是不能删除name。
class User:
def __delattr__(self, item):
if item == 'sex':
pass
else:
object.__delattr__(self, item)
def __init__(self, name, sex):
self.name = name
self.sex = sex
u1 = User('li', 'male')
del u1.sex
print(u1.sex)
del u1.name
print(u1.name)
male
AttributeError: 'User' object has no attribute 'name'
__dir__方法以及Python __dict__与dir()区别
Python下一切皆对象,每个对象都有多个属性(attribute),Python对属性有一套统一的管理方案。
__dict__与dir()
的区别:
- dir()是一个函数,返回的是list;
-
__dict__
是一个字典,键为属性名,值为属性值; - dir()用来寻找一个对象的所有属性,包括
__dict__
中的属性,__dict__
是dir()的子集;
dir()是Python提供的一个API函数,dir()函数会自动寻找一个对象的所有属性(包括从父类中继承的属性)。
一个实例的__dict__
属性仅仅是那个实例的实例属性的集合,并不包含该实例的所有有效属性。所以如果想获取一个对象所有有效属性,应使用dir()。
print dir(A)
'''
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'class_f', 'class_var', 'fun', 'level1', 'level2', 'name', 'num', 'static_f']
'''
a_dict = a.__dict__.keys()
A_dict = A.__dict__.keys()
object_dict = object.__dict__.keys()
print a_dict
print A_dict
print object_dict
'''
['fun', 'level1', 'age', 'name']
['__module__', 'level2', 'num', 'static_f', '__dict__', '__weakref__', '__init__', 'class_f', 'class_var', 'fun', '__doc__']
['__setattr__', '__reduce_ex__', '__new__', '__reduce__', '__str__', '__format__', '__getattribute__', '__class__', '__delattr__', '__subclasshook__', '__repr__', '__hash__', '__sizeof__', '__doc__', '__init__']
'''
#因为每个类都有一个__doc__属性,所以需要去重,去重后然后比较
print set(dir(a)) == set(a_dict + A_dict + object_dict) #True
属性访问顺序
最后,属性访问的顺序如下:
- __getattribute__
- 数据描述符
- 当前对象的属性
- 类的属性
- 非数据描述符
- 父类的属性
- __getattr__
去期待陌生,去拥抱惊喜。