关于python:类的__repr__类,而不是类

Class __repr__ of a metaclass, not a class

我知道使用元类定义'class repr'的能力。但是,我需要用它自己的__repr__返回元类的功能,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Meta(type):
    def __repr__(cls):
        return 'Person class: {}'.format(cls.__name__)


class Person(metaclass=Meta):
    def __init__(self, name, age, job):
        self.name = name
        self.job = job
        self.age = age

    def __str__(self):
        return 'Person: {}, {}, {}'.format(self.name,
                                           self.age,
                                           self.job)


class Employee(Person):
    def __init__(self, name, age):
        super(Employee, self).__init__(name, age, 'employee')


class Manager(Person):
    def __init__(self, name, age):
        super(Manager, self).__init__(name, age, 'manager')

m = Manager('bob', 79)
e = Employee('stephen', 25)

如预期,type(e)type(m)返回各自的'Person class: ...',但是,如果我执行type(Employee)操作,我会得到。我需要这个类有它自己的__repr__,因为我使用的实际实现由一个基础Type类组成,它的子类有StringNumber等。在实例上调用类型工作得很好,但是由于类型也可以在类上调用,所以我需要一个更"用户友好"的返回字符串。


实际上,没有什么可以阻止您为元类本身编写带有__repr__的元类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
In [2]: class MM(type):
   ...:     def __repr__(cls):
   ...:         return f"<metaclass {cls.__name__}"
   ...:      

In [3]: class M(type, metaclass=MM):
   ...:     def __repr__(cls):
   ...:         return f"<class {cls.__name__}>"
   ...:    

In [4]: class O(metaclass=M):
   ...:     pass
   ...:

In [5]: o = O()

In [6]: o
Out[6]: <<class O> at 0x7ff7e0089128>

In [7]: O
Out[7]: <class O>

repr(M)的输出:

1
2
In [8]: repr(M)
Out[8]: '<metaclass M'

(这里令人困惑的是,type也是type本身的元类,这反映在m不是从MM继承的,而是把它作为元类)。


找到了一个简单的解决方案。由于我的类结构(继承树)如下,我只需要返回下一个类:

1
2
3
4
5
MetaType: metaclass with __repr__
 |
Type: base class
 |
builtins: e.g. String, Number

所以我输入的代码是:

1
2
3
4
5
6
t = type(self.parse(args['object']))
# where 'self.parse' is the parsing method for the argument to my function
# where args['object'] is the object whose type is being returned
if t == MetaType:
    return Type
return t