Python:创建对象引用列表

时间:2015-01-28 15:46:02

标签: python python-2.7

我想清理一些我写过的代码,以便扩大我尝试做的事情的规模。为了做到这一点,我想理想地创建一个对象的引用列表,这样我就可以使用循环系统地设置对象,而不必将对象放在列表中。我已经了解了Python处理引用和传递的方式,但还没有找到一种方法来有效地完成这项工作。

为了更好地展示我尝试做的事情:

我使用散景,并希望设置大量选择框。每个框都是这样的

select_one_name = Select(
     title = 'test',
     value = 'first_value',
     options = ['first_value', 'second_value', 'etc']
)

设置每个选择都很好,当我只有几个时,但是当我有20个时,我的代码变得非常冗长和笨拙。我希望能够做的是,我有一个sample_list = [select_one_name, select_two_name, etc]列表,然后我可以循环,设置每个select_one_nameselect_two_name等的值。但是,我希望我的引用select_one_name仍然指向正确的值,而不是通过调用sample_list[0]来引用该值。

我不确定这是否可行 - 如果有更好的方法,而不是创建参考列表,请告诉我。我知道我可以创建一个对象列表,但我试图避免这种情况。

供参考,我在Python 2.7,Anaconda发行版,Windows 7上。谢谢!


跟进@Alex Martelli的帖子:

我认为这可能不起作用的原因是因为当我尝试使用列表列表进行小型测试时,我没有得到我想要的结果。演示

x = [1, 2, 3]
y = [4, 5, 6]

test = [x, y]
test[0].append(1)

x = [1, 2, 3, 1]中的结果,但相反,我使用test[0] = [1, 2],然后x仍为[1, 2, 3],尽管test本身反映了这一变化。

回到我原来的例子,我想我会看到与设置相同的结果。这不是真的吗?

2 个答案:

答案 0 :(得分:8)

每个Python list 总是在内部是一个引用数组(在CPython中,毫无疑问你正在使用它,在C级别它是{{1}的数组 - “指向Python对象的指针”。

没有隐式地创建对象的副本:而是(再次,在CPython中)当您将“对象”(实际上是对它的引用)添加到列表时,每个对象的引用计数都会增加。事实上,当你想要一个对象的副本时,你需要特别要求一个(通常使用PyObject*模块,或者有时使用特定于类型的复制方法)。

对同一对象的多个引用是指向完全相同内存的内部指针。如果一个对象是可变的,那么对它进行变异会通过对它的所有引用进行反映。当然,有不可变的对象(字符串,数字,元组,...),这种变异不适用于此。

所以当你这样做时,例如,

copy

每个名称(只要它在范围内)仍然引用与sample_list = [select_one_name, select_two_name, etc] 中相应项目完全相同的对象。

换句话说,只要存在对同一对象的两个引用,使用sample_listsample_list[0]就完全等效。

IOW平方,你声明的目的已经已经完成了Python最基本的语义。现在,请编辑Q以澄清您观察到的哪种行为似乎与此相矛盾,与您认为您应该观察(和期望)的行为相对应,我们可以进一步提供帮助 - - 因为到目前为止,所有上述观察都相当于“你得到了你所要求的语义”,所以“随着时间的推移”是“我可以实际建议的!” -

添加(在答案中更好,而不是在下面的评论:-):注意关注变异操作。 OP尝试select_one_name后跟test[0]= somelist并看到test[0].append相应变异;然后尝试somelist并惊讶地发现test[0] = [1, 2] 已更改。但那是因为赋值到引用不是对象的变异操作,表示引用用于指示!它只是somelist引用,递减先前引用的对象的引用计数,就是这样。

如果你想改变一个现有的对象(首先需要一个可变的对象,但re-seats满足那个),你需要对它进行变异操作(通过任何参考,不没问题。例如,除了list和许多其他命名方法之外,列表上的一个变异操作是分配给切片,包括表示为append的整个列表切片。因此,[:]实际上会改变test[0][:] = [1,2] - 非常somelist不同的test[0] = [1,2]分配给参考,到切片

答案 1 :(得分:0)

不推荐这样做,但它确实有效。

sample_list = ["select_one_name", "select_two_name", "select_three_name"]
for select in sample_list:
    locals()[select] = Select(
        title = 'test',value = 'first_value',
        options = ['first_value', 'second_value', 'etc']
    )

您可以直接使用select_one_name,select_two_name等,因为它们是由于特殊的locals()列表而在本地范围内设置的。 更简洁的方法是使用字典,例如

selects = {
    'select_one_name': Select(...),
    'select_two_name': Select(...),
    'select_three_name': Select(...)
}

在您的代码中引用selects['select_one_name'],您可以迭代selects.keys()selects.items()