将输入参数传递给类属性

时间:2018-07-19 20:02:16

标签: python

我正在开发一个与另一个模块一起使用的模块。另一个模块要求在__init__方法之前设置类属性(假定该另一个模块的行为无法更改,让我们开始工作)。这些类属性(在下面的示例中为Signal)部分源自我代码中的对象。

以下所示的方法由于许多原因而成为灾难。例如,

  1. my_obj1my_obj2不保证存在;的 在这种情况下,导入其他模块将失败。
  2. 可能需要创建2个不同的实例 OtherModuleVodoo1使用我代码中的2个不同实例 (my_obj

这是解释代码的骨架:

import Signal, Device
from my_module.setup import my_obj1, my_obj2

class OtherModuleVodoo1(Device):
    # The class signal attributes must be defined before the __init__ 
    # and rely upon an object from my module

    x = Signal(my_obj1.cmds['thing_x'], 'thing_x')
    y = Signal(my_obj1.cmds['thing_y'], 'thing_y')

    # ...
    # ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)


class OtherModuleVodoo2(Device):
    x = Signal(my_obj2, 'thing1')
    y = Signal(my_obj2, 'thing2')

    # ...
    # ...

    def __init__(self, *args, **kwargs):
       super().__init__(*args, **kwargs)


# now in my file I do this
dev1 = OtherModuleVodoo1()
dev2 = OtherModuleVodoo2()

# but would much prefer to do this 
dev1 = OtherModuleVodoo(my_object_input = my_obj1)
# where I don't need ```Vodoo1, Vodoo2``` but can have a generic 
solution. 

问题:

是否可以将参数“输入”到类的构造中(而不是类实例的初始化)?

我尝试了什么,为什么每个都不起作用。

  1. 元类。这些感觉接近正确的方法,但是我无法使其正常工作。
  2. __new__,但这不会填充类定义中的名称空间(在__init__之前)
  3. 设置my_obj1 = None直到需要一个OtherModuleVodoo1实例,然后在实例化对象之前修改class属性:

尝试3的示例:

xyq = None
class Test2():
    print(xyq)
    def __init__(self):
        print(self.xyq)

Test2.xyq = 55
t2 = Test2()

但是,这里的输出是:

None
55

我期望完全集中于改变方法的回应。那是必要的。但是,我的直接问题是如何最好地使用创可贴。

2 个答案:

答案 0 :(得分:1)

这可能需要一些按摩才能使其与您的代码一起使用,但是您可以在父类中使用__init_subclass__ 来接受创建类的参数。这是在Python 3.6中引入的

class Voodoo:
    def __init_subclass__(cls, myobj, **kwargs):
        super().__init_subclass__(**kwargs)
        cls.x = Signal(my_obj1.cmds['thing_x'], 'thing_x')
        cls.y = Signal(my_obj1.cmds['thing_y'], 'thing_y')

class Voodoo1(Voodoo, Device, myobj=myobj1):
    pass

您还可以将Voodoo设为Device的子类,以清理子类的签名。

答案 1 :(得分:0)

在Python 3中具有元类的示例

class Meta(type):
    def __new__(cls, name, bases, dct):
        dct['xyq'] = 55

        return super().__new__(cls, name, bases, dct)

class A(metaclass=Meta):
    ... # A.xyq == 55

class B(A):
    ... # B.xyq == A.xyq == 55

当创建类A和B(不是实例化)时,元类才起作用。