For metaclasses, the methods that would normally be "class methods" - like __prepare__
and __new__
will receive on the first parameter the metaclass itself.
There is no convention about the naming of that parameter. Usually people unaware, or simply not worried, about the full extent of what is really going on with a metaclass, will simply name these cls
as if it were a normal class and life follows. I believe most IDEs won't recognize anything other, and if the highlighted "correct" use of "cls" and "self" as the first parameter to methods, they might even mark anything else as "wrong". One always has to keep in mind these are just conventions - and linters and syntax highlighters are far less flexible than the human mind (at least currently), and their word should not be taken as the law.
That said, unlike the names "cls" and "self", there is no strong convention for when the first parameter is the metaclass itself - I usually name it mcls
, but mcs
would be fine, while metaclass
is a bit dangerous, as it is a reserved keyword in the class definition itself (when using the class
statement).
However, it happens that the class used in the metaclass
argument is exactly the one passed to the first argument of the metaclass __new__
method, so, yes, it might "fix an inconsistency" if the first parameter in a metaclass __new__
is named metaclass
. (I never thought about that).
In other words, when defining a class with class MyClass(ClassA, ClassB, metaclass=MyMeta):
, the MyMeta
is what is passed in the first parameter of MyMeta.__new__
, and if it is named metaclass
, it will be as if Python was passing it as a "named parameter". Even though, on the class
statement side, the metaclass
name is hardcoded in the language definition, and on the def __new__
side, whatever name is on the first parameter will be used.
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
Anyway, as I said, I am usually happy with mcls
.
And conversely, and equally important: any other methods on a metaclass, that on an ordinary class would be self
will be receiving as parameter the class
created with the metaclass - So it is usual to name those cls
instead of self
, as it is easier to keep in mind what an instance of the metaclass represents.
Thus, in a metaclass for the methods __init__
, __getattr__
, __call__
and whatever one finds useful, the first argument makes sense as being cls
instead of self
.
Going back to one of your snippets:
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)
As I commented, you may call the first argument metacls
, but the second argument to __new__
and __prepare__
should be name
not cls
. Again: Python passes these as ordered arguments, so it would work if you named it cls
, but its contents are the declared class name as a string, nonetheless. On one hand, the cls
name normally designates the class itself, and it does not even exist when these methods are called - it will exist only from the point where you call super().__new__
inside the __new__
metaclass method.
As for the fourth parameter, you call clsdict
, I know of no strong convention - clsdict
is clear enough, as would be namespace
- but over the years, I've been using simply dct
, and have used ns
on occasion as well.
And finally, as stated above, I would not expect PyCharm or any other style highlighter (or "corrector") to understand better than me what are my intentions with a metaclass: I will just ignore them.