2014-09-12 59 views
6

在给定的情况下,选择在给定班级中实施哪些规则,有哪些一般的经验法则?什么是决定__get__,__getattr__和__getattribute__之间的一些经验法则?

我已阅读文档,并了解它们之间的区别。相反,我正在寻找关于如何通过更好地注意到更细微的机会来使用它们以及何时使用它们来最佳地将其用法集成到我的工作流程中的指导。那种事。有问题的方法是(据我所知):

## fallback 
__getattr__ 
__setattr__ 
__delattr__ 

## full control 
__getattribute__ 
##(no __setattribute__ ? What's the deal there?) 

## (the descriptor protocol) 
__get__ 
__set__ 
__delete__ 
+1

给封闭选民:IMX,学习者的问题如“我如何决定X和Y?”或者“X和Y有什么区别?”真的有两个问题 - “X的预期目的是什么?”和“Y的预期目的是什么?”也许最好单独问问他们,但在目前的情况下,两者都不是“太宽泛”的海事组织,在这里不同的魔法方法至少有一些联系。 – 2014-09-12 12:55:27

回答

5

__setattribute__不存在,因为__setattr__总是调用__getattr__仅在f.x(如果通过正常通道(由__getattribute__提供,因此函数总是被调用)失败)下调用。

描述符协议与其他协议略有正交。鉴于

class Foo(object): 
    def __init__(self): 
     self.x = 5 

f = Foo() 

以下为真:

  • f.x将调用f.__getattribute__('x'),如果它被定义。
  • f.x如果定义了它将不会调用f.__getattr__('x')
  • f.y将调用f.__getattr__('y')如果它被定义,否则 f.__getattribute__('y')如果被定义它

该描述符由调用的属性,而不是对的属性。那就是:

class MyDescriptor(object): 
    def __get__(...): 
     pass 
    def __set__(...): 
     pass 

class Foo(object): 
    x = MyDescriptor() 

f = Foo() 

现在,f.x会导致type(f).__dict__['x'].__get__被调用,并f.x = 3会打电话type(f).__dict__['x'].__set__(3)

也就是说,Foo.__getattr__Foo.__getattribute__将被用于查找f.x引用;一旦你有,f.x产生type(f.x).__get__()如果定义的结果,和f.x = y调用f.x.__set__(y)如果定义。

(以__get____set__以上呼叫只能近似正确的,因为我已经离开了哪些参数__get____set__实际收到的细节,但是这应该是足以说明__get____getattr[ibute]__之间的区别。)

换言之,如果MyDescriptor没有定义__get__,那么f.x只会返回MyDescriptor的实例。

+0

哦..我现在看到了。感谢让这些连接更清晰。有什么办法可以让'x = 3'(并且符合方法所附的对象) – Inversus 2014-09-12 13:07:18

+0

*(没有限定... – Inversus 2014-09-14 02:46:47

+0

但是,现在我已经玩了一下了,我认为__getattribute__是正确的我的用例是当它在一个集合中时,所以我认为这会起作用,谢谢 – Inversus 2014-09-14 02:48:47

6

对于__getattr__ VS __getattribute__,例如参见Difference between __getattr__ vs __getattribute__

__get__没有真正相关。我要从这里引用official documentation for the descriptor protocol

属性访问的默认行为是从对象的字典中获取,设置或删除属性。例如,a.x的查找链从a.__dict__['x']开始,然后是type(a).__dict__['x'],并且继续通过不包含元类的type(a)的基类。如果查找的值是定义其中一个描述符方法的对象,则Python可以覆盖默认行为并调用描述符方法。在优先链中发生这种情况取决于定义了哪些描述符方法。

__get__的目的是控制什么发生一次a.x通过该“查找链”中找到(例如,创建方法的对象而不是返回经由type(a).__dict__['x']发现纯函数); __getattr____getattribute__的目的是改变查找链本身。

没有__setattribute__,因为只有一种方式,实际上设置了一个对象的属性,在引擎盖下。当设置属性时,您可能想要“神奇地”发生其他事情;但__setattr__涵盖。 __setattribute__不可能提供__setattr__尚未提供的任何功能。

但是 - 在绝大多数情况下,最好的答案是甚至没有想到使用任何这些。首先看更高层次的抽象,如property s,classmethod s和staticmethod s。如果你认为你需要像这样的专门工具,并且不能为自己弄明白,那么你的想法很可能错了;但无论如何,最好在这种情况下发布更具体的问题。