Python API - 用于创建可选括号的模式?

时间:2011-07-05 19:31:45

标签: python function

我正在为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的结果,而不是返回可调用对象。

我在想这可能是不可行的,但我认为无论如何我都会问大师。

2 个答案:

答案 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中引起副作用。通常这在其他地方并不合理,因为它使您的应用程序很难进行调试和测试。