为了账号安全,请及时绑定邮箱和手机立即绑定

如何在不忘记在子类中添加属性装饰器的情况下覆盖抽象属性方法?

如何在不忘记在子类中添加属性装饰器的情况下覆盖抽象属性方法?

当年话下 2023-06-20 10:36:15
如果我重写了一个抽象属性方法,但忘记指定它仍然是子类中的属性方法,我希望 Python 解释器对我大喊大叫。class Parent(metaclass=ABCMeta):  @property  @abstractmethod  def name(self) -> str:    passclass Child(Parent):  @property # If I forget this, I want Python to yell at me.  def name(self) -> str:    return 'The Name'if __name__ == '__main__':  print(Child().name)Python 真的没有内置方法可以做到这一点吗?我真的必须创建自己的装饰器来处理这种行为吗?
查看完整描述

3 回答

?
白衣非少年

TA贡献1155条经验 获得超0个赞

您可以使用metaclass:


class Parent(type):

  def __new__(cls, name, bases, body):

    if 'name' not in body.keys() or body['name'].__class__.__name__ != 'property':

      raise TypeError(f"Can't instantiate class {name} without property name")

    return super().__new__(cls, name, bases, body)



class Child(metaclass=Parent):

  @property # If I forget this, raise TypeError

  def name(self) -> str: # also, name must be implemented

    return 'The Name'


if __name__ == '__main__':

  print(Child().name)

这引发了一个TypeError: Can't instantiate class Child without property name- when@property被注释掉了!


查看完整回答
反对 回复 2023-06-20
?
郎朗坤

TA贡献1921条经验 获得超9个赞

您可以在 Parent 的方法中进行运行时检查,如果是方法__init__则引发异常。name


class Parent(metaclass=ABCMeta):

  def __init__(self):

    assert not callable(self.name)


  @abstractmethod

  def name(self) -> str:

    pass



class GoodChild(Parent):

  @property

  def name(self) -> str:

    return 'The Name'



class BadChild(Parent):

  def name(self) -> str:

    return 'Whoops, not a property'



if __name__ == '__main__':

  good_child = GoodChild()

  print(good_child.name)   # Prints 'The Name'

  bad_child = BadChild()   # Raises an AssertionError when initialized


查看完整回答
反对 回复 2023-06-20
?
qq_笑_17

TA贡献1818条经验 获得超7个赞

TLDR - 在我看来不值得麻烦:


在 linting/mypy 和单元测试之间,应该涵盖你的大部分需求和围绕类分析/元类的小技巧可能不值得他们带来额外的认知负担。你只会“失败”你的装饰一次,但必须阅读异国情调的脚手架代码,用于您每次都想做的事情。


详细信息 - 实际使用被标记为什么?


ie if badchild1.name.startswith("John"): 将在运行时失败,我希望 mypy 或 pylint 也能标记分析,因为它将成为一个方法对象。串联也是如此。唯一真正需要监督的候选人是 f 字符串,直接布尔值或==不!=关心它不是字符串的相等比较。


pylint是这样说的:


test_171_prop.py:11 Method 'name' was expected to be 'property', found it instead as 'method' (invalid-overridden-method)

但是mypy没有问题。


但是,如果我添加这个:


child = Child()


print("name:" + child.name)

然后mypy说:


test_171_prop.py:16: error: Unsupported operand types for + ("str" and "Callable[[], str]")

Found 1 error in 1 file (checked 1 source file)

并使用 2 条新行运行代码说:


TypeError: can only concatenate str (not "method") to str


查看完整回答
反对 回复 2023-06-20
  • 3 回答
  • 0 关注
  • 121 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信