什么是可变阴影?

时间:2018-12-12 00:29:23

标签: python python-3.x

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。

在这种情况下,可变阴影是什么意思?

3 个答案:

答案 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属性)。如果孩子和父母为某件事使用相同的名称,则他们必然是在指同一对象。