python基础-attr系列

xiaoxiao2021-02-28  46

__getattr____getattribute____setattr__Local其他

__getattr__

实例instance通过instance.name访问属性name,只有当属性name没有在实例的__dict__或它构造类的dict或基类的dict中没有找到,才会调用__getattr__。当属性name可以通过正常机制追溯到时,getattr是不会被调用的。如果在getattr(self, attr)存在通过self.attr访问属性,会出现无限递归错误。

class Foo(): c = 1 def __init__(self,name): self.name = name def __getattr__(self, item): print(item) # self.item 无限递归错误 print("__getattr__") def sing(self): print("sing") foo = Foo("safly") print(foo.__dict__) print(foo.a)

输出如下:

{'name': 'safly'} a __getattr__ None from threading import get_ident,Thread import time class Local(object): storage = {} def __setattr__(self, k, v): print("__setattr__", k,v) ident = get_ident() if ident in Local.storage: Local.storage[ident][k] = v else: Local.storage[ident] = {k: v} def __getattr__(self, k): print("__getattr__",k) ident = get_ident() return Local.storage[ident][k] obj = Local() def task(arg): obj.val = arg print(obj.val) for i in range(10): t = Thread(target=task,args=(i,)) t.start()

输出如下:

E:\python\python_sdk\python.exe "C:/Users/67334/Documents/Tencent Files/673346821/FileRecv/day123/safly.py" __setattr__ val 0 __getattr__ val 0 __setattr__ val 1 __getattr__ val 1 __setattr__ val 2 __getattr__ val 2 __setattr__ val 3 __getattr__ val 3 __setattr__ val 4 __getattr__ val 4 __setattr__ val 5 __getattr__ val 5 __setattr__ val 6 __getattr__ val 6 __setattr__ val 7 __getattr__ val 7 __setattr__ val 8 __getattr__ val 8 __setattr__ val 9 __getattr__ val 9 Process finished with exit code 0

__getattribute__

实例instance通过instance.name访问属性name,__getattribute__方法一直会被调用,无论属性name是否追溯到。如果类还定义了getattr方法,除非通过__getattribute__显式的调用它,或者getattribute方法出现AttributeError错误,否则getattr方法不会被调用了。如果在getattribute(self, attr)方法下存在通过self.attr访问属性,会出现无限递归错误。 如下所示,ClassA中定义了getattribute方法,实例insA获取属性时,都会调用getattribute返回结果,即使是访问__dict__属性

class Foo(): c = 1 def __init__(self,name): self.name = name def __getattr__(self, item): print(item) # self.item 无限递归错误 print("__getattr__") def __getattribute__(self, item): print(item) # self.item 无限递归错误 print("__getattribute__") def sing(self): print("sing") foo = Foo("safly") print(foo.__dict__) print(foo.a)

输出如下:

E:\python\python_sdk\python.exe E:/python/py_dev/python/django_dev/app08/tests.py __dict__ __getattribute__ None a __getattribute__ None Process finished with exit code 0

示例

class Foo(): c = 1 def __init__(self,name): self.name = name def __getattr__(self, item): print(item) # self.item 无限递归错误 print("__getattr__") def __getattribute__(self, item): print(item) # self.item 无限递归错误 print("__getattribute__") def sing(self): print("sing") foo = Foo("safly") print(Foo.__dict__)

输出如下:

{'__module__': '__main__', 'c': 1, '__init__': <function Foo.__init__ at 0x055919C0>, '__getattr__': <function Foo.__getattr__ at 0x05591978>, '__getattribute__': <function Foo.__getattribute__ at 0x05591930>, 'sing': <function Foo.sing at 0x05591810>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}

如下代码

class Foo(): def __init__(self,name): self.name = name def __getattr__(self, item): print("__getattr__", item) def __getattribute__(self, item): print("__getattribute__",item) raise AttributeError() foo = Foo("safly") foo.a

输出

__getattribute__ a __getattr__ a

__setattr__

如果类自定义了setattr方法,当通过实例获取属性尝试赋值时,就会调用setattr。 常规的对实例属性赋值,被赋值的属性和值会存入实例属性字典dict中。

class Foo(): def __init__(self,name): self.name = name def __setattr__(self, key, value): print("__getattr__", key, value) foo = Foo("safly") foo.a=1 Foo.b = 1

输出如下:

E:\python\python_sdk\python.exe E:/python/py_dev/python/django_dev/app08/tests.py __getattr__ name safly __getattr__ a 1

在看一个例子

class Foo(): def __init__(self,name): self.name = name def __setattr__(self, key, value): print("__getattr__", key, value) foo = Foo("safly") foo.a=1 print(foo.__dict__)

输出如下:

__getattr__ name safly __getattr__ a 1 {}

继续看示例

class Foo(): def __init__(self,name): self.name = name def __setattr__(self, key, value): print("__getattr__", key, value) self.__dict__[key] = value foo = Foo("safly") foo.a=1 print(foo.__dict__) print(Foo.__dict__)

输出如下:

E:\python\python_sdk\python.exe E:/python/py_dev/python/s8day93/app01/tests.py getattr name safly getattr a 1 {‘name’: ‘safly’, ‘a’: 1}

{'__module__': '__main__', '__init__': <function Foo.__init__ at 0x058129C0>, '__setattr__': <function Foo.__setattr__ at 0x05812978>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}

Local

try: from greenlet import getcurrent as get_ident except Exception as e: from threading import get_ident from threading import Thread import time class Local(object): def __init__(self): object.__setattr__(self, 'storage', {}) def __setattr__(self, k, v): ident = get_ident() if ident in self.storage: self.storage[ident][k] = v else: self.storage[ident] = {k: v} def __getattr__(self, k): ident = get_ident() return self.storage[ident][k] obj = Local() def task(arg): obj.val = arg obj.xxx = arg print(obj.val) for i in range(10): t = Thread(target=task, args=(i,)) t.start()

其他

class MyType(type): def __init__(self,*args,**kwargs): print('创建类之前') super(MyType,self).__init__(*args,**kwargs) print('创建类之后') class Foo(object,metaclass=MyType): # 当前类,由type类创建。 CITY = "bj" def func(self, x): return x + 1 class Bar(Foo): pass

输出如下:

创建类之前 创建类之后 创建类之前 创建类之后 class MyType(type): def __init__(self,*args,**kwargs): print('创建类之前') super(MyType,self).__init__(*args,**kwargs) print('创建类之后') def with_metaclass(arg): return MyType('Base',(arg,),{}) # class Base(object,metaclass=MyType): pass class Foo(with_metaclass(object)): CITY = "bj" def func(self, x): return x + 1

输出如下:

创建类之前 创建类之后 创建类之前 创建类之后
转载请注明原文地址: https://www.6miu.com/read-2614417.html

最新回复(0)