N Chauhan
N Chauhan

Reputation: 3515

Class __repr__ of a metaclass, not a class

I am aware of the ability to define a 'class repr' by using a metaclass. However, I need the functionality of returning the metaclass with its own __repr__ as such:

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)

As expected, type(e) and type(m) return their respective 'Person class: ...', however, if I do type(Employee), I get <class '__main__.Meta'>. I need this class to have its own __repr__ as the actual implementation I am using consists of a base Type class with subclasses of String, Number, etc. Calling type on the instances works just fine, but since type may be also called on the class, I need a more 'user-friendly' return string.

Upvotes: 1

Views: 336

Answers (2)

N Chauhan
N Chauhan

Reputation: 3515

Found a simple solution. Since my class structure (inheritance tree) is as follows, I just need to return the next class down:

MetaType: metaclass with __repr__
 |
Type: base class
 |
builtins: e.g. String, Number

So all I put in my code was this:

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

Upvotes: 0

jsbueno
jsbueno

Reputation: 110811

Actually, nothing would prevent you from writting a meta-meta class with the __repr__ for the metaclass itself:

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>

The output of repr(M):

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

(The confusing thing here is that type is also the metaclass for type itself - that is reflected here in that M does not inherit from MM, but rather, have it as its metaclass).

Upvotes: 2

Related Questions