python中的abstractproperty + classmethod装饰器
Posted
技术标签:
【中文标题】python中的abstractproperty + classmethod装饰器【英文标题】:abstractproperty + classmethod decorators in python 【发布时间】:2021-03-30 12:06:54 【问题描述】:我想强制孩子们在 python2.7 中使用类方法。 我试过这个:
import abc
class Base(object):
__metaclass__ = abc.ABCMeta
@abc.abstractproperty
def value(self):
pass
@abc.abstractproperty
@classmethod
def text(cls):
pass
class Imp(Base):
TEXT = "hi im text"
@classmethod
def haba(cls):
print 'HI'
@property
def value(self):
return 'asdasd'
@classmethod
@property
def text(cls):
return 'ho ho p'
print Imp.text
print Imp.TEXT
但我得到了这个输出:main.Imp'>> 嗨,我的文字
我怎样才能正确地强制孩子实现类方法属性? 您可以看到 Imp.TEXT 正在工作,但无法强制以这种方式从基类创建此成员
【问题讨论】:
【参考方案1】:在重新阅读您的问题几次后,我得出结论,您希望 cl
方法的行为就像它是类的属性一样。
首先,Python 的抽象方法/属性检查的实现仅在实例化时执行,而不是在类声明时执行。我希望你知道这一点。
其次,Python 的描述符协议允许创建等效的“类属性”,尽管语言本身没有更高级别的支持 - 您可以创建一个类,__get__
方法在以下情况下返回您的计算属性实例参数是 None (通常描述符将返回 'self' 以便可以从类中检索它们)。
最后 - 有可能通过将自定义元类声明为抽象本身,然后将其声明为您的类元类,abstractproperties 将在运行时触发 - 让我们尝试一下 - :
In [1]: import abc
In [2]: class AbsPropertyMeta(abc.ABC, type):
...: @abc.abstractproperty
...: def cl(cls):
...: return "Ho ho ho"
...:
In [3]: class ConcreteExample(metaclass=AbsPropertyMeta):
...: pass
...:
(请注意,我将使用 Python 3 开发答案,这应该是您在任何新项目或学习目的中应该使用的)
因此,对于前一个示例,元类中的属性确实作为“类属性”工作,但 Python 不会强制在类主体中对其进行重新定义。
所以,如果你真的需要这种设计,你应该为此创建一个完整的自定义元类,并完全放弃 abc.ABCMeta 机制:
from functools import partial
def abstractclassproperty(func):
func._abstract_property = True
return func
class clsproperty(object):
def __init__(self, func):
self.func = func
def __get__(self, instance, owner):
return self.func(owner)
class ABCAbstractClsProperty(type):
def __new__(mcls, name, bases, namespace, **kw):
new_cls = super(ABCAbstractClsProperty, mcls).__new__(mcls, name, bases, namespace, **kw)
for attr_name in dir(new_cls): # Dir retrieves attributes from all superclasses
attr = getattr(new_cls, attr_name)
if getattr(attr, "im_func", None): # Python 2 specific normalization.
attr = attr.im_func
if getattr(attr, '_abstract_property', False) and new_cls.__dict__.get(attr_name) is not attr:
raise TypeError("Can't create class !r: abstract property !r not implemented".format(name, attr_name))
return new_cls
""" # Python 3:
class A(metaclass=ABCAbstractClsProperty):
@abstractclassproperty
def cl(cls):
pass
"""
class A(object):
__metaclass__ = ABCAbstractClsProperty
@abstractclassproperty
def cl(cls):
pass
try:
class B(A):
pass
except TypeError:
print("Check ok")
class C(A):
@clsproperty
def cl(cls):
return "ho ho ho " + cls.__name__
print(C.cl)
【讨论】:
以上是关于python中的abstractproperty + classmethod装饰器的主要内容,如果未能解决你的问题,请参考以下文章