Python- Multiple dynamic inheritance

元气小坏坏 提交于 2019-12-08 10:03:00

问题


I'm having trouble with getting multiple dynamic inheritance to work. These examples make the most sense to me(here and here), but there's not enough code in one example for me to really understand what's going on and the other example doesn't seem to be working when I change it around for my needs (code below).

I'm creating a universal tool that works with multiple software packages. In one software, I need to inherit from 2 classes: 1 software specific API mixin, and 1 PySide class. In another software I only need to inherit from the 1 PySide class.

The least elegant solution that I can think of is to just create 2 separate classes (with all of the same methods) and call either one based on the software that's running. I have a feeling there's a better solution.

Here's what I'm working with:

## MainWindow.py

import os
from maya.app.general.mayaMixin import MayaQWidgetDockableMixin

# Build class
def build_main_window(*arg):

    class Build(arg):
        def __init__(self):
            super( Build, self ).__init__()

        # ----- a bunch of methods

# Get software
software = os.getenv('SOFTWARE')

# Run tool
if software == 'maya':
    build_main_window(maya_mixin_class, QtGui.QWidget)
if software == 'houdini':
    build_main_window(QtGui.QWidget)

I'm currently getting this error:

#     class Build(arg):
# TypeError: Error when calling the metaclass bases
#     tuple() takes at most 1 argument (3 given) # 

Thanks for any help!

EDIT:

## MainWindow.py

import os

# Build class 
class BuildMixin():
    def __init__(self):
        super( BuildMixin, self ).__init__()

    # ----- a bunch of methods

def build_main_window(*args):
    return type('Build', (BuildMixin, QtGui.QWidget) + args, {})

# Get software
software = os.getenv('SOFTWARE')

# Run tool
if software == 'maya':
    from maya.app.general.mayaMixin import MayaQWidgetDockableMixin

    Build = build_main_window(MayaQWidgetDockableMixin)

if software == 'houdini':
    Build = build_main_window()

回答1:


The error in your original code is caused by failing to use tuple expansion in the class definition. I would suggest simplifying your code to this:

# Get software
software = os.getenv('SOFTWARE')

BaseClasses = [QtGui.QWidget]
if software == 'maya':
    from maya.app.general.mayaMixin import MayaQWidgetDockableMixin
    BaseClasses.insert(0, MayaQWidgetDockableMixin)

class Build(*BaseClasses):
    def __init__(self, parent=None):
        super(Build, self).__init__(parent)

UPDATE:

The above code will only work with Python 3, so it looks like a solution using type() will be needed for Python 2. From the other comments, it appears that the MayaQWidgetDockableMixin class may be a old-style class, so a solution like this may be necessary:

def BaseClass():
    bases = [QtGui.QWidget]
    if software == 'maya':
        from maya.app.general.mayaMixin import MayaQWidgetDockableMixin
        class Mixin(MayaQWidgetDockableMixin, object): pass
        bases.insert(0, Mixin)
    return type('BuildBase', tuple(bases), {})

class Build(BaseClass()):
    def __init__(self, parent=None):
        super(Build, self).__init__(parent)



回答2:


arg is a tuple, you can't use a tuple as a base class.

Use type() to create a new class instead; it takes a class name, a tuple of base classes (can be empty) and the class body (a dictionary).

I'd keep the methods for your class in a mix-in method:

class BuildMixin():
    def __init__(self):
        super(BuildMixin, self).__init__()

    # ----- a bunch of methods

def build_main_window(*arg):
    return type('Build', (BuildMixin, QtGui.QWidget) + args, {})

if software == 'maya':
    Build = build_main_window(maya_mixin_class)
if software == 'houdini':
    Build = build_main_window()

Here, args is used as an additional set of classes to inherit from. The BuildMixin class provides all the real methods, so the third argument to type() is left empty (the generated Build class has an empty class body).

Since QtGui.QWidget is common between the two classes, I just moved that into the type() call.



来源:https://stackoverflow.com/questions/39878892/python-multiple-dynamic-inheritance

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!