1

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.

AivanF.
  • 1,134
  • 2
  • 23
  • 52

1 Answers1

1

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
chepner
  • 497,756
  • 71
  • 530
  • 681
  • Hi and thanks for the reply! As I said, our codebase is really big, there is a dozen of such mixin classes, and your case with `class Fitter(FitterMixin)` 1. is actually just inheritance, 2. it won't work the same well with 10+ mixin classes; there would be a need to design some inheritance tree which is not what I want. And your last code sample is just what I described as a problem of mixins: IDE sees `self.field` in the `FitterMixin`, but it cannot confidently find a definition; the same with methods. My Q was about approach to solve this problem, is it possible? – AivanF. Dec 04 '20 at 18:31
  • Sounds like an IDE-specific problem, not a Python problem. – chepner Dec 04 '20 at 18:37
  • Oh, I found [a pretty similar Q](https://stackoverflow.com/q/55209849/5308802), probably this is what I'm looking for. – AivanF. Dec 04 '20 at 19:01