一、 _setattr_,_delattr_,_getattr_
class Foo:
x = 1
def __init__(self, y):
self.y = y
def __getattr__(self, item):
print('----> from getattr:你找的属性不存在')
def __setattr__(self, key, value):
print('----> from setattr')
# self.key=value #这就无限递归了,你好好想想
# self.__dict__[key]=value #应该使用它
def __delattr__(self, item):
print('----> from delattr')
# del self.item #无限递归了
self.__dict__.pop(item)
# __setattr__添加/修改属性会触发它的执行
f1 = Foo(10)
print(f1.__dict__) # 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值
print('==============')
f1.z = 3
print(f1.__dict__)
print('==============')
# __delattr__删除属性的时候会触发
f1.__dict__['a'] = 3 # 我们可以直接修改属性字典,来完成添加/修改属性的操作
del f1.a
print(f1.__dict__)
print('==============')
# __getattr__只有在使用点调用属性且属性不存在的时候才会触发
f1.xxxxxx
结果:
----> from setattr
{}
==============
----> from setattr
{}
==============
----> from delattr
{}
==============
----> from getattr:你找的属性不存在
二、_getattribute_
class Foo:
def __init__(self, x):
self.x = x
def __getattr__(self, item):
print('执行的是我')
# return self.__dict__[item]
f1 = Foo(10)
print(f1.x)
print('============')
f1.xxxxxx # 不存在的属性访问,触发__getattr__
结果:
10
============
执行的是我
class Foo:
def __init__(self, x):
self.x = x
def __getattribute__(self, item):
print('不管是否存在,我都会执行')
f1 = Foo(10)
f1.x
print('===================')
f1.xxxxxx
结果:
不管是否存在,我都会执行
===================
不管是否存在,我都会执行
class Foo:
def __init__(self, x):
self.x = x
def __getattr__(self, item):
print('执行的是我')
# return self.__dict__[item]
def __getattribute__(self, item):
print('不管是否存在,我都会执行')
# raise AttributeError('哈哈')
f1 = Foo(10)
f1.x
print('==================')
f1.xxxxxx
结果:
不管是否存在,我都会执行
==================
不管是否存在,我都会执行
class Foo:
def __init__(self, x):
self.x = x
def __getattr__(self, item):
print('执行的是我')
# return self.__dict__[item]
def __getattribute__(self, item):
print('不管是否存在,我都会执行')
raise AttributeError('哈哈')
f1 = Foo(10)
f1.x
print('==================')
f1.xxxxxx
结果:
不管是否存在,我都会执行
执行的是我
==================
不管是否存在,我都会执行
执行的是我
当__getattribute__与__getattr__同时存在,只会执行__getattribute__
如果__getattribute__在执行过程中抛出异常AttributeError,两个都会执行,不管属性存不存在。
三、_get_、_set_、_delete_
_get_():调用一个属性时,触发
_set_():为一个属性赋值时,触发
_delete_():采用del删除属性时,触发
# 描述符Str
class Str:
def __get__(self, instance, owner):
print('Str调用')
def __set__(self, instance, value):
print('Str设置...')
def __delete__(self, instance):
print('Str删除...')
# 描述符Int
class Int:
def __get__(self, instance, owner):
print('Int调用')
def __set__(self, instance, value):
print('Int设置...')
def __delete__(self, instance):
print('Int删除...')
class People:
name = Str()
age = Int()
def __init__(self, name, age): # name被Str类代理,age被Int类代理,
self.name = name
self.age = age
# 何地?:定义成另外一个类的类属性
# 何时?:且看下列演示
p1 = People('winnie', 18)
print('==================')
# 描述符Str的使用
p1.name = 'allen'
del p1.name
print('==================')
# 描述符Int的使用
p1.age = 18
del p1.age
print('==================')
# 我们来瞅瞅到底发生了什么
print(p1.__dict__)
print(People.__dict__)
print('==================')
# 补充
print(type(p1) == People) # type(obj)其实是查看obj是由哪个类实例化来的
print(type(p1).__dict__ == People.__dict__)
结果:
Str设置...
Int设置...
==================
Str设置...
Str删除...
==================
Int设置...
Int删除...
==================
{}
{'__module__': '__main__', 'name': <__main__.Str object at 0x052131F0>, 'age': <__main__.Int object at 0x05213250>, '__init__': <function People.__init__ at 0x052053D8>, '__dict__': <attribute '__dict__' of 'People' objects>, '__weakref__': <attribute '__weakref__' of 'People' objects>, '__doc__': None}
==================
True
True
四、_setitem_、_getitem_、_delitem_
class Foo: # Dict
def __init__(self, name):
self.name = name
def __getitem__(self, item): # item='namexxx'
print('getitem...')
return self.__dict__.get(item)
def __setitem__(self, key, value):
print('setitem...')
# print(key,value)
self.__dict__[key] = value
def __delitem__(self, key):
print('delitem...')
# print(key)
del self.__dict__[key]
obj = Foo('winnie')
print(obj.__dict__)
print('==============================')
# 查看属性:obj.属性名
print(obj['namexxx']) # obj.name
print('==============================')
# 设置属性:
# obj.sex = 'male' # 不会走setitem...
obj['sex'] = 'male'
print(obj.__dict__)
print(obj.sex)
print('==============================')
# 删除属性
# del obj.name #不会触发delitem...
del obj['name']
print(obj.__dict__)
结果:
{'name': 'winnie'}
==============================
getitem...
None
==============================
setitem...
{'name': 'winnie', 'sex': 'male'}
male
==============================
delitem...
{'sex': 'male'}
五、_str_、repr、_format_
-
str函数或者print函数调用的是obj.str()
-
repr函数或者交互式解释器调用的是obj.repr()
注意:
-
如果__str__没有被定义,那么就会使用__repr__来代替输出。
-
__str__和__repr__方法的返回值都必须是字符串。