我正在为 Python 库设计 API,并且遇到了一种情况,我认为我的想象力可能已经超过了 Python 的相当大的能力。
(我想向任何可能被我设计的 Ruby-ness 冒犯的 Pythonista 道歉)
基本上,有一个带有几个方法的类,每个方法都返回 self,这样它们就可以链接在一起。所以:
>>> a = MyKlass()
>>> b = a.method_one()
>>> c = b.method_two()
会和
一样>>> a = MyKlass()
>>> c = a.method_one().method_two()
我的问题是是否可以将括号设为可选。我已经了解了一些关于使用 __getattr__ 和 __call__ 来操作可调用对象的知识,但是还没有能够完全实现它。现在,我让类的 __getattr__ 检查属性,然后确定 name 是方法还是属性(或者更准确地说,它是否可调用) .
我的问题是,如果它是可调用的,我需要 __getattr__ 来做这样的事情:
>>> class MyKlass(object):
>>> def __getattr__(self, name):
>>> # pseudocode, you get the idea...
>>> if name is callable:
>>> def callme(*args, **kwds):
>>> # do stuff
>>> return callme
>>> else:
>>> # just return the attribute
所以它返回一个可调用对象。不过,这意味着我无法将括号设为可选,因为可调用对象将被返回,但从未被调用:
>>> a = MyKlass()
>>> c = a.method_one.method_two # AttributeError, since a bound function object does not have attribute "method_two"
我想到的唯一方法是能够在代码中“向前看”并确定 name 后面是否有括号。然后,如果 name 是可调用但未被调用的,我可以返回调用 name 而不带参数的结果,而不是返回可调用对象。
我在想这可能是不可行的,但我想无论如何我都会问问大师。
请您参考如下方法:
我认为您想要这样做是疯了。你有什么理由?带参数的方法呢? (参见下面的示例。)
如果您使用 __getattribute__ 而不是 __getattr__,它似乎适用于没有参数的方法。
工作示例:
class Test(object):
def __getattribute__(self, name):
attr = super(Test, self).__getattribute__(name)
if callable(attr):
return attr()
return attr
def f(self):
print 'f'
return self
def g(self):
print 'g'
return self
def h(self, x):
print x
return self
t = Test()
t.f.g # Works fine
t.f().g # Fails - the parens aren't optional, they must be left off now
t.f.g.h(1) # Fails - unable to provide an argument
要绕过参数问题,您可以检查函数并仅在它不接受任何参数(self 除外)时才调用它。请参阅:http://docs.python.org/library/inspect.html
帮自己一个忙,不要再走这条路了。
