首页 > 解决方案 > 通常此类方法的第一个参数名为“mcs”

问题描述

我在以下元类中收到了令人惊讶的 PyCharm 警告

通常此类方法的第一个参数名为“mcs”

这是我不知道的一些约定,比如命名第一个参数self还是cls?我尝试搜索 SO 但没有找到任何命中。代码取自这篇文章

警告截图

class Meta(type):

    def __prepare__(metaclass, cls, bases):
        return dict()

    def __new__(metacls, cls, bases, clsdict):
        return super().__new__(metacls, cls, bases, clsdict)

标签: pythonpycharmwarningsmetaclass

解决方案


对于元类,通常是“类方法”的方法 - 就像__prepare__并将__new__在第一个参数上接收元类本身。

关于该参数的命名没有约定。通常人们不知道或根本不担心元类真正发生的全部情况,只会简单地命名它们cls,就好像它是一个正常的类,然后生活就会随之而来。我相信大多数 IDE 不会识别其他任何东西,如果突出显示的“正确”使用“cls”和“self”作为方法的第一个参数,它们甚至可能会将其他任何东西标记为“错误”。必须始终牢记,这些只是惯例 - 短绒和语法荧光笔远不如人类思维灵活(至少目前如此),不应将它们视为法律。

也就是说,与名称“cls”和“self”不同,当第一个参数是元类本身时,没有严格的约定——我通常将它命名为mcls,但mcs会很好,虽然metaclass有点危险,因为它是保留的类定义本身中的关键字(使用class语句时)。

但是,参数中使用的类恰好metaclass是传递给元类方法的第一个参数的类,因此,是的,如果元类中的第一个参数名为__new__,它可能会“修复不一致” 。(我从来没想过那个)。__new__metaclass

换句话说,当用 定义一个类时class MyClass(ClassA, ClassB, metaclass=MyMeta):, 的MyMeta第一个参数传递的是MyMeta.__new__,如果它是 命名metaclass的,就好像Python 将它作为“命名参数”传递一样。即使在class语句方面,metaclass名称在语言定义中是硬编码的,并且在def __new__另一方面,将使用第一个参数上的任何名称。

In [98]: class M(type):
    ...:     def __new__(metaclass, name, bases, namespace, **kwargs):
    ...:         return super().__new__(metaclass, name, bases, namespace, **kwargs)
    ...: 

In [99]: class A(metaclass=M): 
    ...:    pass

无论如何,正如我所说,我通常对mcls.

相反,同样重要的是:元类上的任何其他方法,普通类上的任何其他方法都self将作为参数接收class使用元类创建的 - 所以通常命名它们cls而不是self,因为更容易记住元类的实例代表什么。

因此,在方法的元类中,以及任何有用的方法,第一个参数都有意义,__init__而不是。__getattr____call__clsself

回到你的片段之一:

class Meta(type):

    def __prepare__(metaclass, cls, bases):
        return dict()

    def __new__(metacls, cls, bases, clsdict):
        return super().__new__(metacls, cls, bases, clsdict)

正如我评论的那样,您可以调用第一个参数,metacls第二个参数应该不是。同样:Python 将这些作为有序参数传递,因此如果您将其命名为它会起作用,但它的内容是作为字符串声明的类名,尽管如此。一方面,名称通常表示类本身,在调用这些方法时它甚至不存在——它只会从您在 元类方法内部调用的那一点开始存在。__new____prepare__nameclsclsclssuper().__new____new__

至于第四个参数,你调用clsdict,我知道没有严格的约定 -clsdict足够清楚,就像那样namespace- 但多年来,我一直在使用 simple dct,并且ns有时也使用过。

最后,如上所述,我不希望 PyCharm 或任何其他风格的荧光笔(或“校正器”)比我更好地理解我对元类的意图:我会忽略它们。


推荐阅读