简体   繁体   English

如何定义可变组?

[英]How to define groups of mutables?

Lists are a mutable data type.列表是一种可变数据类型。 If I have sublists inside a 2d list that have multiple references to the same object, the fact that changing any one makes changes in others suggests a question: am I able to extract information about linked sublists?如果我在 2d 列表中有多个对同一对象的引用的子列表,那么更改任何一个都会对其他对象进行更改这一事实提出了一个问题:我是否能够提取有关链接子列表的信息?

To explain, let's consider a 2d list:为了解释,让我们考虑一个二维列表:

import random
lst = [[0] for i in range(9)]  # create list of 9 sublists with value inside
lst
[[0], [0], [0], [0], [0], [0], [0], [0], [0], [0]] .

Each sublist pointing to the same object 0 , but independently.每个子列表都指向同一个对象0 ,但相互独立。 If any given sublist's contents change, the other sublists contents will remain stable.如果任何给定子列表的内容发生变化,其他子列表的内容将保持稳定。 The fact that all IDs are different proves this point:所有ID都不同的事实证明了这一点:

[id(i) for i in lst]
[139963231930640, 139963235043920, 139963236442592, 139963222312992, 139963783242688, 139963234936784, 139963233636256, 139963233634176, 139963233635056] .

Now let's create a random sample of objects:现在让我们创建一个随机的对象样本:

indcs = random.sample(range(9), 9)    

and then modify the sublists using the following function:然后使用以下函数修改子列表:

def mutables(a):
    for i in range(len(a) - 1):
        lst[a[i+1]] = lst[a[i]]
        lst[a[i]][0] += 1

mutables(indcs[:3])
mutables(indcs[3:6])
mutables(indcs[6:])

lst
[[2], [2], [2], [2], [2], [2], [2], [2], [2]] .

The list now contains 3 groups of 3 sublists, each element of a group pointing to the same object.该列表现在包含 3 个组,每组 3 个子列表,组中的每个元素都指向同一个对象。 There are only 3IDsx3 in lst : lst中只有 3IDsx3 :

[id(i) for i in lst]
[139963231930640, 139963235043920, 139963236442592, 139963235043920, 139963236442592, 139963231930640, 139963235043920, 139963231930640, 139963236442592] .

If we change, eg, the third element of a list, it changes each element of a group:如果我们改变,例如,列表的第三个元素,它会改变组的每个元素:

lst[2][0] += 1
lst
[[2], [2], [3], [2], [3], [2], [2], [2], [3]] .

Here, the sublists (2,4,8) are changed.在这里,子列表 (2,4,8) 发生了变化。 The 2nd(0,5,7) and 3rd(1,3,6) groups behave the same way: 2nd(0,5,7) 和 3rd(1,3,6) 组的行为方式相同:

lst[0][0] += 1
lst
[[3], [2], [3], [2], [3], [3], [2], [3], [3]]
lst[1][0] += 1
lst
[[3], [3], [3], [3], [3], [3], [3], [3], [3]] .

The change of an integer values inside sublists did not change IDs:子列表中整数值的更改不会更改 ID:

[id(i) for i in lst]
    [139963231930640, 139963235043920, 139963236442592, 139963235043920, 139963236442592, 139963231930640, 139963235043920, 139963231930640, 139963236442592],

but adding 1 every time a new group member arrives provides useful information on the group size.但是每次有新的组成员到达时加1可以提供有关组大小的有用信息。

The crux of my question is, while the information about link between the sublists is retained, how to extract the indices of each group ((2,4,8),(0,5,7),(1,3,6)) without needing to refer to indcs and how it was originally grouped: [:3:6:] ?我的问题的症结是,在保留有关子列表之间链接的信息的同时,如何提取每个组的索引 ((2,4,8),(0,5,7),(1,3,6) ) 无需参考indcs以及它最初是如何分组的: [:3:6:] I could change the 1st sublist value, track changes in others and pop them in a loop, but this information should be implicitly available on the basis of which an element in a group mutates.我可以更改第一个子列表的值,跟踪其他人的更改并在循环中弹出它们,但是这些信息应该是隐式可用的,基于组中的元素发生变异。 Is there any way to collect it?有什么方法可以收集吗? Eg, I can get id(name) of a sublist and try to find linked sublists by one of the methods in described here or here , but these options return values, not their names.例如,我可以获取子列表的id(name)并尝试通过此处或此处描述的方法之一查找链接的子列表,但这些选项返回值,而不是它们的名称。

I think you have some confusion about where the mutability of lists that you're dealing with lays.我认为您对您正在处理的列表的可变性所在的位置有些困惑。

>>> class Obj:
...   name: str = None
...   def __init__(self, name):
...     self.name = name
...
>>> o = Obj("Athena")
>>> o.name
'Athena'
>>> a = Obj("Athena")
>>> b = Obj("Bacchus")
>>> c = Obj("Clotho")
>>>
>>> la = [a, b]
>>> lb = [a, b]
>>> ls = [la, lb]
>>> for sublist in ls:
...   for item in sublist:
...     print(f"{item.name}")
...
Athena
Bacchus
Athena
Bacchus
>>> ls[0][0] = c
>>> for sublist in ls:
...   for item in sublist:
...     print(f"{item.name}")
...
Clotho
Bacchus
Athena
Bacchus

This demonstrates that if you create the sublists individually, even if the objects that are the elements of that list are the same, the sublists are separate mutable objects, and changing one does not mean changing the others.这表明,如果您单独创建子列表,即使作为该列表元素的对象相同,子列表也是独立的可变对象,更改一个并不意味着更改其他对象。

Consider, instead:考虑一下:

>>> la = [a, b]
>>> ls = [la, la]
>>> for sublist in ls:
...   for item in sublist:
...     print(f"{item.name}")
...
Athena
Bacchus
Athena
Bacchus
>>> ls[0][0] = c
>>> for sublist in ls:
...   for item in sublist:
...     print(f"{item.name}")
...
Clotho
Bacchus
Clotho
Bacchus

Here we see that if we use the same sublist, la , when we change one sublist we change another sublist.在这里我们看到,如果我们使用相同的子列表la ,当我们更改一个子列表时,我们会更改另一个子列表。 To take this a step further:更进一步:

>>> lb = [a, c]
>>> ls[1] = lb
>>> for sublist in ls:
...   for item in sublist:
...     print(f"{item.name}")
...
Athena
Bacchus
Athena
Clotho
>>> ls[0][0] = d
>>> for sublist in ls:
...   for item in sublist:
...     print(f"{item.name}")
...
Demosthenes
Bacchus
Athena
Clotho

Here, we've pointed the second element of the outer list to a new list.在这里,我们将外部列表的第二个元素指向了一个新列表。 Now when we change an element of the first sublist, it does not change the second sublist.现在,当我们更改第一个子列表的元素时,它不会更改第二个子列表。 This makes sense, because these are different lists.这是有道理的,因为这些是不同的列表。

The upshot here is that each element of a list points to a single object.这里的结果是列表的每个元素都指向一个对象。 Multiple elements can point to the same object.多个元素可以指向同一个对象。 So, for your outer list, you can have multiple elements point to the same object, a sublist, and for any such sublist changes to that sublist will be visible in any other element of the outer list that points to the same sublist object.因此,对于您的外部列表,您可以让多个元素指向同一个对象,一个子列表,并且对于任何此类子列表,对该子列表的更改将在外部列表中指向同一子列表对象的任何其他元素中可见。 But only so long as that is the case.但只要是这样。

And this is where your reasoning in your question doesn't quite make sense:这就是您在问题中的推理不太合理的地方:

>>> lb = [a, b]
>>> ls = [la, lb, la]
>>> for sublistA in ls:
...   for sublistB in ls:
...     print("Equal") if sublistA is sublistB else print("Not equal")
...
Equal
Not equal
Equal
Not equal
Equal
Not equal
Equal
Not equal
Equal

Here we see that although la and lb are equivalent, they are not the same object.这里我们看到虽然lalb是等价的,但它们不是同一个对象。 And really, all you're doing in your complicated example is shuffling around where you add the sublist object to your outer list.实际上,您在复杂示例中所做的所有事情都是在将子列表对象添加到外部列表的位置进行改组。 Something akin to:类似于:

>>> ls = [la, lb, lb, la]
>>> ls[0][0] = c
>>> for sublist in ls:
...   for item in sublist:
...      print(f"{item.name}")
...
Clotho
Bacchus
Athena
Bacchus
Athena
Bacchus
Clotho
Bacchus

This has nothing to do with the 'groups' you're putting them in, it's just that each element in the outer list is referencing a particular list object.这与您将它们放入的“组”无关,只是外部列表中的每个元素都引用了一个特定的列表对象。 That is where the 'implicit tracking' is occurring, and you can get at that information by using a comparison as I did.这就是发生“隐式跟踪”的地方,您可以像我一样通过比较来获得该信息。 Because a list is not hashable, it's difficult to do a reverse lookup dictionary without creating a wrapper for the list, and it's expensive to do the object comparison every time (and not the difference between is and == in comparing two objects, especially lists!).因为列表是不可散列的,所以如果不为列表创建包装器就很难进行反向查找字典,并且每次进行对象比较都是昂贵的(而不是比较两个对象,尤其是列表时is==之间的区别!)。 Apart from those two options - keeping a separate variable that tracks the indices of each unique object (in this case, each sublist that has itself multiple elements) - there isn't a lot you can do that would be avoiding the work you're trying to avoid.除了这两个选项 - 保留一个单独的变量来跟踪每个唯一对象的索引(在这种情况下,每个子列表本身都有多个元素) - 你可以做的事情不多,可以避免你正在做的工作试图避免。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在正则表达式中定义几个浮点组? - How to define several float groups in a regular expression? 如何使用configobj定义和选择值组? - How to define and select groups of values using configobj? 生成不同的空变量列表 - Generate a list of distinct empty mutables 了解涉及可变的函数范围 - Understanding function scopes when it comes to mutables Python:向函数内的可变参数添加属性 - Python: Adding attributes to mutables inside a function 创建一个散列在 Pandas 中定义组 - Create a hash do define groups in pandas 如何在 Django 中定义和引用自定义用户组,我可以像 user.is_superuser 一样对其进行排序? - How can I define and refer to custom user groups in Django that I can sort against like user.is_superuser? argparse:如何声明几组 arguments 对一个子命令互斥? 如何定义几种使用子命令的方式? - Argparse: How to declare several groups of arguments to be mutually exclusive for one sub-command? How to define several ways of using a sub-command? python正则表达式使用捕获组来定义另一个组长度{} - python regex use capture group to define another groups length { } 定义默认组和权限的最简单方法是什么? - What's the simplest way to define default groups and permissions?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM