在Python中,我如何使用属性作为属性和方法/可调用?

时间:2011-10-07 21:21:35

标签: python

这是一个实验。我对支持这两种语法的API感兴趣:

obj.thing

- >返回默认值

obj.thing(2, 'a')

- >返回从* args和** kwargs

派生的值

thing”在两种情况下都是相同的对象;我希望调用thing是可选的(或隐含的,如果之后没有(),那么。)

我试过覆盖__repr__,但这只是对象本身的直观表示,<​​em>实际返回的是包含对象的实例(这里是'obj')。所以,没有好处。

我认为在一个可调用的对象上会设置一个属性(不管它是一个实例,一个def,还是只是对象的__call__),它有足够的默认值:

class CallableDefault(object):
    __call__(self, num=3, letter="z"):
        return letter * num

class DumbObject(object):
    foo = CallableDefault()

obj = DumbObject()

所以,理想情况下,单独执行obj会返回“zzz”,但也可以执行obj(7,'a')并获取'aaaaaaa'。

我认为装饰者可能是这样做的方式,但我对装饰者不太满意。可以覆盖包含类的getattr()调用,但这意味着它必须位于支持此功能的包含类中。

2 个答案:

答案 0 :(得分:3)

您所描述的内容可行,但请注意,现在该属性的值被限制为CallableDefault类的对象。这可能不会非常有用。

我强烈建议您不要尝试这样做。首先,你花了很多时间试图欺骗Python做一些它不想做的事情。另一方面,API的用户会感到困惑,因为它的行为与他们见过的所有其他Python代码的行为不同。他们会感到困惑。

编写一个在Python中自然运行的Python API。

答案 1 :(得分:3)

当你做任何一件事时会发生什么

obj.thing

obj.thing(2, 'a')

是Python在thing上寻找obj;一旦它有thing,它就会返回它(上面的第一种情况),或者用参数调用它(第二种情况) - 关键点是调用直到之后才发生检索属性 - 并且包含的​​类无法知道它返回的东西是否会被调用。

你可以为这种方式使用的每种类型添加__call__方法,但这种方式就是疯狂。

<强>更新

好吧,只要你对精神错乱感到满意,你就可以尝试这样的事情:

class CallableStr(str):
    def __call__(self, num, letter):
        return num*letter

class CallableInt(int):
    def __call__(self, num, pow):
        return num ** pow

class Tester(object):
    wierd = CallableStr('zzz')
    big = CallableInt(3)

t = Tester()
print repr(t.wierd)
print repr(t.wierd(7, 'a'))
print repr(t.big)
print repr(t.big(2, 16))

关于这个神奇物体的一个好处是,当你在计算(或调用)中使用它时,它会很快变为正常:

print type(t.big), type(t.big + 3), t.big + 3
print type(t.big), type(t.big(2, 3) + 9), t.big(2, 3) + 9

导致

<class '__main__.CallableInt'> <type 'int'> 6
<class '__main__.CallableInt'> <type 'int'> 17