在Python中重用变量
在Python中,我经常以类似以下方式重用变量:在Python中重用变量,python,Python,在Python中,我经常以类似以下方式重用变量: files = files[:batch_size] 我喜欢这种技术,因为它可以帮助我减少需要跟踪的变量数量 从未遇到过任何问题,但我想知道我是否遗漏了潜在的缺点,例如性能等。关于该特定示例的一些信息:如果您只想迭代、映射或过滤结果,可以使用生成器来避免阵列副本: import itertools files = itertools.islice(files, batch_size) 至于一般情况:您是将新值分配给一个已经存在的名称还是一个新
files = files[:batch_size]
我喜欢这种技术,因为它可以帮助我减少需要跟踪的变量数量
从未遇到过任何问题,但我想知道我是否遗漏了潜在的缺点,例如性能等。关于该特定示例的一些信息:如果您只想迭代、映射或过滤结果,可以使用生成器来避免阵列副本:
import itertools
files = itertools.islice(files, batch_size)
至于一般情况:您是将新值分配给一个已经存在的名称还是一个新名称,应该完全没有区别(至少从解释器/虚拟机的角度来看)。两种方法产生几乎完全相同的字节码:
Python 2.7.2 (default, Nov 21 2011, 17:25:27)
[GCC 4.6.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import dis
>>> def func1(files):
... files = files[:100]
...
>>> def func2(files):
... new_files = files[:100]
...
>>> dis.dis(func1)
2 0 LOAD_FAST 0 (files)
3 LOAD_CONST 1 (100)
6 SLICE+2
7 STORE_FAST 0 (files)
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
>>> dis.dis(func2)
2 0 LOAD_FAST 0 (files)
3 LOAD_CONST 1 (100)
6 SLICE+2
7 STORE_FAST 1 (new_files)
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
在Python3中也可以看到同样的情况
事实上,
func1
甚至可以更快一点,因为名称文件
以前已经出现过,并且可能已经存在于一些变量查找缓存中。重用变量名称在技术上没有任何缺点。但是,如果重用变量并更改其“用途”,则可能会使阅读代码的其他人感到困惑(特别是如果他们错过了重新分配)
不过,在您提供的示例中,您应该意识到,当您拼接时,实际上正在生成一个全新的列表。在GC收集该列表的旧副本之前,该列表将存储在内存中两次(您拼接出来的内容除外)。另一种方法是迭代该列表并在到达
batch\u size
th元素时停止,而不是完成该列表,或者更简洁地说,del files[batch\u size::
重用变量确实不会有很多缺点,但也不会有很多优点。Python GC无论如何都必须运行以收集旧对象,因此重写变量时不会立即获得内存,这与C等静态编译语言不同,在C等静态编译语言中,重用变量会阻止完全为新对象分配内存
此外,您可能会让任何未来的代码读者感到困惑,他们通常希望新对象有新名称(垃圾收集语言的副产品)。缺点是,您不能使用:
file_rest = files[batch_size:]
关于性能,没有缺点。相反,您甚至可以通过避免相同名称空间中的哈希冲突来提高性能
在另一种情况下,关于这一点有一种说法。我看不出这里有什么问题。可与之比较的替代方案是什么?使用第二个变量,如
files=XYZ;文件头=文件[:批量大小]
?为什么会有什么不同呢?另一种选择是:新的文件集=文件[:批大小]你会马上注意到主要的一个:嘿!我仍然需要文件
的旧值!。另一种方法是使用大量的额外变量unused1=files[0]
,unused2='foobar'
,'unused3=-1,
veryunuuse=None`。事实上,这并不能使代码非常可读。但有人可能会喜欢它。说真的,你的问题是什么?我能问你有什么区别会使这不同吗?@Rik:我认为这是受影响的局部变量的索引(0
,在第一种情况下,因为这是第一个访问的变量,1
,在第二种情况下)。不过,我不是100%确定。+1关于如何避免创建新对象(尽管它可能不太可读?)@cheeken:另一种选择(可能是最具Pythonic的选择)是使用itertools.islice
。很好,NiklasBaumstark!对于任何被否决的人:我希望有人能解释一下原因,以便我能纠正它。