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

时间:2017-04-13 05:41:53

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

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

例如,请在此处获取此代码:

import React, {Component} from 'react'
import queries from './queries'
import { graphql, compose } from 'react-apollo';

class Test extends Component {
...

  render() {
    ...
    
    console.log(this.props.subjectsQuery, this.props.appsQuery); // should show both 
    
    ...
  }
}

export default compose(
   graphql(queries.getSubjects, {
      name: "subjectsQuery"
   }),
   graphql(queries.getApps, {
      name: "appsQuery"
   }),
)(Test);

在该代码中,创建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创建时,sub2v的{​​{1}}属性将变为sub1。我想我可能知道为什么会这样。我假设基类的sub2实际上并没有设置子类的属性,而是它自己的属性。然后该属性在子类中继承。我的问题是:如何使用这种继承来设置子类的属性,而不是继承的基类的属性。

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

这甚至可能吗?

1 个答案:

答案 0 :(得分: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)