Python 2.7结合abc.abstract方法和classmethod [英] Python 2.7 Combine abc.abstractmethod and classmethod

查看:579
本文介绍了Python 2.7结合abc.abstract方法和classmethod的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在Python 2.7中为抽象类方法创建装饰器?

How do I create a decorator for an abstract class method in Python 2.7?

是的,这与这个问题,除了我想结合 abc.abstractmethod classmethod ,而不是静态方法。此外,它看起来像 abc.abstractclassmethod 是在Python 3中添加了 (我认为?),但我使用的是Google App Engine,所以我目前仅限于Python 2.7

Yes, this is similar to this question, except I would like to combine abc.abstractmethod and classmethod, instead of staticmethod. Also, it looks like abc.abstractclassmethod was added in Python 3 (I think?), but I'm using Google App Engine, so I'm currently limited to Python 2.7

非常感谢。

推荐答案

以下是源自Python 3.3的 abc 模块源代码的一个工作示例:

Here's a working example derived from the source code in Python 3.3's abc module:

from abc import ABCMeta

class abstractclassmethod(classmethod):

    __isabstractmethod__ = True

    def __init__(self, callable):
        callable.__isabstractmethod__ = True
        super(abstractclassmethod, self).__init__(callable)

class DemoABC:

    __metaclass__ = ABCMeta

    @abstractclassmethod
    def from_int(cls, n):
        return cls()

class DemoConcrete(DemoABC):

    @classmethod
    def from_int(cls, n):
        return cls(2*n)

    def __init__(self, n):
        print 'Initializing with', n

以下是运行时的样子:

Here's what it looks like when running:

>>> d = DemoConcrete(5)             # Succeeds by calling a concrete __init__()
Initializing with 5

>>> d = DemoConcrete.from_int(5)    # Succeeds by calling a concrete from_int()
Initializing with 10

>>> DemoABC()                       # Fails because from_int() is abstract    
Traceback (most recent call last):
  ...
TypeError: Can't instantiate abstract class DemoABC with abstract methods from_int

>>> DemoABC.from_int(5)             # Fails because from_int() is not implemented
Traceback (most recent call last):
  ...
TypeError: Can't instantiate abstract class DemoABC with abstract methods from_int

请注意,最后一个例子因为 cls()不会实例化。 ABCMeta 可以防止未定义所有抽象方法的类的过早实例化。

Note that the final example fails because cls() won't instantiate. ABCMeta prevents premature instantiation of classes that haven't defined all of the required abstract methods.

另一种触发 > from_int()抽象类方法被调用是为了引发异常:

Another way to trigger a failure when the from_int() abstract class method is called is to have it raise an exception:

class DemoABC:

    __metaclass__ = ABCMeta

    @abstractclassmethod
    def from_int(cls, n):
        raise NotImplementedError

设计 ABCMeta 不会阻止任何抽象方法在一个没有实际意义的类上被调用,因此您需要触发通过类方法调用 cls()失败,或者引发NotImplementedError 。无论哪种方式,你都会得到一个很好的,干净的失败。

The design ABCMeta makes no effort to prevent any abstract method from being called on an uninstantiated class, so it is up to you to trigger a failure by invoking cls() as classmethods usually do or by raising a NotImplementedError. Either way, you get a nice, clean failure.

写一个描述符来拦截直接调用抽象类方法可能很诱人,但那会是 ABCMeta 的整体设计的可能性(这是关于在实例化之前检查所需方法而不是在调用方法时)。

It is probably tempting to write a descriptor to intercept a direct call to an abstract class method, but that would be at odds with the overall design of ABCMeta (which is all about checking for required methods prior to instantiation rather than when methods are called).

这篇关于Python 2.7结合abc.abstract方法和classmethod的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆