简体   繁体   English

动态添加类继承

[英]Adding class inheritance dynamically

I want to create dynamic class inheritance with python. 我想用python创建动态类继承。 For example ( x is maybe an random number) 例如( x可能是一个随机数)

#!/usr/bin/env python
# -*- coding: utf-8 -*-

class Test3(object):
  def sub(self):
    self.c = self.a - self.b

class Test2(object):
  def add(self):
    self.c = self.a + self.b


class Test1(object):
  def __init__(self):
    self.a = 1
    self.b = 2
    self.c = 0


if x >= 0:
  test = Test1
  ## do something to load Test2 methods
  test.add()
  print (test.c)
elif x >= 10:
  test = Test1
  ## do something to load Test3 methods
  test.sub()
  print (test.c)
else:
  test = Test1
  ## do something to load Test3 & Test2 methods
  test.add()
  print (test.c)
  test.sub()
  print (test.c)

I have tried different things to make this working. 我尝试了不同的方法来使其正常工作。 I couldn't manage anyway other than staticly implement the subclasses, which is not what I want: 除了静态实现子类外,我无法管理,这不是我想要的:

class Test1(Test2, Test3)

I also don't want to load a object in a variable and get access about the variables name like: 我也不想在变量中加载对象并获得有关变量名称的访问权,例如:

test1.test3.sub()

There are a couple of tricks you can do to achieve this sort of thing. 您可以通过几种技巧来实现这种目的。

First of you can do something ugly like this:- 首先,您可以像这样做一些丑陋的事情:

def extend(instance, new_class):
    """Add new_class mixin to existing instance"""
    instance.__class__ = type(
            '%s_extended_with_%s' % (instance.__class__.__name__, new_class.__name__), 
            (instance.__class__, new_class), 
            {}
        )

You can use that like this 你可以这样使用

   extend(test , Test2 )

But I would normally prefer to create the dynamic type before initialization rather than overwrtting __class__ so instead of the above for your first example you would do 但是我通常更喜欢在初始化之前创建动态类型,而不是覆盖__class__,因此您可以在第一个示例中使用上面的方法而不是上面的方法

   custom_class = type('special_extended_class', ( Test, Test2 ), {} )
   test  = custom_class()

Note that in the above Test, and Test2 are variable refernces so you cna use anything here, but it isn't hugely different from doing the following which is more readable. 请注意,在上面的Test和Test2是变量引用,因此您可以在此处使用任何内容,但是与以下更易读的操作没有太大不同。

  class1 = Test
  class2 = Test2
  class TmpClass(class1, class2):pass
  test = TmpClass()

I don't really understand why you would want to do things that way. 我不太了解您为什么要那样做。 I would create a base test class then inherit different methods based off of that class. 我将创建一个基础测试类,然后基于该类继承不同的方法。

class BaseTest(object):
    def __init__(self):
        super().__init__()

        self.a = 1
        self.b = 2
        self.c = 0

class Test3(BaseTest):
    def sub(self):
        self.c = self.a - self.b

class Test2(BaseTest):
    def add(self):
        self.c = self.a + self.b

class Test4(Test3, Test2):
    pass

if __name__ == '__main__':
    x = -1
    if x >= 10:
        test = Test3()
        ### load test3 methodes
        test.sub()
        print (test.c)

    elif x >= 0:
        test = Test2()
        ## load test2 methodes
        test.add()
        print (test.c)

    else:
        test = Test4()
        ### load test 2 & test 3 methodes
        test.add()
        print (test.c)
        test.sub()
        print (test.c)

If you really want something dynamic then you will have to set the x value on import 如果您真的想要动态的东西,那么必须在导入时设置x值

import random

class Test3(object):
    def sub(self):
        self.c = self.a - self.b

class Test2(object):
    def add(self):
        self.c = self.a + self.b

class Test4(Test3, Test2):
    pass

val = random.randint(0, 3)
print(val)
x = {0: object,
     1: Test3,
     2: Test2,
     3: Test4,
     }.get(val, object)
print(x)

class BaseTest(x):
    def __init__(self):
        super().__init__()

        self.a = 1
        self.b = 2
        self.c = 0


if __name__ == '__main__':
    b = BaseTest()
    print(b.c)

You could probably make this work by manually setting the members of the class member dictionary as suggested by rgammans, but the easiest way would be with exec: 您可能可以按照rgammans的建议通过手动设置类成员字典的成员来完成这项工作,但是最简单的方法是使用exec:

super = 'list'
exec('class Awesome(' + super +'):\n  pass')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM