好吧,我遇到了一些问题,我不太清楚为什么会出现问题。我想要做的是允许通过snake_case中的snake_case或camelCase访问对象上的属性。我认为__getattr__
是正确的方法,但显然我错了,我不是前
所以这是我简化的实现。在这种情况下,无论您访问哪个属性,我都希望返回foo.x
。
class Foo(object):
def __init__(self, x):
self.x = x
def __getattr__(self, name):
if hasattr(self, name):
return getattr(self, name)
elif hasattr(self, 'x'):
return getattr(self, 'x')
else:
raise AttributeError, n
现在,如果我这样做:
f = Foo('myX')
f.x
# => "myX"
但是,我不明白为什么:
f.y
永远循环。有趣的是,当我将print "__getattr__ called with : %s" % name
放在__getattr__
的第一行时,似乎在调用f.y
时,getattr(self, 'x')
行实际上会被调用,但之后它就不会被调用看起来getattr实际上是用'x'实际调用的,__getattr__
仍然说是用“y”调用它。
我一直在四处寻找,我认为这与我对getattr
的工作方式的误解有关。你们都必须指出的任何建议或文件都会非常有益。提前谢谢。
答案 0 :(得分:4)
hasattr()
实现为对getattr()
的调用,如果引发异常则返回False
。
__getattr__
;这是一个后备。在hasattr()
中使用__getattr__
完全没有意义。
由于存在f.x
,因此永远不会调用Foo.__getattr__
。 f.y
不存在,因此会调用Foo.__getattr__(f, 'y')
,调用hasattr(f, 'y')
调用调用getattr(f, 'y')
的{{1}},因为Foo.__getattr__(f, 'y')
属性没有&#39} ; t存在等等。
来自object.__getatt__()
documentation:
当属性查找未在通常位置找到该属性时调用(即,它不是实例属性,也不在类树中找到自己)。
来自hasattr()
function documentation:
(这是通过调用
y
并查看是否引发异常来实现的。)
答案 1 :(得分:0)
我要发布我在开头谈到的我的snake / camelCase问题的工作实现。查看@ Martijn的答案,了解为什么这种方法有效并且旧的方法失败。
class Foo(object):
def __init__(self, x):
self.x = x
def __getattr__(self, name):
#if hasattr(self, name) # As Martijn pointed out, this call is completely
# getattr(self, name) # useless in this context because the only reason
# you are even in __getattr__ is because self
# does not have the attribute. This call is what
# was causing the infinite loop.
components = name.split('_')
camel_case = components[0] + "".join(x.title() for x in components[1:])
if hasattr(self, camel_case):
return getattr(self, camel_case)
else:
raise AttributeError, name