【问题标题】:How do I reference existing class variables when defining them定义现有类变量时如何引用它们
【发布时间】:2013-02-13 14:48:15
【问题描述】:

我想做:

class Whatevs(object):
    foo = 3
    bar = foo * 3

    def __init__(self):
        # enhance!

或我如何才能使其正常工作。 ;)

编辑:

好的,事实证明这不是问题,上面的工作正常,这个虽然:

class Whatevs(object):
    foo = 3
    zap = list(foo for _ in range(10))

哦,你,蟒蛇!我可以想出一些解决方法,但是有人可以向我解释到底发生了什么吗?为什么生成器不能访问类变量?

【问题讨论】:

  • “正常工作”是什么意思?
  • 这对你还没有用吗?你试过了吗?
  • 是的,很抱歉,这很好用,我以为是问题所在,但事实并非如此。还有@ThorstenKranz,我在引用stackoverflow.com/questions/3392228/… ;)
  • 谈论一个不起眼的参考...

标签: python


【解决方案1】:

生成器推导实际上是显式定义生成器的简写。在幕后,您尝试编写的内容相当于:

class Whatevs(object):
    foo = 3
    def _gen():
        for _ in range(10):
            yield foo
    zap = list(_gen())

不幸的是,您无法从生成器或类主体中定义的函数内部访问 foo 之类的作用域变量(并且您不能使用 Whatevs.foo,因为 Whatevs 尚不存在。

一种选择是将代码移到类主体之外:

class Whatevs(object):
    foo = 3

Whatevs.zap = list(Whatevs.foo for _ in range(10))

另一种选择是将 foo 变成参数:

def _init_zap(foo):
    return list(foo for _ in range(10))

class Whatevs(object):
    foo = 3
    zaps = _init_zap(foo)

在 Python 2.x 中,列表推导在这里有效,但 Python 3.x 的变化之一是列表推导也使用单独的范围(即隐藏函数),就像生成器推导一样,因此列表推导也会中断在 Python 3 中。

【讨论】:

  • 哦!感谢您提供的信息,尤其是最后一点。列表理解和生成器之间的不一致确实让我感到奇怪!我很高兴他们至少在 Python 3 中打破了这一切! ;) j/k.
  • @Noio:是的,Python 3 中的这些和其他“改进”足以让人怀疑“愚蠢的一致性是小聪明的妖精”这句格言是否适用。
【解决方案2】:

你可以试试:

class Whatevs(object):
    foo = 3
    zap = [foo] * 10

甚至:

class Whatevs(object):
    foo = 3
    zap = [foo for _ in range(10)]

原因是 Python 中的类有自己的命名空间。引入此命名空间的作用域无法访问此命名空间,因此,在生成器表达式的作用域中,您无法访问 Whatevs' 命名空间内的变量。

我的列表理解并没有引入新的作用域——至少在 Python 2.x 中是这样。在 Python 3.x 中,这已经改变,所以我的选项 2 也不起作用。

【讨论】:

  • 但是为什么会有所不同呢?因为生成器表达式隐式定义了一个函数?
  • Python 3.3 似乎不喜欢列表推导,但乘法工作正常。
  • 在我的回答中查看我的解释。
【解决方案3】:

一般的解决方案是封装一个 lambda 函数,在 Python2 和 Python3 中的工作方式相同

class Whatevs(object):
    foo = 3
    zap = (lambda foo=foo:list(foo for _ in range(10)))()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-04
    • 2017-09-21
    • 2022-12-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多