我正在为Python库设计API,并且遇到了我认为我的想象力可能超过Python相当大的能力的情况。
(我想向任何可能因我的设计的Ruby-ness冒犯的Pythonistas道歉)
基本上,有一个类有几个方法,每个方法返回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
的结果,而不是返回可调用对象。
我在想这可能是不可行的,但我认为无论如何我都会问大师。
答案 0 :(得分:4)
我认为你想要这样做是疯了。你有什么理由?拿参数的方法怎么样? (见下面的例子。)
如果您使用__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
帮自己一个忙,不要走这条路。
答案 1 :(得分:3)
如果没有括号,您可以引用该函数,您可以使用它们调用它的结果。这是Python语法的基本部分(这种一致性是一件好事!)。
你总是可以使用Python的property
函数(或相关的装饰器)来使方法在引擎盖下工作,作为一个属性的别名,它将实现你想要的。但是,这表明你正在编写非常副作用的代码,这是一个坏主意。
这样的链接在jQuery中很流行,因为jQuery的唯一目的是在DOM中引起副作用。通常这在其他地方并不合理,因为它使您的应用程序很难进行调试和测试。