通常这种方法的第一个参数被命名为 'mcs'

Usually first parameter of such methods is named 'mcs'

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

Usually first parameter of such methods is named 'mcs'

这是我不知道的约定,例如将第一个参数命名为 selfcls?我尝试搜索 SO 但没有找到任何结果。代码取自 this post.

class Meta(type):

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

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

对于 metaclasses,通常是“class 方法”的方法 - 如 __prepare____new__ 将在第一个参数上接收 metaclass本身。

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

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

但是,碰巧 metaclass 参数中使用的 class 恰好是传递给 meta[=90] 的第一个参数的那个=] __new__ 方法,所以,是的,如果元 class __new__ 中的第一个参数被命名为 metaclass,它可能会“修复不一致”。 (我从没想过)。

换句话说,当用 class MyClass(ClassA, ClassB, metaclass=MyMeta): 定义 class 时,MyMetaMyMeta.__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感到满意。

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

因此,在方法 __init____getattr____call__ 的元 class 中以及任何认为有用的方法中,第一个参数是 cls 而不是 self.

回到你的一个片段:

class Meta(type):

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

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

正如我评论的那样,您可以调用第一个参数 metacls,但是 __new____prepare__ 第二个 参数应该是 name 不是 cls。再次:Python 将这些作为有序参数传递,因此如果您将其命名为 cls,它将 工作 ,但其内容是声明的 class 名称尽管如此,还是一个字符串。一方面,cls 名称通常指定 class 本身,当调用这些方法时它甚至 不存在 - 它只会从点存在在 __new__ metaclass 方法中调用 super().__new__ 的地方。

至于第四个参数,你调用 clsdict,我知道没有强约定 - clsdict 足够清楚,namespace - 但多年来,我一直简单地使用 dct,有时也使用 ns

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

我认为 meta类 的使用频率比常规 类 低得多,因此像 selfcls 这样强大和广泛的约定不合乎逻辑不存在。

Google 搜索结果稍微偏向 mcs:

__new__(mcs 3490 个结果

__new__(mcls 2230 个结果

__new__(metacls 1940 个结果

__new__(metaclass 919 个结果

就我个人而言,我会倾向于 metacls,因为它更具描述性,而且对我来说感觉更符合 cls

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