Python 继承的基类变量

2 投票
1 回答
3872 浏览
提问于 2025-04-18 09:46

我有一个叫做 Base 的类,下面有两个子类。我的想法是创建一个模型,里面包含所有的数据,然后把这些数据放到其中一个子类里。接着,我会调用一个方法来设置每个子类的头部信息,然后把模型里的数据复制到子类的实例中。不过,我发现当我在第一个类的实例(这里是 a)上调用 add_header 方法时,第二个实例 b 也得到了这个头部信息。这让我有点困惑,因为我以为不同的类实例之间是互不影响的。我的问题是,为什么会这样?有没有办法避免这种情况呢?

class Base(object):
    __model__ = None
    headers = ['base_header','base_header2']

    def add_header(self, *args):
        for h in args:
            self.headers.append(h)

    def set_header_values(self):
        for h in self.headers:
            setattr(self, h, getattr(self.__model__, h))


class ChildOne(Base):
    def __init__(self, model):
        self.__model__ = model


class ChildTwo(Base):
    def __init__(self, model):
        self.__model__ = model


class Model(object):
    foo = 'bar'

m = Model()
a = ChildOne(m)
b = ChildTwo(m)
a.add_header('tralala')
print b.headers // Output ['base_header','base_header2','tralala']

1 个回答

3

“在第一个类实例(这里是 a)调用 add_header 方法后,b 也得到了这个头部信息。”

这是因为这两个实例共享了同一个变量 headers。

所以,headers 应该是实例变量,而不是变量。

class Base(object):
    __model__ = None
    def __init__(self):
        self.headers = []

    def add_header(self, *args):
        for h in args:
            self.headers.append(h)

    def set_header_values(self):
        for h in self.headers:
            setattr(self, h, getattr(self.__model__, h))


class ChildOne(Base):
    def __init__(self, model):
        super(ChildOne, self).__init__()
        self.__model__ = model


class ChildTwo(Base):
    def __init__(self, model):
        super(ChildTwo, self).__init__()
        self.__model__ = model


class Model(object):
    foo = 'bar'

m = Model()
a = ChildOne(m)
b = ChildTwo(m)
a.add_header('tralala')
print a.headers
print b.headers 

输出

['tralala']

[]

补充说明

在 Python 中,类变量和实例变量常常会让人困惑。来看下面这个例子:

class A:
    l =[] 

class B:
    l =[]

x = A()
y = A()
x.l.append(1)
print 'class A ', A.l, x.l, y.l

x = B()
y = B()
x.l = [1]
print 'class B ', B.l, x.l, y.l

输出

class A  [1] [1] [1]
class B  [] [1] []

这两个例子在访问数据成员 'l' 时看起来很相似,但第一个例子修改了已经存在的类变量,而第二个例子则创建了一个新的实例变量。

在你的例子中,如果你用 self.headers = [...] 来赋值,而不是 self.append(...),那么你的输出结果会不同。

另外,问题中的 __model__ 属性和这个问题没有关系。

撰写回答