内容简介:Python 中有三个看上去非常相似的魔法方法:首先来看看但是, 如果你在定义类的时候实现了
Python 中有三个看上去非常相似的魔法方法: __getattribute__
, __getattr__
, __getitem___
, 就是前面这仨哥们儿了.
不同之处
首先来看看 __ getattribute__
和 __getattr__
, 这俩在一定程度上有先后调用的关系. 简单来说, 在用 .
运算符获取某个实例的属性值的时候, Python 解释器会首先调用 __getattribute__
, 如果该实例中有需要获取的属性值, 就返回属性值, 如果没有, 则会抛出 AttributeError
.
class Foo: def __init__(self, a): self.a = a def __getattribute__(self, key): print('I\'m in __getattribute__ func') return super(Foo, self).__getattribute__(key) foo = Foo(3) print(foo.a) # 访问存在的属性 print(foo.b) # 访问不存在的属性 # 执行结果如下: I'm in __getattribute__ func 3 I'm in __getattribute__ func --------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-29-1f8f708fdf11> in <module>() 16 foo = Foo(3) 17 print(foo.a) # 访问存在的属性 ---> 18 print(foo.b) # 访问不存在的属性 <ipython-input-29-1f8f708fdf11> in __getattribute__(self, key) 5 def __getattribute__(self, key): 6 print('I\'m in __getattribute__ func') ----> 7 return super(Foo, self).__getattribute__(key) 8 AttributeError: 'Foo' object has no attribute 'b' 复制代码
但是, 如果你在定义类的时候实现了 __getattr__
方法, 那么在 __getattribute__
抛出 AttributeError
后, 就会执行 __getattr__
. 当然, 如果 __getattribute__
获取到了属性值, __ getattr__
就不会被调用.
class Foo: def __init__(self, a): self.a = a def __getattribute__(self, key): print('I\'m in __getattribute__ func') return super(Foo, self).__getattribute__(key) def __getattr__(self, key): print('I\'m in __getattr__ func') return 0 foo = Foo(3) print(foo.a) # 访问存在的属性 print(foo.b) # 访问不存在的属性 # 执行结果如下: I'm in __getattribute__ func 3 I'm in __getattribute__ func I'm in __getattr__ func 0 复制代码
其实我们用 getattr(instance, key)
获取属性值的时候, 内部调用其实是和 .
运算符是一样的!
print(getattr(foo, 'a')) print(getattr(foo, 'b')) # 执行结果如下: I'm in __getattribute__ func 3 I'm in __getattribute__ func I'm in __getattr__ func 0 复制代码
接下来就是 __getitem__
了. 其实重载 __getitem__
实现了容器类, 也就是你可以像字典和列表一样, 通过 instance['key']
或者 instance[index]
获取属性值.
class Poo: def __init__(self, a): self.a = a def __getitem__(self, key): try: val = self.__getattribute__(key) except AttributeError: val = 0 return val a = Poo(3) print(a.a) print(a['a']) print(a['b']) # 执行结果如下: 3 3 0 复制代码
怎么用
知道了它们的不同处之后, 那我们该怎么用呢? 什么时候用哪个呢???
-
__getitem__
:
__getitem__
主要是用于将一个普通的类变成一个容器类, 可以通过像其他容器获取属性值一样获取自定义类的属性值 -
__getattr__
:
__getattr__
主要作用是定制化获取实例中不存在的属性后触发的动作 -
__getattribute__
:
__getattibute__
可以用于阻止获取实例中的某些敏感属性
class Count: def __init__(self,mymin,mymax): self.mymin=mymin self.mymax=mymax self.current=None def __getattribute__(self, item): if item.startswith('cur'): raise AttributeError return object.__getattribute__(self,item) # or you can use ---return super().__getattribute__(item) obj1 = Count(1,10) print(obj1.mymin) print(obj1.mymax) print(obj1.current) # 执行结果如下: 1 10 --------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-4-2c95d579e6a7> in <module>() 14 print(obj1.mymin) 15 print(obj1.mymax) ---> 16 print(obj1.current) <ipython-input-4-2c95d579e6a7> in __getattribute__(self, item) 7 def __getattribute__(self, item): 8 if item.startswith('cur'): ----> 9 raise AttributeError 10 return object.__getattribute__(self,item) 11 # or you can use ---return super().__getattribute__(item) AttributeError: 复制代码
需要注意的是, 在重载 __getattribute__
的时候, 为了防止无线递归, 我们应该调用基类的 __getattribute__
方法( object.__getattribute__(self, key)
或者 super().__getattribute__(key)
), 而不是直接通过 self.__dict__[key]
这种形式获取属性值.
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Python 最会变魔术的魔术方法,我觉得是它
- PHP几种常见魔术方法解析
- PHP反序列化入门之常见魔术方法
- 对于魔术方法 __call, __callStatic 新的认识
- 032.Python魔术方法__new__和单态模式
- 034.Python的__str__,__repr__,__bool__ ,__add__和__len__魔术方法
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Coming of Age in Second Life
Tom Boellstorff / Princeton University Press / 2008-04-21 / USD 29.95
The gap between the virtual and the physical, and its effect on the ideas of personhood and relationships, is the most interesting aspect of Boellstorff's analysis... Boellstorff's portrayal of a virt......一起来看看 《Coming of Age in Second Life》 这本书的介绍吧!
SHA 加密
SHA 加密工具
UNIX 时间戳转换
UNIX 时间戳转换