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

bad*_*der 7 python warnings metaclass pycharm

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

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

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

警告截图

class Meta(type):

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

    def __new__(metacls, cls, bases, clsdict):
        return super().__new__(metacls, cls, bases, clsdict)
Run Code Online (Sandbox Code Playgroud)

jsb*_*eno 9

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

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

也就是说,与名称“cls”和“self”不同,当第一个参数是元类本身时,没有严格的约定 - 我通常将其命名为mcls,但mcs没问题, whilemetaclass有点危险,因为它是保留的类定义本身中的关键字(使用该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
Run Code Online (Sandbox Code Playgroud)

无论如何,正如我所说,我通常对此感到满意mcls

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

因此,在方法__init____getattr__以及__call__任何人们认为有用的元类中,第一个参数是有意义的cls而不是self

回到你的一个片段:

class Meta(type):
    @classmethod
    def __prepare__(mcls, metaclass, cls, bases):
        return dict()

    def __new__(metacls, cls, bases, clsdict):
        return super().__new__(metacls, cls, bases, clsdict)
Run Code Online (Sandbox Code Playgroud)

正如我所评论的,您可以将第一个参数称为metacls,但第二个参数__new____prepare__应该namecls。再次强调:Python 将这些作为有序参数传递,因此如果您将其命名为,它会起作用cls,但它的内容仍然是作为字符串声明的类名。一方面,该cls名称通常指定类本身,并且在调用这些方法时它甚至不存在super().__new__- 它仅从您在元类方法内部调用的位置开始存在__new__

至于第四个参数,你称之为clsdict,我知道没有强有力的约定 -clsdict已经足够清楚了namespace- 但多年来,我一直简单地使用dct,并且ns有时也使用过。

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


use*_*698 5

可以在 中更改首选值File | Settings | Editor | Inspections | Python | Methods having troubles with first parameter,请参见屏幕截图:

检查设置