【问题标题】:abc.abstractmethod + propertyabc.abstractmethod + 属性
【发布时间】:2013-01-18 05:29:52
【问题描述】:

根据docs,它应该可以结合@property@abc.abstractmethod,所以以下应该在python3.3中工作:

import abc

class FooBase(metaclass=abc.ABCMeta):

    @property
    @abc.abstractmethod
    def greet(self):
        """ must be implemented in order to instantiate """
        pass

    @property
    def greet_comparison(self):
        """ must be implemented in order to instantiate """
        return 'hello'

class Foo(FooBase):
    def greet(self):
        return 'hello'

测试实现:

In [6]: foo = Foo()
In [7]: foo.greet
Out[7]: <bound method Foo.greet of <__main__.Foo object at 0x7f935a971f10>>

In [8]: foo.greet()
Out[8]: 'hello'

所以它显然不是一个属性,因为它应该像这样工作:

In [9]: foo.greet_comparison
Out[9]: 'hello'

也许我太笨了,或者它根本不起作用,有人有想法吗?

【问题讨论】:

    标签: python properties abc


    【解决方案1】:

    如果你想让greet 成为一个属性,你仍然需要在你的实现中使用@property 装饰器:

    class Foo(FooBase):
        @property
        def greet(self):
            return 'hello'
    

    ABC 元类所做的只是测试您是否在具体类中提供了相同的名称;它不关心它是方法、属性还是常规属性。

    因为它不在乎,所以它也不会神奇地应用 property 装饰器。这是一件的事情;也许在特定的实现中,一个静态属性就足以满足要求,而一个属性将是矫枉过正。

    ABC 元类的目的是帮助您发现实施中的差距;它从来没有打算强制执行属性的类型。

    请注意,在 Python 3.3 之前,您不能将 @property@abstractmethod 结合使用。您必须改用@abstractproperty decorator。在这种情况下,当您的属性需要的不仅仅是一个简单的 getter 时,就会出现歧义; Python 3.3 更好地涵盖了这种情况(有关痛苦的细节,请参阅 issue 11610)。

    【讨论】:

    • 如果你有一个抽象设置器,装饰 greet 会满足覆盖要求吗?只是一个兴趣点。
    • @m.brindley:如果greet in dir(Foo) 工作,它满足作为替代。请参阅previous answer of mine,了解 ABC 如何检查覆盖。
    • 感谢您的解释,您最后一句话的一件小事,我使用它是因为python3.3 docs 提到,@abstractproperty 装饰器已弃用。
    • 啊,我还没有看到;感谢您指出了这一点!这确实有道理;通过支持这样的属性方法,可以很好地解决歧义(我不知道)!
    • 较新版本的 python 再次弃用 abstractproperty 装饰器。现在只需将propertyabstractmethod 一起使用,顺序似乎很重要
    猜你喜欢
    • 2011-05-27
    • 2012-06-28
    • 2016-05-03
    • 2012-07-19
    • 2014-03-05
    • 2010-09-17
    • 1970-01-01
    • 2018-08-18
    相关资源
    最近更新 更多