简体   繁体   English

元类的__getattr__没有被调用

[英]__getattr__ of meta class not being called

As the title says. 如标题所示。 It seems no matter what I do, __getattr__ will not be called. 看来无论我做什么,都不会调用__getattr__ I also tried it for instance (absurd, I know), with predictably no response. 例如,我也尝试过(很奇怪,我知道),但是没有反应。 As if __getattr__ was banned in meta classes. 好像__getattr__在元类__getattr__被禁止。

I'd appreciate any pointer to documentation about this. 我会很高兴有任何有关此文档的指针。

The code: 编码:

class PreinsertMeta(type):

    def resolvedField(self):
        if isinstance(self.field, basestring):
            tbl, fld = self.field.split(".")
            self.field = (tbl, fld)
        return self.field

    Field = property(resolvedField)

    def __getattr__(self, attrname):
        if attrname == "field":
            if isinstance(self.field, basestring):
                tbl, fld = self.field.split(".")
                self.field = (tbl, fld)
            return self.field
        else:
            return super(PreinsertMeta, self).__getattr__(attrname)

    def __setattr__(self, attrname, value):
        super(PreinsertMeta, self).__setattr__(attrname, value)


class Test(object):
    __metaclass__ = PreinsertMeta
    field = "test.field"

print Test.field  # Should already print the tuple
Test.field = "another.field"  # __setattr__ gets called nicely
print Test.field  # Again with the string?
print Test.Field  # note the capital 'F', this actually calls resolvedField() and prints the tuple

Thanks to BrenBarn, here's the final working implementation: 感谢BrenBarn,这是最终的工作实现:

class PreinsertMeta(type):

    def __getattribute__(self, attrname):
        if attrname == "field" and isinstance(object.__getattribute__(self, attrname), basestring):
            tbl, fld = object.__getattribute__(self, attrname).split(".")
            self.field = (tbl, fld)
        return object.__getattribute__(self, attrname)

As documented , __getattr__ is only called if the attribute does not exist. 文档所述 ,仅在属性不存在时才调用__getattr__ Since your class has a field attribute, that blocks __getattr__ . 由于您的课程有一个field属性,因此会阻塞__getattr__ You can use __getattribute__ if you really want to intercept all attribute access, although it's not clear from your example why you need to do this. 如果您确实想拦截所有属性访问,则可以使用__getattribute__ ,尽管从示例中尚不清楚为什么需要这样做。 Note that this has nothing to do with metaclasses; 注意,这与元类无关。 you would see the same behavior if you created an instance of an ordinary class and gave it some attribute. 如果创建一个普通类的实例并为其赋予一些属性,您将看到相同的行为。

Even assuming you used __getattribute__ , so it was called when the attribute exists, your implementation doesn't make much sense. 即使假设您使用了__getattribute__ ,当属性存在时也被调用了,您的实现也没有多大意义。 Inside __getattr__ you try to get a value for self.field . __getattr__内部,您尝试获取self.field的值。 But if __getattribute__ was called in the first place, it will be called again for this access, creating an infinite recursion: in order to get self.field , it has to call __getattribute__ , which again tries to get self.field , which again calls __getattribute__ , etc. See the documentation for __getattribute__ for how to get around this. 但是,如果首先调用__getattribute__ ,则将为此访问再次调用__getattribute__ ,从而创建无限递归:为了获取self.field ,它必须调用__getattribute__ ,它再次尝试获取self.field ,然后再次调用__getattribute__等见文档__getattribute__如何来解决这个问题。

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

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