元类方法相互调用的最佳实践是什么?

3

我正试图构建一个元类,我觉得我真的理解了它。我想为这个元类的每个实例都创建类方法。

class MyMeta(type):
    """A metaclass"""
    def __new__(mcs, name, bases, attributes):
        pass

    def _foo(cls):
        pass

    def _bar(cls):
        cls._foo()

当我在它上运行pylint时,cls._foo出现了问题:
[pylint] E1120:No value for argument 'cls' in unbound method call

当我尝试运行代码时(我的代码比这个更复杂),它似乎正在正常运行,并且正在执行我期望它执行的操作。那么我该如何解决这个问题?这究竟意味着什么。
听起来像是由于未正确声明为静态方法而引起的其他错误,但我无法将其标记为@classmethod,因为那样它将成为元类方法。
相关搜索似乎在谈论人们动态添加构造函数或其他内容的地方,而我不认为这是那种情况。我是否还在误解关于元类的某些事情?
我真正想要的是在元类中定义相互调用的类方法。有更好的方法吗?

https://dev59.com/B5Pfa4cB1Zd3GeqPHcFU - SteveJ
@SteveJ 这正是我提到的情况。那个问题中的 OP 希望在派生类中声明一个构造函数。但这里并非如此。 - McKay
1个回答

2
[pylint] E1120:未绑定方法调用中参数'cls'没有值
就你的元类而言,你的_foo和_bar方法只是普通的Python方法——这意味着当调用这些方法时,Python会自动填充对每个类(元类实例)的引用。
此外,由于这是一个元类,为了清晰、语义明确和易读性,最好像你所做的那样:将它们的第一个参数命名为cls而不是self。
问题在于pylint不知道这一点:它可能期望一个硬编码的self。在这方面,你的代码是无可挑剔的。
你需要做的就是添加一个元注释来让pylint忽略这些行——幸运的是,Pylint允许在块级别进行标记,而不像某些工具需要在每行上标记。
class MyMeta(type):
    """A metaclass"""
    # pylint: disable=no-value-for-parameter

    def __new__(mcs, name, bases, attributes):
        pass

    def _foo(cls):
        pass

    def _bar(cls):
        cls._foo()

您的示例元类,具有“元注释”,以便pylint忽略非错误。


这很有道理。但我认为你的答案实际上是“我认为这是pylint的一个错误/限制,只需禁用它。”并不是说我认为你错了,但这里没有权威的东西。 - McKay
我已经编辑了问题的标题,以便更清晰地表达。 - McKay
那不会改变我的答案。这里有一部分写着“…按照你的做法更好”。你只需要意识到,在元类中定义的这些方法在类的实例中是不可见的:它们仅仅是类方法。(这有时是一个优点和设计,我希望 Python 的 datetime.datetime 也采用这种方式) - jsbueno
“不在实例中可见”是一项理想的功能。 - McKay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接