我正在为Python库设计API,并且遇到了一种情况,我认为我的想象力可能超过了Python的相当大的能力。
(我想向所有可能被我的ruby设计冒犯的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
的结果而不带参数,而不是返回一个可调用的对象。
我想这可能是不可行的,但我想我应该问大师。
我认为你想做这件事是疯了。你有什么理由?接受参数的方法呢?(见下面的例子)
如果你使用__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
别再这样下去了。
没有括号,您就得到了对函数的引用,有了括号,您就得到了函数调用的结果。这是Python语法的基本部分(这种一致性是一件好事!)。
你总是可以使用Python的property
函数(或相关的装饰器)使一个方法作为一个属性的别名在底层工作,从而达到你想要的效果。然而,这表明你正在编写副作用很大的代码,这是一个坏主意。