Con*_*nor 3 python inheritance
我正在尝试构建一些继承自父类的类,该类包含从其他父类继承的子类.但是当我在任何子级中更改子类中的属性时,更改会影响所有子类.我希望避免创建实例,因为我稍后使用该功能.
下面的代码归结了这个问题.最后一行显示了意外的结果.
class SubclsParent(object):
a = "Hello"
class Parent(object):
class Subcls(SubclsParent):
pass
class Child1(Parent):
pass
class Child2(Parent):
pass
Child1.Subcls.a # Returns "Hello"
Child2.Subcls.a # Returns "Hello"
Child1.Subcls.a = "Goodbye"
Child1.Subcls.a # Returns "Goodbye"
Child2.Subcls.a # Returns "Goodbye" / Should still return "Hello"!
Run Code Online (Sandbox Code Playgroud)
您所看到的行为正是您应该期待的.定义类时
>>> class Foo(object): pass
...
Run Code Online (Sandbox Code Playgroud)
你可以修改那个类 - 不是它的实例,类本身 - 因为类只是另一个对象,存储在变量Foo中.因此,例如,您可以获取并设置类的属性:
>>> Foo.a = 1
>>> Foo.a
1
Run Code Online (Sandbox Code Playgroud)
换句话说,class
关键字创建一种新类型的对象,并将指定的名称绑定到该对象.
现在,如果你在另一个类中定义一个类(顺便说一句,这是一个奇怪的事情),这相当于在类体中定义一个局部变量.而且你知道在类体内定义局部变量的作用是什么:它将它们设置为类属性.换句话说,本地定义的变量存储在类对象中,而不是存储在单个实例上.从而,
>>> class Foo(object):
... class Bar(object): pass
...
Run Code Online (Sandbox Code Playgroud)
定义一个Foo
具有一个类属性的类Bar
,它本身就是一个类.但是这里没有子类化 - 类Foo
和Bar
完全独立.(您已实现的行为可以复制如下:
>>> class Foo(object):
... class Bar(object): pass
...
>>> class Foo(object): pass
...
>>> class Bar(object): pass
...
>>> Foo.Bar = Bar
Run Code Online (Sandbox Code Playgroud)
.)
所以你总是修改同一个变量!当然,你会改变你看到的价值观; 你自己改变了!
您的问题似乎是您在实例和类属性之间有些混淆,这些属性完全不同.
甲类属性是其在整个类定义的变量.也就是说,该类的任何实例都将共享相同的变量.例如,大多数方法都是类属性,因为您希望在每个实例上调用相同的方法(通常).您还可以将类属性用于全局计数器(您实例化此类的次数?)以及应在实例之间共享的其他属性.
一个实例属性是一个变量特有的类的一个实例.也就是说,每个实例都有一个不同的变量副本,可能含有不同的内容.这是您将数据存储在类中的位置 - 例如,如果您有一个Page
类,那么您希望contents
每个实例存储该属性,因为不同的Page
s当然需要不同contents
.
在您的示例中,您希望Child1.Subcls.a
并Child2.Subcls.a
成为不同的变量.当然,他们应该依赖于实例!
这可能是一种信念的飞跃,但您是否尝试在Python中实现Java风格的接口?换句话说,您是否尝试指定类应具有哪些属性和方法,而不实际定义这些属性?
这曾经被认为是非Pythonic要做的事情,因为普遍的共识是你应该允许类做任何他们想做的事情并捕捉他们没有定义所需属性或方法时产生的异常.然而,最近人们已经意识到接口实际上有时是一件好事,并且Python中添加了新功能以允许这样:抽象基类.
归档时间: |
|
查看次数: |
11546 次 |
最近记录: |