1

I'm trying to figure out how to ensure that a method of a class inheriting from an ABC is created using the appropriate decorator. I understand (hopefully) how ABCs work in general.

from abc import ABCMeta, abstractmethod

class MyABC(metaclass=ABCMeta):
    @abstractmethod
    def my_abstract_method(self):
        pass

class MyClass(MyABC):
    pass

MyClass()

This gives "TypeError: Can't instantiate abstract class MyClass with abstract methods my_abstract_method". Great, makes sense. Just create a method with that name.

class MyClass(MyABC):
    def my_abstract_method(self):
        pass

MyClass()

Boom. You're done. But what about this case?

from abc import ABCMeta, abstractmethod

class MyABC(metaclass=ABCMeta):    
    @property
    @abstractmethod
    def my_attribute(self):
        pass

class MyClass(MyABC):
    def my_attribute(self):
        pass

MyClass()

The MyClass() call works even though my_attribute is not a property. I guess in the end all ABCs do is ensure that a method with a given name exists. Thats it. If you want more from it, you have to look at MyABC's source code and read the documentation. The decorators and comments there will inform you of how you need to construct your sub-class.

Do I have it right or am I missing something here?

4

1 回答 1

2

您是正确的,ABC 不会强制执行此操作。没有办法强制执行诸如“具有特定装饰器”之类的内容。装饰器只是返回对象的函数(例如,property返回一个属性对象)。ABCMeta 没有做任何事情来确保类上定义的属性是特定的;它只是确保它们在那里。这个“有效”没有错误:

class MyABC(metaclass=ABCMeta):
    @abstractmethod
    def my_abstract_method(self):
        pass

class MyClass(MyABC):
    my_abstract_method = 2

MyClass()

也就是说,ABCMeta 甚至不确保子类上提供的抽象方法是方法。只是必须有某种具有该名称的属性,

您当然可以编写自己的元类来进行更复杂的检查以确保某些属性具有某些类型的值,但这超出了 ABCMeta 的范围。

于 2016-08-09T05:45:50.370 回答