在方法中动态定义局部变量的最佳方法是什么?



当我调用一个函数时,我希望能够在函数中定义动态变量名,像这样…

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

编辑:是的,我的意思是执行。

最新更新