没有调用元类的__getattr__

时间:2014-07-01 07:44:47

标签: python python-2.7

正如标题所说。似乎无论我做什么,__getattr__都不会被调用。我也试过它(荒谬,我知道),可以预见没有反应。好像__getattr__在元类中被禁止了。

我很欣赏任何有关此文档的指针。

代码:

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

感谢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)

1 个答案:

答案 0 :(得分:4)

作为documented,仅在属性不存在时才调用__getattr__。由于您的类具有field属性,因此会阻止__getattr__。如果您确实要拦截所有属性访问权限,可以使用__getattribute__,尽管从您的示例中不清楚为什么需要执行此操作。请注意,这与元类无关;如果你创建了一个普通类的实例并给它一些属性,你会看到相同的行为。

即使假设您使用了__getattribute__,因此在属性存在时调用它,您的实现没有多大意义。在__getattr__内,您尝试获取self.field的值。但是如果首先调用__getattribute__,则会再次调用此访问权限,创建无限递归:为了获得self.field,它必须再次调用__getattribute__尝试获取self.field,再次调用__getattribute__等。请参阅__getattribute__ {{1}}了解如何解决此问题。