当我调用一个函数时,我希望能够在函数中定义动态变量名,像这样…
def build_ports(portlist):
for idx, portname in enumerate(portlist):
chassis, slot, port = portname.split('/')
vartxt = "p%i" % idx
locals()[vartxt] = Port() # Class defining a port object
locals()[vartxt].port_method1(chassis, slot, port)
if idx > 5:
locals()[vartxt].port_method2() # Only call this object method, if idx > 5
但是我们都知道locals()
是只读的,不像globals()
…因此,当解释器看到locals()[vartxt]
时,它会停止…
在方法中定义动态变量而不污染全局命名空间(或者更糟的是,在方法中使用全局变量,而该方法中从未定义过全局变量)是否有任何方法?
使用列表代替这种叫做可变变量的疯狂方法。
def build_ports(portlist)
ports = []
for idx, portname in enumerate(portlist):
ports.append(Port())
ports[-1].port_method1()
if idx > 5:
ports[-1].port_method2()
而不是使用ports[-1]
,您可能会废弃未使用的portname
迭代变量并创建一个本地portname = Port()
,使用它来调用方法,然后在结束时将其附加到ports
。是什么 portlist
呢?
不,这不可能。如果你看一下Python是如何存储局部变量的,你就会明白为什么了。
全局变量存储在一个哈希表中,该哈希表是动态大小的,并且名称被编译成哈希键(在Python术语中,是内部字符串)。这使得全局查找相对"缓慢",但由于需要根据其他编译单元(模块)的名称查找全局变量,因此需要:
# a.py
x = 3
# b.py
import a
a.x = 4 # b needs to know how to find the same x!
局部变量存储在一个固定大小的数组中,变量名被编译成数组索引。
这可以在查看字节码时看到,其中local_load和STORE_FAST是本地的,而LOAD_GLOBAL和STORE_GLOBAL是全局的。它还会在您得到的不同异常中泄漏出来。全局变量逐渐上升,当没有找到时生成一个NameError,但是未定义的局部变量被一个空槽检测到,给出一个UnboundLocalError。
def foo():
a
a = 1
foo()
Traceback (most recent call last):
File "<stdin>", line 1, in foo
UnboundLocalError: local variable 'a' referenced before assignment
def foo():
a = 1
foo()
Traceback (most recent call last):
File "<stdin>", line 1, in foo
NameError: global name 'a' is not defined
由于数组的大小是固定的,并且大小是在编译函数时计算的,因此不能创建任何额外的局部变量。
如果你需要更多的"locals",你需要将值存储为对象的命名属性或存储在字典中;
查看exec
编辑:是的,我的意思是执行。