简体   繁体   English

从基类中设置子类变量/属性

[英]Set Subclass Variables/Attributes from Within Base Class

Is it possible to dynamically create/set variables within a subclass within the base class across multiple subclasses without affecting the other subclasses? 是否可以在多个子类之间的基类的子类中动态创建/设置变量,而不影响其他子类?

For example, take this code here: 例如,在这里使用以下代码:

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

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

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

In that code, when sub1 is created, its v attribute is equal to 1 . 在该代码中,创建sub1时,其v属性等于1 But when sub2 is created, the v attribute of both sub1 and sub2 becomes 5 . 但是,当创建sub2时, sub1sub2v属性都变为5 I think I might know why this is. 我想我可能知道为什么。 I assume the @classmethod of the base class is not actually setting the attribute of the subclass, but instead its own attribute. 我假设基类的@classmethod实际上不是设置子类的属性,而是设置其自己的属性。 Then that attribute is inherited in the subclasses. 然后,该属性在子类中继承。 My question is: how can I use this kind of inheritance to set attributes of subclasses, not attributes of the base class which are inherited. 我的问题是:如何使用这种继承来设置子类的属性,而不是继承的基类的属性。

In other words, I would like to be able to use a similar structure, if possible (or at least a simple one) in order to accomplish setting attributes in subclasses that are specific to the subclasses and are not simply globally inherited from the base class. 换句话说,我希望能够使用类似的结构(如果可能的话)(或至少是一个简单的结构),以便在特定于子类的子类中完成设置属性,而不是简单地从基类全局继承。

Is this even possible? 这有可能吗?

I don't know if it can be easily accomplished any other way, but I've come up with a solution myself using a metaclass. 我不知道是否可以通过其他任何方式轻松实现,但是我自己使用元类提出了一个解决方案。

Solution: 解:

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)

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

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