AivanF.
AivanF.

Reputation: 1216

Python mixins and types, dependencies

I work on a project with a huge class. Initially they were implemented as functions that just get imported, like in this answer:

def plot(self, x, y):
     print(self.field)

def clear(self):
     # body

@classmethod
def from_file(cls, path):
    # body
class Fitter(object):
     def __init__(self, whatever):
         self.field = whatever

     # Imported methods
     from .some_file import plot, clear, from_file
     ...

But I think it's not the best solution, IDE is mad on the code because it cannot find field in the external methods and considers classmethod on some functions as an error. I hope mixins can help with it.

But I see the similar problem in this approach: mixin classes don't have a base class with all the common methods and fields specified (an example in Django), so IDE and linters cannot find definitions and understand the code correctly too... I tried to use some common base class, as the following:

class FitterBase(object):
     def __init__(self, whatever):
         self.field = whatever

class FiterMixin(FitterBase):
    def plot(self, x, y):
         print(self.field)

    def clear(self):
         # body

    @classmethod
    def from_file(cls, path):
        # body

class Fitter(FitterBase, FiterMixin):
     pass

But the interpreter raises an error:

TypeError: Cannot create a consistent method resolution

Is there any solution to this problem? It's really important because the class contains dozens of big methods, and correct inheritance would help a lot.

Upvotes: 1

Views: 2903

Answers (1)

chepner
chepner

Reputation: 531490

Python is trying to construct an MRO for Fitter in which FitterBase both precedes and follows FitterMixin; the former because FitterBase is listed first in the seance of base classes, the latter because it is the parent of FitterMixin.

To resolve that issue, simply swap the order of the two base classes:

class Fitter(FitterMixin, FitterBase):
   pass

There's no reason to list both, though, because FitterMixin already inherits from FitterBase:

class Fitter(FitterMixin):
    pass

As this makes more obvious, FitterMixin isn't really a mix-in class, because you aren't mixing it with anything. Or, don't make FitterMixin subclass FitterBase:

class FitterBase:
     def __init__(self, whatever):
         self.field = whatever


class FitterMixin:
    def plot(self, x, y):
         print(self.field)

    def clear(self):
        pass

    @classmethod
    def from_file(cls, path):
        pass


class Fitter(FitterBase, FitterMixin):
     pass

Upvotes: 1

Related Questions