Python API -创建可选圆括号的模式



我正在为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函数(或相关的装饰器)使一个方法作为一个属性的别名在底层工作,从而达到你想要的效果。然而,这表明你正在编写副作用很大的代码,这是一个坏主意。

像这样的链接在jQuery中很流行,因为jQuery的唯一目的是在DOM中引起副作用。通常这在其他地方是不明智的,因为它使您的应用程序很难调试和测试。

最新更新