Python Mixin for __str__and method resolution definitions

I found that many classes that I write in Python contain a small set of variables that I really would like to see when I call str() , and that rewriting __str__(self) for each of them is rather cumbersome. So I prepared the next mixin,

 class StrMixin(object): ''' Automatically generate __str__ and __repr__ ''' def __str__(self): import types name = self.__class__.__name__ + ': ' attrs = [ '{}={}'.format(k,v) for (k,v) in self.__dict__.items() ] return name + ', '.join(attrs) def __repr__(self): return str(self) 

However, if I write a class,

 class C(object, StrMixin): pass 

I get the following error when creating an instance,

 TypeError: Error when calling the metaclass bases Cannot create a consistent method resolution order (MRO) for bases object, StrMixin 

Provided, including object is redundant here, but what happens here?

+6
source share
3 answers

When you define:

 class StrMixin(object): ... 

The compiler knows that StrMixin precedes object in the MRO class.

When you do:

 class C(object, StrMixin): pass 

You told the compiler that object precedes StrMixin in the MRO. But object should also appear after StrMixin , so it should appear twice in the MRO, and this is not allowed.

If you say:

 class C(StrMixin, object): pass 

then MRO is just C , StrMixin , an object that satisfies the order given by both classes. There is no duplication, because although object referenced twice, there is no conflict between definitions.

+11
source

You yourself answered the question - the second object superfluous. Class C has two bases: an object and StrMixin. However, the StrMixin base is also an object, so it is confused as to which object it should solve first. MRO evaluates it as (C, STRMixin, object, object), which has duplicate objects. In this particular case, it seems obvious what the solution should be, but add a few more classes, and the MRO may become less clear. For instance.

 class A(object): pass class B(object, A): pass class C(object, A): pass class D(object, B, C): pass class E(object, A, D): pass 

What is MRO for E? Be that as it may, its really complicated, has duplicates, and possibly several cycles.

The MRO is explained pretty well here , and your particular case is seen about two-thirds down the page, the first example in the β€œBad permission orders” section.

+1
source

Multiple inheritance may be the mind. To keep inheritance simple when using mixins, you can define a function outside the class and assign it to the class when it is defined.

 class StrMixin: # class here used only as a namespace @staticmethod # not needed with Python 3 def __str__(self): name = self.__class__.__name__ + ': ' attrs = [ '{}={}'.format(k,v) for (k,v) in self.__dict__.items() ] return name + ', '.join(attrs) __repr__ = __str__ class C(object): __str__, __repr__ = StrMixin.__str__, StrMixin.__repr__ 

Or, if you store your mixin functions in a module, you can use it in your class as follows:

 class C(object): from StrMixin import __str__, __repr__ 
0
source

Source: https://habr.com/ru/post/910328/


All Articles