在这里,我无法访问Python 列表推导中的类变量 .
class Student:
max_year = 18
year_choice = [i for i in range(100) if i > max_year]
def __init__(self, name):
self.name = name
print (self.year_choice)
Student('Blah')
Run Code Online (Sandbox Code Playgroud)
但它在Python 2中运行良好.
../workspace$ python student.py
[19, 20, 21, 22, 2.... 99]
Run Code Online (Sandbox Code Playgroud)
但是在Python 3中出现错误.
../workspace$ python student.py
File "student.py", line 18, in <listcomp>
year_choice = [i for i in range(100) if i > max_year]
NameError: name 'max_year' is not defined
Run Code Online (Sandbox Code Playgroud)
从调试这个当我改变下面的声明
[i for i in range(100) if i > max_year]
对此
[i …Run Code Online (Sandbox Code Playgroud) 最小的例子
class foo:
loadings = dict(hi=1)
if 'hi' in loadings:
print(loadings['hi'])
# works
print({e : loadings[e] for e in loadings})
# NameError global name 'loadings' not defined
Run Code Online (Sandbox Code Playgroud)
我也尝试引用类命名空间,但这也不起作用
class foo:
loadings = dict(hi=1)
if 'hi' in loadings:
print(loadings['hi'])
#works
print({e : foo.loadings[e] for e in foo.loadings})
#NameError: name 'foo' is not defined
Run Code Online (Sandbox Code Playgroud)
当然,这可以按预期工作
class foo:
loadings = dict(hi=1)
if 'hi' in loadings:
print(loadings['hi'])
print({e : foo.loadings[e] for e in foo.loadings})
Run Code Online (Sandbox Code Playgroud)
我想了解为什么这个范围问题正在发生,如果我想做一些疯狂的事情,那么最好的方法就是这样做.我的感觉是第一个代码片段应该按原样工作,但当然不是.
目标
我正在为一些csv/json文件创建一个DataManager类/模块以及罐装数据库查询,为我的程序提供一站式服务并获取数据.有一些静态数据和一些动态数据,所以它似乎在同一个类中使用静态和非静态数据成员.虽然我理解这些可能是模块级变量,但我喜欢使用静态类数据成员的概念(可能是因为Java的偏见).任何帮助深表感谢
我的解决方案(暂时)
我最终展开了列表理解以保持在课堂范围内,在上面它会变成这样的东西
class foo:
loadings = dict(hi=1) …Run Code Online (Sandbox Code Playgroud) 鉴于班级
from __future__ import annotations
from typing import ClassVar, Dict, Final
import abc
class Cipher(abc.ABC):
@abc.abstractmethod
def encrypt(self, plaintext: str) -> str:
pass
@abc.abstractmethod
def decrypt(self, ciphertext: str) -> str:
pass
class VigenereCipher(Cipher):
@staticmethod
def rotate(n: int) -> str:
return string.ascii_uppercase[n:] + string.ascii_uppercase[:n]
_TABLE: Final[ClassVar[Dict[str, str]]] = dict({(chr(i + ord("A")), rotate(i)) for i in range(26)})
Run Code Online (Sandbox Code Playgroud)
编译失败(使用 3.8.0)
../cipher.py:19: in <module>
class VigenereCipher(Cipher):
../cipher.py:24: in VigenereCipher
_TABLE: Final[ClassVar[Dict[str, str]]] = dict({(chr(i + ord("A")), rotate(i)) for i in range(26)})
../cipher.py:24: …Run Code Online (Sandbox Code Playgroud) python static-methods decorator class-variables python-typing
考虑下面的代码:
class Test:
l = [1, 2, 3]
foo = lambda x: x
for x in l:
print(foo(x))
[print(foo(x)) for x in l]
if __name__ == '__main__':
test = Test()
Run Code Online (Sandbox Code Playgroud)
输出如下:
1
2
3
... in <listcomp>
[print(foo(x)) for x in l]
NameError: name 'foo' is not defined
Run Code Online (Sandbox Code Playgroud)
我不明白为什么foo列表迭代中的函数不是可见的。可能与范围有关,但我正在寻找正确的解释,并在可能的情况下提供支持它的文档。
ps:为了修复代码,我对替代实现不感兴趣。
看看下面这段代码:
class a:
s = 'python'
b = ['p', 'y']
c = [x for x in s]
Run Code Online (Sandbox Code Playgroud)
输出:
>>> a.c
['p', 'y', 't', 'h', 'o', 'n']
Run Code Online (Sandbox Code Playgroud)
但当我试图限制列表时,如果:
class a:
s = 'python'
b = ['p', 'y']
c = [x for x in s if x in b]
Run Code Online (Sandbox Code Playgroud)
显示以下异常:
Traceback (most recent call last):
File "<pyshell#22>", line 1, in <module>
class a:
File "<pyshell#22>", line 4, in a
c = [x for x in s if x in b]
File "<pyshell#22>", …Run Code Online (Sandbox Code Playgroud) 考虑以下:
def f():
a = 2
b = [a + i for i in range(3)]
f()
Run Code Online (Sandbox Code Playgroud)
这没有问题.据我了解(请纠正我,如果我错了),列表推导表达式引入了一个新的范围,但由于它是在一个函数内创建的(而不是一个类),它可以访问周围范围,包括变量a.
相反,如果我要进入调试模式,请在上面的第3行停止,然后在解释器中手动编写以下内容
>>> b = [a + i for i in range(3)]
Run Code Online (Sandbox Code Playgroud)
我收到一个错误:
Traceback (most recent call last):
File "<string>", line 293, in runcode
File "<interactive input>", line 1, in <module>
File "<interactive input>", line 1, in <listcomp>
NameError: global name 'a' is not defined
Run Code Online (Sandbox Code Playgroud)
为什么是这样?当我在调试模式下停在给定的行时,是否可以访问与运行时相同的范围?
(顺便说一下,我正在使用PyScripter)
我有一个代表库存项目及其价值的类:
class stock:
def __init__(self, stockName, stockType, value):
self.name = stockName
self.type = stockType
self.value = value
Run Code Online (Sandbox Code Playgroud)
我有大量库存,所以我制作了一个库存对象列表,我可以从中访问单个项目的价值,例如 stockList[12].value
我想将所有“衬衫”库存商品的价值加起来。以下工作正常:
shirtValue = sum([s.value for s in stockList if s.value == 'shirt'])
Run Code Online (Sandbox Code Playgroud)
好的。但是现在我有一个列表stockType并希望对与 stockType 列表中的特定条目匹配的项目的值求和,例如:
stockTypeValue[0] = sum([s.value for s in stockList if s.value == stockType[0]])
Run Code Online (Sandbox Code Playgroud)
其中,stockType[0] = 'shirt'这是行不通的。我知道为什么 - 这是因为在 Python 3 列表推导中有自己的范围(请参阅此处的详细答案: 从类定义中的列表推导中访问类变量)
我的问题是:我写的代码,我认为可以在 Python 2 中工作的代码看起来很棒,它很干净,易于理解,而且在未受过训练的眼睛看来非常 Pythonic。
但是我不知道如何在 Python 3 中以一种很好的 Pythonic 方式做同样的事情。我将回到大循环结构。
在 Python 3 中执行此操作的最佳方法是什么?
* 编辑 *错误信息:
这是我正在尝试做的一个例子: …
简单的例子:
class A():
a = 1
b = [a + i for i in range(3)]
Run Code Online (Sandbox Code Playgroud)
它会提高
NameError:未定义名称"a"
然而,
class A():
a = 1
b = a + 2
Run Code Online (Sandbox Code Playgroud)
作品.
什么是基本访问规则Python3?
我无法理解此Python调试程序会话中引发的以下异常:
(Pdb) p [move for move in move_values if move[0] == max_value]
*** NameError: name 'max_value' is not defined
(Pdb) [move for move in move_values]
[(0.5, (0, 0)), (0.5, (0, 1)), (0.5, (0, 2)), (0.5, (1, 0)), (0.5, (1, 1)), (0.5, (1, 2)), (0.5, (2, 0)), (0.5, (2, 1)), (0.5, (2, 2))]
(Pdb) max_value
0.5
(Pdb) (0.5, (0, 2))[0] == max_value
True
(Pdb) [move for move in move_values if move[0] == 0.5]
[(0.5, (0, 0)), (0.5, (0, 1)), (0.5, (0, …Run Code Online (Sandbox Code Playgroud) 我想创建一个类属性,它依赖于另一个类属性(我告诉类属性,而不是实例属性)。当此类属性是字符串时,如本主题所示,建议的解决方案
class A:
foo = "foo"
bar = foo[::-1]
print(A.bar)
Run Code Online (Sandbox Code Playgroud)
工作正常。但是,当类属性是列表或元组时,就像我的例子一样,以下代码不起作用......
x=tuple('nice cup of tea')
class A:
remove = ('c','o','a',' ')
remains = tuple(c for c in x if not c in remove)
print(A.remains)
Run Code Online (Sandbox Code Playgroud)
增加
Traceback (most recent call last):
File "[***.py]", line 3, in <module>
class A:
File "[***.py]", line 5, in A
remains = tuple(c for c in x if not c in remove)
File "[***.py]", line 5, in <genexpr>
remains = tuple(c for …Run Code Online (Sandbox Code Playgroud) 在类定义期间,定义为字典的类变量用于构建第二个字典类变量,这是从第一个缩减而来的子集,如下所示:
class C(object):
ALL_ITEMS = dict(a='A', b='B', c='C', d='D', e='E')
SUBSET_X = {k: v for k, v in ALL_ITEMS.items() if k in ('a', 'b', 'd')} # (this works)
SUBSET_Y = {k: ALL_ITEMS[k] for k in ('a', 'b', 'd')} # (this fails)
Run Code Online (Sandbox Code Playgroud)
非常简单的东西,但执行这段代码的最终效果让我感到非常惊讶。我的第一种方法是第 4 行的代码,但我不得不求助于第 3 行的解决方案。关于字典理解范围规则的一些微妙之处,我显然没有掌握。
具体来说,失败案例中引发的错误是:
File "goofy.py", line 4, in <dictcomp>
SUBSET_Y = {k: ALL_ITEMS.get(k) for k in ('a', 'b', 'd')}
NameError: name 'ALL_ITEMS' is not defined
Run Code Online (Sandbox Code Playgroud)
由于几个不同的原因,这个错误的性质让我感到困惑:
SUBSET_Y是一个格式良好的字典理解,并引用一个应该在范围内且可访问的符号。SUBSET_X),这也是一个字典理解,该符号ALL_ITEMS是完全明确且可访问的。因此,NameError …我有以下几点:
x = [1,2,3,4,5]
def foo(lbd:str, value):
ret_val = eval(lbd, globals(), locals())
print(ret_val)
Run Code Online (Sandbox Code Playgroud)
在此调用中使用 'value' 变量成功:
>>> foo("[i for i in value]",x)
[1, 2, 3, 4, 5]
Run Code Online (Sandbox Code Playgroud)
但是这个失败了:
>>> foo(r"any([x in value for x in {'',0,None,'0'}])", x)
Traceback (most recent call last):
File "<pyshell#171>", line 1, in <module>
foo(r"any([x in value for x in {'',0,None,'0'}])", x)
File "<pyshell#165>", line 2, in foo
ret_val = eval(lbd, globals(), locals())
File "<string>", line 1, in <module>
File "<string>", line 1, in <listcomp>
NameError: …Run Code Online (Sandbox Code Playgroud) name = 'Guido'
class MyClass:
name = 'Raymond'
list_1 = [name] * 3
list_2 = [name for i in range(3)]
@classmethod
def hello(cls):
return '{} says hello'.format(name)
Run Code Online (Sandbox Code Playgroud)
如果我这样做?它打印以下内容:
>>> print(MyClass.hello())
Guido says hello
>>> print(MyClass.list_1)
['Raymond', 'Raymond', 'Raymond']
>>> print(MyClass.list_2)
['Guido', 'Guido', 'Guido']
Run Code Online (Sandbox Code Playgroud)
我的问题是,
雷蒙德打招呼