【问题标题】:Dynamic class and method instantiation with Inheritance使用继承的动态类和方法实例化
【发布时间】:2017-09-18 21:18:30
【问题描述】:

我的要求是根据特定字符串动态实例化一个类。这里的问题是新类继承了其他一些类。问题是我无法看到从 Inherited 类执行的代码。

我试图通过创建一个 SystemConfigure 的类来做到这一点,它将根据字典中给出的参数调用特定的类。在我的代码中,我动态调用从Base 类继承函数的超类。我没有看到 Base 类中的代码被执行。

请告诉我如何做到这一点。

代码

class SystemConfigure():

    def __init__(self,snp_dict):
        dict = snp_dict
        osname = dict['osname']
        protocol = dict['protocol']
        module = protocol
        func_string = osname + "_" + protocol + "_" + "Configure"
        print ("You have called the Class:", module, "and the function:", func_string)
        m = globals()[module]
        func = getattr(m, func_string)
        func(dict)

class Base():

    def __init__(self):
        pass
        print("BASE INIT")

    def Unix_Base_Configure(dict):
        print ("GOT IN THE UNIX BASE CLASS FUNCTION")

    def Linux_Base_Configure(dict):
        print("GOT IN THE LINUX BASE CLASS FUNCTION")

class Super(Base):

    def __init__(self):
        dict = dict
        Base.__init__(self)
        Base.Unix_Base_Configure(dict)

    def Unix_Super_Configure(dict):
        print ("GOT IN THE UNIX SUPER CLASS FUNCTION", dict)

n = SystemConfigure({'protocol':'Super','osname':'Unix','device':'dut'})

输出

You have called the Class: Super and the function: Unix_Super_Configure
GOT IN THE UNIX SUPER CLASS FUNCTION {'protocol': 'Super', 'osname': 'Unix', 'device': 'dut'}

期待

我期待打印“GOT IN THE UNIX BASE CLASS FUNCTION”错误。需要在“GOT IN THE UNIX SUPER CLASS FUNCTION”消息之前打印输出。

【问题讨论】:

  • 您的代码有多个错误。你永远不会实例化你的类,所以__init__ 也不会被调用。您的“配置”方法也不接受 self 参数。

标签: python python-3.x inheritance dynamic


【解决方案1】:

您需要将一些方法定义为@staticmethods,因为它们没有self 参数(或需要一个参数)。下面是你的代码# ADDED

我还更改了传递给 SystemConfigure() 的字典参数的处理方式,因此它现在利用 Python 关键字参数传递来创建一个字典来传递它,但这种更改并不是严格要求的。

class SystemConfigure():
    def __init__(self, **kwargs):  # CHANGED - argument snp_dict into **kwargs
        # dict = snp_dict  # REMOVED - no longer needed
        osname = kwargs['osname']
        protocol = kwargs['protocol']
        module = protocol
        func_string = osname + "_" + protocol + "_" + "Configure"
        print ("You have called the Class:", module, "and the function:", func_string)
        m = globals()[module]
        func = getattr(m, func_string)
        func(kwargs)

class Base():
    def __init__(self):
        pass
        print("BASE INIT")

    @staticmethod  # ADDED
    def Unix_Base_Configure(dict):
        print ("GOT IN THE UNIX BASE CLASS FUNCTION")

    @staticmethod  # ADDED
    def Linux_Base_Configure(dict):
        print("GOT IN THE LINUX BASE CLASS FUNCTION")

class Super(Base):
    def __init__(self):  # THIS IS NEVER CALLED
#        dict = dict  # REMOVED - don't know what this is all about...
        Base.__init__(self)
        Base.Unix_Base_Configure(dict)  # why is a type being passed?

    @staticmethod  # ADDED
    def Unix_Super_Configure(dict_):
        print ("GOT IN THE UNIX SUPER CLASS FUNCTION", dict_)

# Changed how dictionary argument is created into a more (IMO) readable form (optional)
n = SystemConfigure(protocol='Super', osname='Unix', device='dut')

输出:

You have called the Class: Super and the function: Unix_Super_Configure
GOT IN THE UNIX SUPER CLASS FUNCTION {'protocol': 'Super', 'osname': 'Unix', 'device': 'dut'}

【讨论】:

    【解决方案2】:

    这通常是 Python 中元类的工作。
    快速解释一下,元类可用于定义“如何”“创建”类。
    查看文档或查找“python 元编程教程”以获取有关该主题的更多信息 (So: What are Python metaclasses useful for?

    class BaseMetaClass(type):
        def __new__(meta, name, bases, dct):
            return super(BaseMetaClass, meta).__new__(meta, name, bases, dct)
    
        def __init__(cls, name, bases, dct):
            super(BaseMetaClass, cls).__init__(name, bases, dct)
    
        def __call__(cls, *args, **kwds):
            if args and isinstance(args[0], dict):
                if 'osname' in args[0]:
                    cls.osname = args[0]['osname']
                else:
                    cls.osname = "undefined os"
    
                cls.base_configure = "GOT IN THE %s BASE CLASS FUNCTION" % cls.osname.upper()
            return type.__call__(cls, *args, **kwds)
    
    
    class SystemConfigure(metaclass=BaseMetaClass):
        def __init__(self, snp_dict):
            print (self.base_configure)
    
    n = SystemConfigure({'protocol':'Super','osname':'Unix','device':'dut'})
    n = SystemConfigure({'protocol':'Super','osname':'Linux','device':'dut'})
    n = SystemConfigure({'protocol':'Super','device':'dut'})
    

    返回:

    GOT IN THE UNIX BASE CLASS FUNCTION
    GOT IN THE LINUX BASE CLASS FUNCTION
    GOT IN THE WINDOWS BASE CLASS FUNCTION
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-10
      • 1970-01-01
      • 2020-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-21
      • 1970-01-01
      相关资源
      最近更新 更多