https://stackoverflow.com/a/37657923/8061009声明该程序:
class Parent(object):
i = 5;
def __init__(self):
self.i = 5
def doStuff(self):
print(self.i)
class Child(Parent, object):
def __init__(self):
super(Child, self).__init__()
self.i = 7
class Main():
def main(self):
m = Child()
print(m.i) #print 7
m.doStuff() #print 7
m = Main()
m.main()
输出将是:
$ python Main.py
7
7
然后,该答案将其与Java中的类似程序进行比较:
原因是因为Child类中的Java int声明使 我成为了类范围变量,而在 Python子类化。如果您在Java的Child类中删除int i,它将 也会打印7和7。
在这种情况下,可变阴影是什么意思?
答案 0 :(得分:1)
在这种情况下,可变阴影是什么意思?
可变阴影表示在所有情况下 都是同一件事,独立于上下文。定义为变量“隐藏”另一个具有相同名称的变量。因此,当发生变量遮蔽时,有两个或多个具有相同的名称,它们的定义取决于它们的作用域(这意味着它们的值可能取决于作用域而有所不同) )。快速示例:
In [11]: def shadowing():
...: x = 1
...: def inner():
...: x = 2
...: print(x)
...: inner()
...: print(x)
...:
In [12]: shadowing()
2
1
请注意,我们首先调用inner()
,这将x
分配为2
,并打印2
。但这不会在外部范围(即第一个x
)修改x
,因为x
中的inner
是遮蔽第一个x
。因此,在我们调用inner()
之后,调用又返回了,现在第一个x
返回了作用域,最后一个打印输出了1
。
在这个特定示例中,您引用的原始作者说的是没发生阴影 (并且要明确:没有在实例级别发生)。您会注意到,父级的i
与子级的i
具有相同的值。如果发生阴影,它们将具有不同的 值,例如上面的示例(即,父级将具有变量i
的副本,而子级将具有 different 也称为i
的变量的副本。但是,他们没有。 i
是父母双方的{em> 中的7
。原始作者指出,Python的继承机制在这方面不同于Java。
HTH。
答案 1 :(得分:0)
当在某个范围内声明的变量(决策块,方法或内部类)与在外部范围内声明的变量具有相同的名称时,就会发生可变阴影。然后,您在阴影中的变量(隐藏/遮罩)在外部范围中。
在上面的代码中,变量i
在父类和子类中均被初始化。因此,超类中的初始化将被子类和类中的初始化遮盖。
m = Child() #we initialized the child class with i=7
print(m.i) #eventhough we are calling a method in the super class the value of i in the super class is shadowed by the value we initialized the instance of the child class (m)
m.doStuff() #same thing here
答案 2 :(得分:0)
在Java中,方法和字段本质上是不同的事物,它们通过完全不同的规则进行操作。子类仅继承方法。字段特定于声明它们的类。如果子类声明的字段与父类中的字段名称相同,则它们是完全无关的。父类的方法继续访问父版本,子类的方法访问其版本。这就是所谓的阴影。如果父类确实希望将其字段提供给孩子,则必须为其定义getter / setter方法。
在Python中,没有这种区别-方法基本上是其值恰好是函数的字段。此外,整个继承层次结构中的所有字段都存储在单个命名空间中(通常实现为名为__dict__
的dict属性)。如果孩子和父母为某件事使用相同的名称,则他们必然是在指同一对象。