为什么此分配的对象与原始对象共享相同的存储空间? [英] Why does this assigned object share the same memory space as the original object?

查看:93
本文介绍了为什么此分配的对象与原始对象共享相同的存储空间?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在python中,在使用itertools groupby模块时遇到了这种奇怪的现象.

在python中,变量分配意味着向新变量分配自己的内存,而不是指向原始内存的指针(据我了解,如果不正确,请告知我):

y = 7
x = y    
y = 9

x will still be 7

但是,当我使用groupby模块时,我正在使用该模块将具有相同密钥的项目归为一组.我想要两个组,因为在原始组上重复是没有用的,因为内存已经被修改了.示例:

for key, group in groupby(rows, lambda x: x[0]):

    data = [thing[1] for thing in group] #accesses 1st attribute of element
    data2 = [thing[2] for thing in group] # would yield [] as group is empty

因此,我尝试了以下方法:

for key, group in groupby(rows, lambda x: x[0]):
    #create a copy of group to reiterate over
    toup = group

    print toup #<itertools._grouper object at 0x1039a8850>
    print group #<itertools._grouper object at 0x1039a8850>

    data = [thing[1] for thing in group] #accesses 1st attribute of element
    data2 = [thing[2] for thing in toup]

data2应该访问第二项,但会产生[],因为它们都共享相同的内存

我的问题是为什么会这样?不应该将组分配给toup意味着toup在不同的十六进制地址位置会拥有组内存的副本吗?

还有什么可以解决这个问题的方法,这样我就不必编写两个groupby迭代了?

解决方案

您声明:

在python中,变量分配意味着将新变量分配为其 自己的内存,而不是指向原始内存的指针(来自我的 了解是否不正确,请通知我):

那是不正确的. Python名称可以具有(有时)类似于C变量的方面,也可以具有(有时)类似于C指针的方面.试图说他们像另一个一样,只是令人困惑.别.认为它们是Python的独特和习惯用法.

Python变量"应该更多地被视为名称.即使您不打算引用同一内存位置,也可能有多个 .

示例:

>>> y=7
>>> x=7
>>> x is y
True
>>> id(x)
140316099265400
>>> id(y)
140316099265400

并且(由于实习,以下可能是的,有关短整数的实习,请参见 PEP 237 .实施细节):

>>> x=9
>>> y=5+4
>>> x is y
True

如果通过比较它们的内存地址,这两个对象是相同的对象,则Python is运算符将返回True. id函数返回该地址.

最后一个例子:

>>> li1=[1,2,3]
>>> li2=[1,2,3]
>>> li1==li2
True
>>> li1 is li2
False

即使li1 == li2,它们也必须是单独的列表,否则,如果您更改一个列表,则两者都将更改,如本例所示:

>>> li1=[1,2,3]
>>> li2=li1
>>> li1.append(4)
>>> li2
[1, 2, 3, 4]
>>> li1==li2
True
>>> li1 is li2
True

(请务必理解另一个经典错误所有Python程序员迟早都会犯的错误.这是由多次引用引起的到单个可变对象,然后期望一个引用的行为像单个对象一样.)

正如jonrsharpe在评论中指出的那样,请阅读Ned Batchelders优秀的有关Python名称和值的事实和神话如何像Pythonista那样思考以获得更详细的概述. >

In python I came across this strange phenomena while working with itertools groupby module.

In python, variable assignment means assigning the new variable its own memory instead of a pointer to the original memory (from my understanding if this is incorrect please let me know):

y = 7
x = y    
y = 9

x will still be 7

Yet when I was working with groupby module, I was using this module to group items that had the same key into one group. I wanted two groups since reiterating over the original group was useless as the memory would have already been modified. Example:

for key, group in groupby(rows, lambda x: x[0]):

    data = [thing[1] for thing in group] #accesses 1st attribute of element
    data2 = [thing[2] for thing in group] # would yield [] as group is empty

So I tried this instead:

for key, group in groupby(rows, lambda x: x[0]):
    #create a copy of group to reiterate over
    toup = group

    print toup #<itertools._grouper object at 0x1039a8850>
    print group #<itertools._grouper object at 0x1039a8850>

    data = [thing[1] for thing in group] #accesses 1st attribute of element
    data2 = [thing[2] for thing in toup]

data2 should access the 2nd item but yields [] since they both share the same memory

My question is why does this happen? Shouldn't assigning group to toup means toup would have a copy of groups memory at a different hex address location?

Also what can I do to circumvent this problem so I don't have to write two groupby iterations?

解决方案

You state:

In python, variable assignment means assigning the new variable its own memory instead of a pointer to the original memory (from my understanding if this is incorrect please let me know):

That is incorrect. Python names can have aspects that (at time) are like C variables and can also have aspects that (at times) are like C pointers. To try and say they are like one or the other is just confusing. Don't. Consider them as unique and idiomatic to Python.

Python 'variables' should more be thought of as names. More than one may refer to the same memory location even if you did not intend them to.

Example:

>>> y=7
>>> x=7
>>> x is y
True
>>> id(x)
140316099265400
>>> id(y)
140316099265400

And (due to interning, the following may be true. See PEP 237 regarding interning of short ints, but this is an implementation detail):

>>> x=9
>>> y=5+4
>>> x is y
True

The Python is operator returns True if the two are the same objects by comparing their memory address. The id function returns that address.

Consider as a final example:

>>> li1=[1,2,3]
>>> li2=[1,2,3]
>>> li1==li2
True
>>> li1 is li2
False

Even though li1 == li2, they have to be separate lists otherwise both would change if you change one, as in this example:

>>> li1=[1,2,3]
>>> li2=li1
>>> li1.append(4)
>>> li2
[1, 2, 3, 4]
>>> li1==li2
True
>>> li1 is li2
True

(Be sure to understand another classic mistake all Python programers will make sooner or later. This is caused by multiple references to a single mutable object and then expecting one reference to act like a single object.)

As jonrsharpe pointed out in the comments, read Ned Batchelders excellent Facts and myths about Python Names and Values or How to Think Like a Pythonista for more detailed overview.

这篇关于为什么此分配的对象与原始对象共享相同的存储空间?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆