0

是否可以在不影响其他子类的情况下,在基类内的子类内动态创建/设置变量?从基类中设置子类变量/属性

例如,这里借此代码:

class Base: 
    @classmethod 
    def __init__(cls,v): 
     cls.v=v 

class sub1(Base): 
    Base.__init__(1) 

class sub2(Base): 
    Base.__init__(5) 

在该代码中,创建sub1的情况下,其v属性等于1。但是,当创建sub2时,sub1sub2v属性将变为5。我想我可能知道这是为什么。我假设基类的@classmethod实际上并没有设置子类的属性,而是它自己的属性。然后,该属性在子类中继承。我的问题是:如何使用这种继承来设置子类的属性,而不是继承的基类的属性。

换句话说,我希望能够使用类似的结构(如果可能的话)(或者至少是一个简单的结构),以便完成特定于子类的子类中的设置属性,而不是简单地全局继承来自基类。

这甚至可能吗?

+0

是有一些原因,你不能只是做:'V = 1'在'sub1'和'V = 5'在'sub2'?在任何方法之外的类声明体内的赋值已经定义了类属性;你不需要一个特殊的方法来做到这一点。使'__init__'成为'classmethod'使得它听起来像你真的想要一个元类,但如果你只是想设置一个类属性,那么这太大了矫枉过正...... – ShadowRanger

回答

0

我不知道是否可以用其他方式轻松完成,但我使用元类自己想出了一个解决方案。

解决方案:

class MetaBase(type): 
    def __init__(cls, name, bases, namespace): 
     super(MetaBase, cls).__init__(name, bases, namespace) 
     if '_superclass' in namespace: # A special attribute to distinguish between superclasses and subclasses 
      if '_attrnames' not in namespace: 
       raise AttributeError('"_attrnames" needs to be defined as a class attribute in a superclass.') 
     else: 
      if 'classvars' in namespace: # Allow for define all required class attributes in one iterable attribute 
       for attrname, attr in zip(getattr(cls.__mro__[1], '_attrnames'), getattr(cls, 'classvars')): # Get all the varnames in the superclass's "varnames", as well as the values 
        setattr(cls, attrname, attr) 
        namespace[attrname] = attr 
       delattr(cls, 'classvars') 
      else: 
       for attrname in getattr(cls.mro()[1], '_attrnames'): 
        if attrname not in namespace: 
         raise AttributeError('"%s" not defined, but is required.' % attrname) 

class Base(metaclass=MetaBase): 
    _superclass = True # The value of this attribute doesn't matter 
    _attrnames = ('a','b','c') 

class Sub1(Base): 
    a = 1 
    b = 2 
    c = 3 

class Sub2(Base): 
    classvars = (1, 2, 3)