Reputation: 868
Say I create a new class as part of a metaclass:
import six
class Meta(type):
def __new__(mcl, name, bases, attrs):
nt = type.__new__(mcl, name, bases, attrs)
class NestedClass(object):
pass
print(NestedClass)
return nt
class Foo(six.with_metaclass(Meta), object):
pass
In Python 2, I get:
<class '__main__.NestedClass'>
whereas in Python 3, I get:
<class '__main__.Meta.__new__.<locals>.NestedClass'>
I know that I can control the behavior of __repr__()
by implementing my own version on Meta
, for example:
class Meta(type):
# ...
def __repr__(self):
return "<class '{}'>.format(self.__name__)"
However, I am mostly curious where the default Python 3 version is getting "__main__.Meta.__new__.<locals>.
" from at call time. Inspecting the class object, I am not seeing any state that stores it. Is it getting baked straight into the __repr__()
function itself?
Upvotes: 0
Views: 484
Reputation: 70223
This comes from the combination of __module__
and __qualname__
(new in python3 via PEP 3155)
Adjusting your example slightly:
import six
class Meta(type):
def __new__(mcl, name, bases, attrs):
nt = type.__new__(mcl, name, bases, attrs)
class NestedClass(object):
pass
print(NestedClass)
# vvvvvvvvvvvvvvvvvvvvvvvvvvvvv
print(NestedClass.__module__)
print(NestedClass.__qualname__)
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
return nt
class Foo(six.with_metaclass(Meta), object):
pass
Produces the following output:
$ python3 t.py
<class '__main__.Meta.__new__.<locals>.NestedClass'>
__main__
Meta.__new__.<locals>.NestedClass
Note that python 2.x does not have __qualname__
so you'll need to adjust with something like getattr(cls, '__qualname__', '__name__')
to be compatible
Upvotes: 2