在另一个类变量的理解中引用类变量

2024-02-03

这可能是一个简单的问题,但我很难对其进行独特的搜索。

我有一个定义静态字典的类,然后尝试静态地定义该字典的子集。

因此,作为一个玩具示例:

class example(object): 
    first_d = {1:1,2:2,3:3,4:4} 
    second_d = dict((k,first_d[k]) for k in (2,3))

这会产生NameError: global name 'first_d' is not defined

我应该如何做这个参考?看来这种模式在其他情况下也适用,例如:

class example2(object):
    first = 1
    second = first + 1

基本的列表理解具有以下内容syntax http://docs.python.org/reference/expressions.html#displays-for-sets-and-dictionaries

[expression for var in iterable]

当列表理解发生在类内部时,类的属性 可用于iterable。在Python2和Python3中也是如此。

但是,类的属性可以在以下情况中使用(即访问):expression在 Python2 中,但在 Python3 中则不然。

对于生成器表达式来说,情况有些不同:

(expression for var in iterable)

虽然类属性仍然可以从iterable,类属性不可从expression。 (对于 Python2 和 Python3 来说也是如此)。

这一切可以概括如下:

                             Python2      Python3
Can access class attributes
--------------------------------------------------
list comp. iterable                Y            Y
list comp. expression              Y            N
gen expr. iterable                 Y            Y
gen expr. expression               N            N
dict comp. iterable                Y            Y
dict comp. expression              N            N

(在这方面,字典推导式的行为与生成器表达式相同。)


现在这与您的问题有什么关系:

在你的例子中,

second_d = dict((k,first_d[k]) for k in (2,3))

a NameError发生是因为first_d无法从expression生成器表达式的一部分。

Python2 的解决方法是将生成器表达式更改为列表理解:

second_d = dict([(k,first_d[k]) for k in (2,3)])

然而,我认为这不是一个非常舒适的解决方案,因为这段代码在 Python3 中会失败。

你可以按照乔尔·科内特的建议去做:

second_d = {k: v for k, v in first_d.items() if k in (2, 3)}

因为这使用first_d in the iterable而不是expression字典理解的一部分。但这可能会循环遍历比必要的更多的项目,如果first_d包含许多项目。尽管如此,如果first_d是小。

一般来说,您可以通过定义一个辅助函数来避免这个问题,该函数可以在类内部或外部定义:

def partial_dict(dct, keys):
    return {k:dct[k] for k in keys}

class Example(object):
    first_d = {1:1,2:2,3:3,4:4}
    second_d = partial_dict(first_d, (2,3))

class Example2(object):
    a = [1,2,3,4,5]
    b = [2,4]
    def myfunc(A, B):
        return [x for x in A if x not in B]
    c = myfunc(a, b)

print(Example().second_d)
# {2: 2, 3: 3}

print(Example2().c)
# [1, 3, 5]

函数之所以有效,是因为它们定义了局部作用域并且 可以从字典理解中访问此局部范围内的变量。

这是在这里解释 https://stackoverflow.com/a/11670273/190597,但我对此并不完全满意,因为它没有解释为什么expression部分的行为与iterable列表理解、生成器表达式或字典理解的一部分。

因此我无法(完全)解释whyPython 就是这样运行的,只不过这就是它看起来的运行方式。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在另一个类变量的理解中引用类变量 的相关文章

随机推荐