Python Store dynamic data - python

I don't know if the heading makes sense... but this is what I am trying to do using list
>>> x = 5
>>> l = [x]
>>> l
[5]
>>> x = 6
>>> l
[5] # I want l to automatically get updated and wish to see [6]
>>>
The same happens with dict, tuple. Is there a python object that can store the dynamic value of variable?
Thanks,

There's no way to get this to work due to how the assignment operator works in Python. x = WHATEVER will always rebind the local name x to WHATEVER, without modifying what previously x was previously bound to.(*)
You can work around this by replacing the integers with a container data type, such as single-element lists:
>>> x = [5]
>>> l = [x]
>>> l
[[5]]
>>> x[0] = 6
>>> l
[[6]]
but that's really a hack, and I wouldn't recommend it for anything but experimentation.
(*) Rebinding may actually modify previously bound objects when their reference count drops to zero, e.g. it may close files. You shouldn't rely on that, though.

A variable is a place to store data. A datastructure is a place to store data. Pick the one which meets your needs.

You can do it with the numpy module.
>>> from numpy import array
>>> a = array(5)
>>> a
array(5)
>>> l = [a]
>>> l
[array(5)]
>>> a.itemset(6)
>>> a
array(6)
>>> l
[array(6)]
Generally a 0-D numpy array can be treated as any regular value as shown below:
>>> a + 3
9
However, if you need to, you can access the underlying object as such:
>>> a.item()
6
Here's a kind of hacky method of dynamic access that isn't very extensible/flexible in its given form, but could be used as a basis for something better.
>>> a = 7
>>> class l:
def a_get(self):
global a
return a
def a_set(self, value):
global a
a = value
a = property(a_get, a_set)
>>> c = l()
>>> c.a
7
>>> a = 4
>>> c.a
4
>>> c.a = 6
>>> a
6

Related

Co-assigning python variables works different with integers and sets. Why?

Suppose I co-assign two python variables to zero:
>>> x = y = 0
When I now assign to one value it changes independently of the other:
>>> y = 2
>>> x
0
>>> y
2
Now suppose I co-assign two python variables to an empty set:
>>> a = b = set([])
When I now add to one set, it changes the value of the other. Why?
>>> b.add(2)
>>> a
set([2])
>>> b
set([2])
As commments to OP answer are just implicit clues I am making them explicit:
y = 0
x = y
Names x and y reference the same int object with 0 value.
int objects are immutable. As you can't alter them, it actually doesn't
matter what object with zero value you are pointing to, if there were several.
When you assign y again with
y = 2
y now refers to a different int object with value 2.
x still refers to the old 0 value object.
If you consider mutable types like sets,
b = set()
a = b
a and b reference the same empty set object.
If you change the set object with an in-place assignment, or using an object method that changes it in-place, the object remains the same (but with its value content changed).
So you can see the changed object either through a or through b.
However, to compare apples with apples and follow the int sample, if you make
b = set() # a new empty set
b becomes a new different set empty object, while a still references the original.
>>> a = set()
>>> b = a
>>> id(a) == id(b)
True
>>> b = set()
>>> id(a) == id(b)
False
>>>
So behaviour is actually the same in both cases. But in int case you can't make changes to the object value.

How does variable copying in Python exactly work?

Why is it that:
>>> a = 1
>>> b = a
>>> a = 2
>>> print(a)
2
>>> print(b)
1
...but:
>>> a = [3, 2, 1]
>>> b = a
>>> a.sort()
>>> print(b)
[1, 2, 3]
I mean, why are variables really copied and iterators just referenced?
Variables are not "really copied". Variables are names for objects, and the assignment operator binds a name to the object on the right hand side of the operator. More verbosely:
>>> a = 1 means "make a a name referring to the object 1".
>>> b = a means "make b a name referring to the object currently referred to by a. Which is 1.
>>> a = 2 means "make a a name referring to the object 2". This has no effect on which object anything else that happened to refer to 1 now refers to, such as b.
In your second example, both a and b are names referring to the same list object. a.sort() mutates that object in place, and because both variables refer to the same object the effects of the mutation are visible under both names.
Think of the assigned variables as pointers to the memory location where the values are held. You can actually get the memory location using id.
a = 1
b = a
>>> id(a)
4298171608
>>> id(b)
4298171608 # points to the same memory location
a = 2
>>> id(a)
4298171584 # memory location has changed
Doing the same with your list example, you can see that both are in fact operating on the same object, but with different variables both pointing to the same memory location.
a = [3, 2, 1]
b = a
a.sort()
>>> id(a)
4774033312
>>> id(b)
4774033312 # Same object
in your first example you've reassigned a's value after making b's value a. so a and b carry different values.
the same would've occurred in your second example if you had reassigned a to a new sorted list instead of just sorting it in place.
a = [3,2,1]
b = a
a.sort()
print b
[1,2,3]
but...
a = [3,2,1]
b = a
sorted(a)
print b
[3,2,1]

Difference between assignment of a variable to a number and lists of numbers in Python [duplicate]

This question already has an answer here:
List vs. int assignment - "Every variable is a pointer"
(1 answer)
Closed 8 years ago.
In python if assign a list of numbers to a variable in the following way
>>>a=range(4)
>>>b=a
>>>a[2]=9
>>>b
[0,1,9,3]
but when I assign a single variable in a similar way I get the following result
>>>a=1
>>>b=a
>>>a=2
>>>b
1
Why is it that b=1 instead of b=2 as in the result from assigning the variable to a list?
In your first example, a and b are both references to the same object, a list. When you change the list, so does the output for a and b (which still point to the same list).
In your second example, you are assigning a new integer object to the name a. a and b are two different objects with different ids now. Demo:
>>> a = range(4)
>>> b = a
>>> id(a)
38845472
>>> id(b)
38845472
>>> a=1
>>> b=a
>>> id(a)
33619048
>>> id(b)
33619048
>>> b=2
>>> id(a)
33619048
>>> id(b)
33619024
Integers are immutable so to speak, that you can not change them with slicing, unlike lists:
>>> x = range(4)
>>> x
[0, 1, 2, 3]
>>> id(x)
4300734408
>>> x[0] = 5
>>> id(x)
4300734408
>>> x = 1
>>> id(x)
4299162584
>>> x+=1
>>> id(x)
4299162560
>>>
As you can see above, you can change the list, but it still has the same id. However, if you call += on an integer, the id changes.
This is exactly why although you change a, b doesn't change along with it.

how can i set a variable in a array in python?

i have the problem where i set a variable but it creates a new one instead, i am not quite sure what is going on here. I have tried using global, setting the variables first and tried to use a tupple but just can't get it working. but this is the problem:
>>> variable = 1
>>> variableList = [variable]
>>> variableList[0] = 2
>>> print(variable)
1
as you can see it variable stays 1 although i set it to 2, is there a easy way to fix this?
Doing variableList = [variable] actually created a new reference(variableList[0]) to the object 1. And when you did variableList[0] = 2, it removed one reference from 1 and assigned variableList[0] to 2. So, using an assignment you can never modify other references.
>>> import sys
>>> variable = 1000
>>> sys.getrefcount(variable)
2
>>> variableList = [variable]
>>> sys.getrefcount(variable) # Reference count increased by 1
3
>>> variableList[0] = 2
>>> sys.getrefcount(variable) #Reference count decreased by 1
2
In fact even you've used +=, that too wouldn't have affected variable because you don't modify a immutable object, you simply assign a new object to that variable name.
>>> a = 100
>>> b = a
>>> b += 10 #This too only affects b
>>> a
100
>>> b
110
But, if variable points to a mutable object and you perform some in-place operation on that object from either variable or variableList[0], then you'll see that both of them have changed.
>>> a = []
>>> b = [a]
>>> b[0].append(1) #in-place operation on a mutable object affects all references
>>> a
[1]
>>> b
[[1]]
you don't set variable. you just change variableList content.
variableList[0] it's a variable like variable so the command variableList = [variable] just copy its value.
it is just like this:
>>> a = 1
>>> b = a
>>> b = 2
>>> print(a)
1
You're reassigning the 0th element of the list (not Array), to the Integer 2, you are not overwriting the variable variable.
>>> variable = 1
>>> variableList = [variable]
>>> variableList[0] = 2
>>> print(variable)
>>> 1
>>> print(variableList)
[2]
It suggest you also look up mutability, as it's important to note that integers are immutable:
The value of some objects can change. Objects whose value can change are said to be mutable; objects whose value is unchangeable once they are created are called immutable.
When you did :variableList = [variable]
you created the first element of veribleList and made its value to balue of variable but it dont makes this first element a varible you just coppied its value so when you change variableList[0] it has nothing to do with variable

Store reference to primitive type in Python?

Code:
>>> a = 1
>>> b = 2
>>> l = [a, b]
>>> l[1] = 4
>>> l
[1, 4]
>>> l[1]
4
>>> b
2
What I want to instead see happen is that when I set l[1] equal to 4, that the variable b is changed to 4.
I'm guessing that when dealing with primitives, they are copied by value, not by reference. Often I see people having problems with objects and needing to understand deep copies and such. I basically want the opposite. I want to be able to store a reference to the primitive in the list, then be able to assign new values to that variable either by using its actual variable name b or its reference in the list l[1].
Is this possible?
There are no 'primitives' in Python. Everything is an object, even numbers. Numbers in Python are immutable objects. So, to have a reference to a number such that 'changes' to the 'number' are 'seen' through multiple references, the reference must be through e.g. a single element list or an object with one property.
(This works because lists and objects are mutable and a change to what number they hold is seen through all references to it)
e.g.
>>> a = [1]
>>> b = a
>>> a
[1]
>>> b
[1]
>>> a[0] = 2
>>> a
[2]
>>> b
[2]
You can't really do that in Python, but you can come close by making the variables a and b refer to mutable container objects instead of immutable numbers:
>>> a = [1]
>>> b = [2]
>>> lst = [a, b]
>>> lst
[[1], [2]]
>>> lst[1][0] = 4 # changes contents of second mutable container in lst
>>> lst
[[1], [4]]
>>> a
[1]
>>> b
[4]
I don't think this is possible:
>>> lst = [1, 2]
>>> a = lst[1] # value is copied, not the reference
>>> a
2
>>> lst[1] = 3
>>> lst
[1, 3] # list is changed
>>> a # value is not changed
2
a refers to the original value of lst[1], but does not directly refer to it.
Think of l[0] as a name referring to an object a, and a as a name that referring to an integer.
Integers are immutable, you can make names refer to different integers, but integers themselves can't be changed.
There were a relevant discussion earlier:
Storing elements of one list, in another list - by reference - in Python?
According to #mgilson, when doing l[1] = 4, it simply replaces the reference, rather than trying to mutate the object. Nevertheless, objects of type int are immutable anyway.

Categories