Python: create a list of object references

I want to clear the code that I wrote to scale the scale of what I'm trying to do. To do this, I would like to ideally create a list of links to objects so that I can systematically set objects using a loop without actually placing the objects in the list. I read about how Python handles links and passes them, but have not yet found a way to do this efficiently.

To better demonstrate what I'm trying to do:

I use bokeh and want to customize a large number of boxes of choice. Each block is as follows

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

Customizing each choice is in order when I have only a few, but when I have 20, my code becomes very long and cumbersome. What I would like to do is a sample_list = [select_one_name, select_two_name, etc] list, which I then scroll to set values ​​for each select_one_name , select_two_name , etc. However, I want to get the select_one_name link to still point to the correct value, and not to necessarily refer to the value by calling sample_list[0] .

I'm not sure if this is possible - if there is a better way to do this than to create a list of links, please let me know. I know that I could just create a list of objects, but I try to avoid this.

For reference, I'm on Python 2.7, Anaconda distribution, Windows 7. Thanks!


To follow @Alex Martelli's post below:

The reason I thought this might not work is because when I tried the mini test with a list of lists, I did not get the desired results. To demonstrate

 x = [1, 2, 3] y = [4, 5, 6] test = [x, y] test[0].append(1) 

The results are in x = [1, 2, 3, 1] , but instead I use test[0] = [1, 2] , then x remains [1, 2, 3] , although test itself reflects this change.

Drawing a parallel to my initial example, I thought that I would see the same results as from installation to equal. This is not true?

0
source share
2 answers

Each Python list always an internal reference array (in CPython, which no doubt you use, at C level it is an array of PyObject* - "pointers to Python objects").

No copies of objects are created implicitly: rather (again, in CPython), each counter of object references increases when you add an “object” to the list (actually a link to it). In fact, when you need a copy of an object, you need to specifically request it (using the copy module as a whole or sometimes using type copy methods).

Multiple references to the same object are internal pointers to the same memory. If an object is modified, then its mutation is reflected in all references to it. Of course, there are immutable objects (strings, numbers, tuples, ...) to which such a mutation cannot be applied.

So when you do this for example

 sample_list = [select_one_name, select_two_name, etc] 

each of the names (as long as it is in scope) still refers to the exact same object as the corresponding element in sample_list .

In other words, using sample_list[0] and select_one_name completely equivalent if both references to the same object exist.

In the IOW square, your stated goal has already been fulfilled by Python's most fundamental semantics. Now, please edit Q to clarify what behavior you are observing, which seems to contradict this, compared to the behavior that you think you should observe (and desire), and we may be able to help further , because at this point, all the above observations mean that “you get exactly the semantics that you ask for,” so “steady when it goes” - that’s all I can practically offer!)

Added (better here in the answer than a little lower in the comments :-): pay attention to the work of mutations. The OP tried test[0]= somelist , then test[0].append and saw that somelist mutated accordingly; then I tried test[0] = [1, 2] and was surprised to change somelist not . But this is because assignment for a link is not a mutational operation on the object that the link refers to! This is just a re-seats link, decreases the reference count of previous objects and what it is.

If you want to mutate an existing object (which should be modified first, but <<20>), you need to perform mutating operations on it (through any link, not the case). For example, in addition to append and many other named methods, one mutating operation in the list is the slice assignment, including the slice of the entire list, designated as [:] . Thus, test[0][:] = [1,2] actually mutates somelist - very different from test[0] = [1,2] , which assigns a slice not .

+7
source

This is not recommended, but it works.

 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'] ) 

You can use select_one_name, select_two_name, etc. directly, because they are set in the local area due to the special locals () list. A cleaner approach is to use a dictionary like

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

And the selects['select_one_name'] link in your code, and you can iterate through selects.keys() or selects.items() .

0
source

All Articles