【问题标题】:How to make one member of class to be both field and method?如何使类的一个成员既是字段又是方法?
【发布时间】:2016-02-04 03:01:25
【问题描述】:

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

【问题讨论】:

  • 你需要在你的类 getattr 上实现一些东西,但实际上,我看不到一个很好的用例来处理那个看起来很糟糕的场景 ant设计选择。无论如何,你可以看看那个问题stackoverflow.com/questions/20120983/…,它可能会对你的情况有所帮助

标签: python


【解决方案1】:

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

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

hello = some_function
hello()

在语义上与

相同
some_function()

那么如果你有一个名为 x 的类 A 的对象会发生什么:

x = A()
foo = x.count
foo()

您可以做到这一点的唯一方法是在x.count 中存储一个特殊对象,该对象是可调用的,也可以变成例如以这种方式使用时是一个整数,但这很糟糕,并且 实际上 不符合规范。

【讨论】:

    【解决方案2】:

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

    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,而不是作为您想要的值类型,而是作为另一个类的实例,除其他外,它必须实现(为了使该类行为,通过鸭子类型,作为您想要的类型)__call__ 方法,它应该返回与您相同的类__getattr__,这样,公共属性count 将作为可调用的(your_inst.count())回答,或者,正如您所说,一个字段 (your_inst.count),方法相同。

    顺便说一句,我不知道您是否清楚以下内容,但它可以帮助您理解为什么它不像人们认为的那样微不足道,使countcount()行为方式相同:

    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__ 以获取项目counta.count 会将引用返回到该函数 (python's function are first class objects),第二个函数也会这样做,但括号将调用 a.count 中的 __call__ 方法。

    【讨论】:

      猜你喜欢
      • 2018-07-26
      • 1970-01-01
      • 2012-02-10
      • 1970-01-01
      • 2017-07-09
      • 2019-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多