【问题标题】:Access local variables of overridden parent method访问被覆盖的父方法的局部变量
【发布时间】:2017-07-26 00:50:30
【问题描述】:

如何在子类的重写方法中访问超类方法的局部变量?

class Foo(object):
    def foo_method(self):
        x = 3

class Bar(Foo):
    def foo_method(self):
        super().foo_method()
        print(x) # Is there a way to access x, besides making x an attribute of the class?

下面的代码给出了NameError: name 'x' is not defined

bar = Bar()
bar.foo_method()

这不足为奇,可以通过将x 设为实例属性来解决此问题,但是否可以更直接地在Bar.foo_method 中直接访问x

【问题讨论】:

  • 你不能那样做。为什么需要?
  • 我不需要这样做。我只是想知道这是否可能。通常当 Python 的一个特性很难找到时,就意味着有更好的方法来做。
  • 理论上,您不应该知道类/方法的内部工作原理,除非它专门将它们公开为公共属性。

标签: python python-3.x scope namespaces stack-frame


【解决方案1】:

总结

问。 ... 可以更直接地在 Bar.foo_method 中按原样访问 x 吗?

正如所写,答案是否定的

super().foo_method() 返回时,该方法的堆栈帧已经被打包并且局部变量已经消失。没有什么可以访问的。

替代方案:return 语句

共享数据最简单的解决方案是让foo_method 返回x

class Foo(object):
    def foo_method(self):
        x = 3
        return x

class Bar(Foo):
    def foo_method(self):
        x = super().foo_method()
        print(x)

替代解决方案:动态范围

如果您正在寻找类似于 dynamic scoping 的内容,最简单的解决方案是传入共享命名空间:

class Foo(object):
    def foo_method(self, ns):
        x = 3
        ns['x'] = 3

class Bar(Foo):
    def foo_method(self):
        ns = {}
        super().foo_method(ns)
        x = ns['x']
        print(x)

如果您想在嵌套调用中模拟动态范围,请考虑使用collections.ChainMap()

【讨论】:

  • 我喜欢动态范围编辑。由于这仅在您无法更改签名和返回类型时才真正重要,因此也许 ns 应该是一个可选的关键字参数,并且只有在不是 None 时才添加 x 键。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-16
  • 2013-03-27
相关资源
最近更新 更多