如何在定义现有类变量时引用它们

2024-09-28 20:40:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我想做:

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

    def __init__(self):
        # enhance!

或者我怎样才能让它正常工作。;)

编辑:

好吧,事实证明这不是问题,上面的方法很好,这个不过:

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

哦,你,Python!我能想出一些解决办法,但有人能准确地向我解释一下发生了什么事吗?为什么生成器不能访问类变量?你知道吗


Tags: 方法inself编辑forobjectfooinit
3条回答

你可以试试:

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

甚至:

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

原因是Python中的类有自己的名称空间。引入此命名空间的作用域无权访问此命名空间,因此,从生成器表达式的作用域中,无法访问Whatevs命名空间内的变量。你知道吗

我的列表理解没有引入一个新的作用域——至少在Python2.x中是这样。在Python3.x中,这个作用域已经改变了,所以我的选项2也不起作用。你知道吗

生成器理解实际上是显式定义生成器的简写。在幕后,你想写的东西相当于:

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)

在Python2.x中,列表理解在这里起作用,但Python3.x的一个变化是,列表理解也使用单独的作用域(即隐藏函数),就像生成器理解一样,因此列表理解在Python3中也会中断。你知道吗

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

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

相关问题 更多 >