__getattr__与__getattribute__之间的区别

我想了解何时使用__getattr____getattribute__ 。 文档中提到__getattribute__适用于新风格的类。 什么是新式课程?

__getattr____getattribute__之间的一个主要区别是,只有在找不到常用的属性时,才会调用__getattr__ 。 对缺less的属性执行回退是很好的,可能是你想要的两个之一。

在查看对象上的实际属性之前调用__getattribute__ ,因此可能会很难正确执行。 你可以很容易地在无限的recursion结束。

新风格的类从object派生,旧风格的类是Python 2.x中没有明确的基类的类。 但是当在__getattr____getattribute__之间进行select时,旧式和新式类别之间的区别并不重要。

你几乎肯定希望__getattr__

让我们看看__getattr____getattribute__魔术方法的一些简单例子。

__getattr__

每当您请求尚未定义的属性时,Python将调用__getattr__方法。 在下面的例子中,我的类Count没有__getattr__方法。 现在主要当我尝试访问obj1.myminobj1.mymax属性一切工作正常。 但是,当我尝试访问obj1.mycurrent属性 – Python给我AttributeError: 'Count' object has no attribute 'mycurrent'

 class Count(): def __init__(self,mymin,mymax): self.mymin=mymin self.mymax=mymax obj1 = Count(1,10) print(obj1.mymin) print(obj1.mymax) print(obj1.mycurrent) --> AttributeError: 'Count' object has no attribute 'mycurrent' 

现在我的类Count__getattr__方法。 现在,当我尝试访问obj1.mycurrent属性 – python返回我无论我已经实现在__getattr__方法。 在我的示例中,每当我尝试调用一个不存在的属性时,python都会创build该属性并将其设置为整数值0。

 class Count: def __init__(self,mymin,mymax): self.mymin=mymin self.mymax=mymax def __getattr__(self, item): self.__dict__[item]=0 return 0 obj1 = Count(1,10) print(obj1.mymin) print(obj1.mymax) print(obj1.mycurrent1) 

__getattribute__

现在让我们看看__getattribute__方法。 如果你的类中有__getattribute__方法,python会为每个属性调用这个方法,不pipe它是否存在。 那么为什么我们需要__getattribute__方法? 一个很好的理由是,您可以防止访问属性并使其更安全,如以下示例所示。

每当有人试图访问我的属性,以子string“cur” python开始引发AttributeErrorexception。 否则,它返回该属性。

 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) 

重要提示:为了避免__getattribute__方法中的无限recursion,其实现应始终调用具有相同名称的基类方法来访问它所需的任何属性。 例如: object.__getattribute__(self, name)super().__getattribute__(item)而不是self.__dict__[item]

重要

如果您的类同时包含getattrgetattribute魔术方法,则首先调用__getattribute__ 。 但是,如果__getattribute__引发AttributeErrorexception,则该exception将被忽略, __getattr__方法将被调用。 看下面的例子:

 class Count(object): def __init__(self,mymin,mymax): self.mymin=mymin self.mymax=mymax self.current=None def __getattr__(self, item): self.__dict__[item]=0 return 0 def __getattribute__(self, item): if item.startswith('cur'): raise AttributeError return object.__getattribute__(self,item) # or you can use ---return super().__getattribute__(item) # note this class subclass object obj1 = Count(1,10) print(obj1.mymin) print(obj1.mymax) print(obj1.current) 

这只是一个基于@Ned Batchelder解释的例子。

__getattr__例子:

 class Foo(object): def __getattr__(self, attr): print "looking up", attr value = 42 self.__dict__[attr] = value return value f = Foo() print fx #output >>> looking up x 42 fx = 3 print fx #output >>> 3 print ('__getattr__ sets a default value if undefeined OR __getattr__ to define how to handle attributes that are not found') 

如果__getattribute__使用相同的例子,您将得到>>> RuntimeError: maximum recursion depth exceeded while calling a Python object

新样式类从objectinheritance,或从另一个新样式类inheritance:

 class SomeObject(object): pass class SubObject(SomeObject): pass 

旧式课堂不会:

 class SomeObject: pass 

这仅适用于Python 2 – 在Python 3中,以上所有内容都将创build新样式的类。

请参阅9.类 (Python教程), NewClassVsClassicClass和Python中的旧风格和新风格类有什么区别? 了解详情。

新式类是直接或间接地将“对象”子类化的类。 除了__init__之外,他们有一个__new__类方法,并且有一些更合理的低级行为。

通常情况下,你会想覆盖__getattr__ (如果你重写),否则你会很难在你的方法中支持“self.foo”语法。

额外信息: http : //www.devx.com/opensource/Article/31482/0/page/4