【问题标题】:manipulation of a variable containing large data操作包含大数据的变量
【发布时间】:2013-12-24 12:37:41
【问题描述】:

在 python 中,我使用一个变量来存储大量数据——大约 1GB。我对此数据进行各种操作,包括截断它。我还需要跨多个功能执行这些操作 - 截断等,也就是说。在我看来,这是对全局变量的合法使用,因为在函数之间将变量作为局部变量传递会涉及内存重复,因此速度会变慢。我也很难将变量分解成更小的块,因为数据不是恒定长度。

有人可以告诉我使用全局变量是否是正确的方法吗?还是有更好的方法?

这里有一些基本的示例代码供参考:

fp = open(filename, 'rb')
bytes = fp.read(1000000000)

def ops1():
  global bytes
  parsed = {}
  i = 0
  while len(bytes):
    parsed[i] = bytes[ : 400]
    bytes = bytes[400 :] # truncate
    parsed[i + 1] = ops2()
    i += 2
    ...more truncating and parsing...

def ops2():
  global bytes
  ...more truncating and parsing...

ops1()

【问题讨论】:

  • 你从哪里知道调用函数会导致复制?
  • 我自己的想象 :P 我的推理是:(1)一个在本地修改一个变量而不返回它的函数必须创建一个副本,(2)python解释器不会向前看是否一个函数返回一个变量,(3) 因此,无论何时在函数中修改局部变量,python 都必须自动创建局部变量的副本。如果(2)是错误的,那么(3)也将是错误的。从你所说的听起来,python 解释器确实会检查函数是否返回局部变量来决定是否复制这个变量?
  • 好吧,我知道你是从哪里来的。事实上,在底层存在复制,因为 python 是按值调用的。但是,复制的不是底层数据,而是对对象的引用。实际数据驻留在堆上,不会被函数调用复制。因此,正确地说变量只包含对值的引用,而不是值。

标签: python python-2.7 memory


【解决方案1】:

Python 传递引用;参数和局部变量,只要您不创建大的新局部值(通过重新绑定或复制),局部与全局就没有区别。

一个函数肯定不会被传递一个值的新副本,除非你明确地首先创建一个副本,然后将那个传递给一个函数。

bytes 作为函数的参数而不是使用全局参数不会对内存使用产生影响,但使取消引用名称​​更快(稍微)。

由于bytes 是一个列表,您可以随时就地操作它;您可以直接从中删除索引,或分配给标识切片以不重新绑定但缩小列表本身:

del bytes[:400]  # remove first 400 elements

bytes[:] = bytes[400:]  # replace *all* indices in `bytes` with everything but the first 400

【讨论】:

  • 说只使用局部变量,如果bytes 被传递给ops2 并且ops2 修改bytes 那么ops1 肯定有一个不同的局部值bytes ?否则bytes 将是一个全局变量,但变量在 python 中默认是局部变量。
  • 不,因为正如 martijn 所说,reference 已通过。如果 ops2 对其进行修改,则 ops1 将看到相同的更改。
  • 如果我错了请纠正我,但只有当ops2 返回bytes 变量时,两个局部变量才会引用相同的内存位置?如果是这样,那么在修改bytes 变量之前,python 必须提前查看它是否返回到ops1 的范围内。我想我的假设是 python 没那么聪明;)
  • @mulllhausen:我明白你的意思,但你可以就地操作列表对象。给出的例子。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-07
  • 2019-11-12
相关资源
最近更新 更多