如何使一个类的成员既是字段又是方法?

时间:2016-02-04 03:01:26

标签: python

我有一个扩展B的A类,B有一个方法count()。现在我想允许用户同时调用A.count和A.count()。 A.count表示count是A的一个字段,而A.count()表示它是从B派生的方法。

2 个答案:

答案 0 :(得分:2)

这在Python中是不可能的,这就是原因:

您始终可以为变量分配方法(或实际上是任何函数)并稍后调用它。

hello = some_function
hello()

在语义上与

相同
some_function()

如果您的班级A的对象名为x:

,会发生什么
x = A()
foo = x.count
foo()

你能做到这一点的唯一方法是在x.count中存储一个可调用的特殊对象,并将其变为例如以这种方式使用时的整数,但这很糟糕,而且实际根据规范工作。

答案 1 :(得分:0)

正如我所说,正如其他答案所说,这并非完全不可能。让我们看一个教学示例:

class A(object):
    class COUNT(object):
        __val = 12345

        def __call__(self, *args, **kwargs):
            return self.__val

        def __getattr__(self, item):
            return self.__val

        def __str__(self):
            return str(self.__val)

    count = COUNT()

if __name__ == '__main__':
    your_inst = A()

    print(your_inst.count)
    # outputs: 12345
    print(your_inst.count())
    # outputs: 12345

正如您可能注意到的,您需要实现一系列事情来实现这种行为。首先,您的类需要实现属性count而不是您想要的值类型,而是作为另一个类的实例,除了其他事项之外(通过duck实现该类的行为)键入,作为你想要的类型__call__方法,它应该返回与你类__getattr__相同的方式,这样,公共属性count将作为可调用的方式回答{{{ 1}})或者,如你所说,一个字段(your_inst.count()),同样的方式。

顺便说一句,我不知道以下内容是否清楚,但它可能会帮助您理解为什么它不像人们认为的那样微不足道your_inst.count和{ {1}}的行为方式相同:

count

count()调用class A(object): def count(self): return 123 if __name__ == '__main__': a = A() print(type(a.count)) # outputs: <class 'method'> print(type(a.count())) # outputs: <class 'int'> .来获取项a__getattr__将返回指向该函数的引用(python's function are first class objects),第二个将执行相同的操作,但括号将从count调用a.count方法。