在Python中重用变量

在Python中重用变量,python,Python,在Python中,我经常以类似以下方式重用变量: files = files[:batch_size] 我喜欢这种技术,因为它可以帮助我减少需要跟踪的变量数量 从未遇到过任何问题,但我想知道我是否遗漏了潜在的缺点,例如性能等。关于该特定示例的一些信息:如果您只想迭代、映射或过滤结果,可以使用生成器来避免阵列副本: import itertools files = itertools.islice(files, batch_size) 至于一般情况:您是将新值分配给一个已经存在的名称还是一个新

在Python中,我经常以类似以下方式重用变量:

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!对于任何被否决的人:我希望有人能解释一下原因,以便我能纠正它。