2012-08-03 89 views
0

Python有一个神奇的__getattr__方法,它允许将返回自定义值:实施Class.magic_class_method

class A(object): 
    def __getattr__(self, name): 
     return name 

B = A() 
print B.foo # 'foo' 

但是,调用A.foo有没有类似的效果,因为A不是一个实例。

Using metaclasses,谷歌应用程序引擎提出了在实例化这个错误:

File "/base/python27_runtime/python27_lib/versions/1/google/appengine/ext/db/__init__.py", line 913, in __init__ 
key_name.__class__.__name__) 
    BadKeyError: Name must be string type, not tuple 

假设引用的问题是正确实施,有什么其他方法可以在魔法类__getattr__实施?

回答

2

元类的解决方案应该工作,这里有一个例子:

class GetAttrMeta(type): 
    def __getattr__(self, name): 
     return name 

class A(object): 
    __metaclass__ = GetAttrMeta 

print A.foo # 'foo' 

或者使用Python 3.X:

class GetAttrMeta(type): 
    def __getattr__(self, name): 
     return name 

class A(object, metaclass=GetAttrMeta): 
    pass 

print(A.foo) # 'foo' 
+0

这被试过(如引用的问题3155436),但Google的'db.Model'对象,我确实使用'class A (db.Model):',与元类扩展'type'冲突,导致上面显示的错误。 – Brian 2012-08-04 16:36:37

+0

您应该尝试检查'db.Model'是否具有与类型不同的元类 - 并扩展它而不是'type'。 – jsbueno 2012-09-07 22:42:21

1

不知道这是否回答你的问题,但也许结帐property descriptors ..

class RevealAccess(object): 
"""A data descriptor that sets and returns values 
    normally and prints a message logging their access. 
""" 

def __init__(self, initval=None, name='var'): 
    self.val = initval 
    self.name = name 

def __get__(self, obj, objtype): 
    print 'Retrieving', self.name 
    return self.val 

def __set__(self, obj, val): 
    print 'Updating' , self.name 
    self.val = val 

>>> class MyClass(object): 
    x = RevealAccess(10, 'var "x"') 
    y = 5 
>>> MyClass.x 
Retrieving var "x" 
10 
>>> MyClass().x 
Retrieving var "x" 
10 
>>> 
>>> m = MyClass() 
>>> m.x 
Retrieving var "x" 
10 
>>> m.x = 20 
Updating var "x" 
>>> m.x 
Retrieving var "x" 
20 
>>> m.y 
5