理解其他类变量中的参考类变量 [英] Reference class variable in a comprehension of another class variable
问题描述
这可能是一个简单的问题,但我无法对其进行唯一搜索.
This may be a simple question, but I'm having trouble making a unique search for it.
我有一个定义静态字典的类,然后尝试静态地定义该字典的子集.
I have a class that defines a static dictionary, then attempts to define a subset of that dictionary, also statically.
因此,作为一个玩具示例:
So, as a toy example:
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:全局名称"first_d"未定义
我应该如何进行参考?在其他情况下,似乎可以使用这种模式,例如:
How should I be making this reference? It seems this pattern works in other cases, eg:
class example2(object):
first = 1
second = first + 1
推荐答案
A basic list comprehension has the following syntax
[expression for var in iterable]
在类内部发生列表理解时,该类的属性可以在 iterable
中使用.在Python2和Python3中是这样.
When a list comprehension occurs inside a class, the attributes of the class
can be used in iterable
. This is true in Python2 and Python3.
但是,可以在Python2的 expression
中使用(即访问)该类的属性,而在Python3中则不能.
However, the attributes of the class can be used (i.e. accessed) in expression
in Python2 but not in Python3.
对于生成器表达式,这个故事有些不同:
The story is a bit different for generator expressions:
(expression for var in iterable)
尽管仍然可以从 iterable
访问类属性,但是不能从 expression
访问类属性.(对于Python2和Python3确实如此).
While the class attributes can still be accessed from iterable
, the class attributes are not accessible from expression
. (This is true for Python2 and 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
(字典理解在这方面的行为与生成器表达式相同.)
(Dict comprehensions behave the same as generator expressions in this respect.)
现在这与您的问题有何关系:
在您的示例中,
second_d = dict((k,first_d[k]) for k in (2,3))
发生 NameError
是因为无法从生成器表达式的 expression
部分访问 first_d
.
a NameError
occurs because first_d
is not accessible from the expression
part of a generator expression.
Python2的一种解决方法是将生成器表达式更改为列表理解:
A workaround for Python2 would be to change the generator expression to a list comprehension:
second_d = dict([(k,first_d[k]) for k in (2,3)])
但是,我发现这不是一个非常舒适的解决方案,因为该代码将在Python3中失败.
However, I don't find this a very comfortable solution since this code will fail in Python3.
您可以按照Joel Cornett的建议进行操作:
You could do as Joel Cornett suggests:
second_d = {k: v for k, v in first_d.items() if k in (2, 3)}
因为它在 iterable
中使用了 first_d
,而不是dict理解的 expression
部分.但是,如果 first_d
包含许多项目,则可能会遍历更多的项目.没关系,如果 first_d
很小,此解决方案可能就很好.
since this uses first_d
in the iterable
rather than the expression
part of the dict comprehension. But this may loop through many more items than necessary if first_d
contains many items. Neverthess, this solution might be just fine if first_d
is small.
通常,您可以通过定义可以在类内部或外部定义的辅助函数来避免此问题:
In general, you can avoid this problem by defining a helper function which can be defined inside or outside the class:
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]
函数之所以起作用,是因为它们定义了局部范围,可以从dict理解中访问此局部范围内的变量.
Functions work because they define a local scope and variables in this local scope can be accessed from within the dict comprehension.
这是在这里解释,但是我对此并不完全满意,因为它不能解释为什么表达式
部分的行为与列表理解,生成器表达式或字典理解的 iterable
部分不同.
This was explained here, but I am not entirely comfortable with this since it does not explain why the expression
part behaves differently than the iterable
part of a list comprehension, generator expression or dict comprehension.
因此,我无法(完全)解释为什么 Python的行为方式,只是这就是它的行为方式.
Thus I can not explain (completely) why Python behaves this way, only that this is the way it appears to behave.
这篇关于理解其他类变量中的参考类变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!