【问题标题】:Set Subclass Variables/Attributes from Within Base Class从基类中设置子类变量/属性
【发布时间】:2017-04-13 05:41:53
【问题描述】:

是否可以跨多个子类在基类内的子类中动态创建/设置变量而不影响其他子类?

例如,这里的代码:

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 实际上并没有设置子类的属性,而是它自己的属性。然后在子类中继承该属性。我的问题是:如何使用这种继承来设置子类的属性,而不是继承的基类的属性。

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

这可能吗?

【问题讨论】:

  • 有什么原因你不能这样做:v = 1 in sub1v = 5 in sub2?类语句主体内的赋值,在任何方法之外,已经定义了类属性;你不需要特殊的方法来做到这一点。将__init__ 设置为classmethod 听起来好像你真的想要一个元类,但如果你只想设置一个类属性,那就太矫枉过正了......

标签: python python-3.x inheritance subclassing class-instance-variables


【解决方案1】:

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

解决方案:

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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-25
    • 2014-02-16
    • 2019-01-30
    • 1970-01-01
    • 2013-01-16
    • 2021-10-14
    相关资源
    最近更新 更多