简体   繁体   English

为什么getattr()无法像我认为的那样工作? 我认为这段代码应该打印'sss'

[英]Why is getattr() not working like I think it should? I think this code should print 'sss'

the next is my code: 接下来是我的代码:

class foo:
    def __init__(self):
        self.a = "a"
    def __getattr__(self,x,defalut):
        if x in self:
            return x
        else:return defalut

a=foo()
print getattr(a,'b','sss')

i know the __getattr__ must be 2 argument,but i want to get a default attribute if the attribute is no being. 我知道__getattr__必须是2个参数,但是如果该属性不存在,我想获得一个默认属性。

how can i get it, thanks 我该如何获得,谢谢


and

i found if defined __setattr__ ,my next code is also can't run 我发现如果定义了__setattr__ ,我的下一个代码也无法运行

class foo:
    def __init__(self):
        self.a={}
    def __setattr__(self,name,value):
            self.a[name]=value

a=foo()#error ,why

hi alex, i changed your example: 您好亚历克斯,我改变了你的例子:

class foo(object):
    def __init__(self):
        self.a = {'a': 'boh'}
    def __getattr__(self, x):
        if x in self.a:
            return self.a[x]
        raise AttributeError

a=foo()
print getattr(a,'a','sss')

it print {'a': 'boh'},not 'boh' i think it will print self.a not self.a['a'], This is obviously not want to see 它打印{'a':'boh'},而不是'boh'我认为它将打印self.a不是self.a ['a'],这显然是不想看到的

why ,and Is there any way to avoid it 为什么,还有什么办法可以避免它

You are confusing the getattr built-in function, which retrieves some attribute binding of an object dynamically (by name), at runtime, and the __getattr__ method, which is invoked when you access some missing attribute of an object. 您会混淆getattr内置函数和__getattr__方法,该函数在运行时动态(按名称)检索对象的某些属性绑定,而__getattr__方法在访问对象的某些缺少属性时会被调用。

You can't ask 你不能问

if x in self:

from within __getattr__ , because the in operator will cause __getattr__ to be invoked, leading to infinite recursion. __getattr__内部进行,因为in运算符将导致__getattr__被调用,从而导致无限递归。

If you simply want to have undefined attributes all be defined as some value, then 如果您只是想将所有未定义的属性都定义为某个值,那么

def __getattr__(self, ignored):
    return "Bob Dobbs"

Your problem number one: you're defining an old-style class (we know you're on Python 2.something, even though you don't tell us, because you're using print as a keyword;-). 问题一:您正在定义一个老式的类(我们知道您使用的是Python2。即使您不告诉我们,因为您使用print作为关键字;-)。 In Python 2: 在Python 2中:

class foo:

means you're defining an old-style, aka legacy, class, whose behavior can be rather quirky at times. 表示您正在定义一个旧式的(又名“旧式”类),其行为有时可能很古怪。 Never do that -- there's no good reason! 永远不要那样做-没有充分的理由! The old-style classes exist only for compatibility with old legacy code that relies on their quirks (and were finally abolished in Python 3). 存在旧类仅是为了与依赖于其怪癖的旧遗留代码兼容(并最终在Python 3中被废除了)。 Use new style classes instead: 改用样式类:

class foo(object):

and then the check if x in self: will not cause a recursive __getattr__ call. 然后检查if x in self:是否不会导致递归__getattr__调用。 It will however cause a failure anyway, because your class does not define a __contains__ method and therefore you cannot check if x is contained in an instance of that class. 但是无论如何它都会导致失败,因为您的类未定义__contains__方法,因此您无法检查x是否包含在该类的实例中。

If what you're trying to do is whether x is defined in the instance dict of self , don't bother: __getattr__ doesn't even get called in that case -- it's only called when the attribute is not otherwise found in self . 如果你正在尝试做的是是否x实例字典定义self ,不要打扰: __getattr__甚至不被调用在这种情况下-当属性以其他方式找到这只是所谓的self

To support three-arguments calls to the getattr built-in, just raise AttributeError in your __getattr__ method if necessary (just as would happen if you had no __getattr__ method at all), and the built-in will do its job (it's the built-in 's job to intercept such cases and return the default if provided). 要支持对内置getattr三个参数的调用,只需在必要时在__getattr__方法中raise AttributeError (就像根本没有__getattr__方法时发生的那样),并且内置__getattr__将完成其工作(即内置-in的工作来拦截此类情况并返回默认值(如果提供)。 That's the reason one never ever calls special methods such as __getattr__ directly but rather uses built-ins and operators which internally call them -- the built-ins and operators provide substantial added value. 这就是为什么从不直接调用诸如__getattr__特殊方法,而是使用内部调用它们的内置函数和运算符的原因-内置函数和运算符提供了可观的附加值。

So to give an example which makes somewhat sense: 因此,举个有意义的例子:

class foo(object):
    def __init__(self):
        self.blah = {'a': 'boh'}
    def __getattr__(self, x):
        if x in self.blah:
            return self.blah[x]
        raise AttributeError

a=foo()
print getattr(a,'b','sss')

This prints sss , as desired. 根据需要打印sss

If you add a __setattr__ method, that one intercepts every attempt to set attributes on self -- including self.blah = whatever. 如果添加__setattr__方法,则方法拦截对self设置属性的所有尝试-包括self.blah =任意。 So -- when you need to bypass the very __setattr__ you're defining -- you must use a different approach. 因此,当您需要绕过要定义的__setattr__ ,必须使用其他方法。 For example: 例如:

class foo(object):
    def __init__(self):
        self.__dict__['blah'] = {}
    def __setattr__(self, name, value):
        self.blah[name] = value
    def __getattr__(self, x):
        if x in self.blah:
            return self.blah[x]
        raise AttributeError

a=foo()
print getattr(a,'b','sss')

This also prints sss . 这也会打印sss Instead of 代替

        self.__dict__['blah'] = {}

you could also use 您也可以使用

        object.__setattr__(self, 'blah', {})

Such "upcalls to the superclass's implementation" (which you could also obtain via the super built-in) are one of the rare exceptions to the rules "don't call special methods directly, call the built-in or use the operator instead" -- here, you want to specifically bypass the normal behavior, so the explicit special-method call is a possibility. 这样的“对超类的实现的调用”(您也可以通过super内置实现获取)是“不直接调用特殊方法,调用内置方法或使用运算符代替”规则的罕见例外之一。 -在这里,您要专门绕过正常行为,因此有可能进行显式的特殊方法调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM