Is it possible to reassign the value referenced to by a variable, rather than the variable itself?
a = {"example": "foo"}
b = a
When I reassign a, it is reassigning the variable a to reference a new value. Therefore, b does not point to the new value.
a = {"example": "bar"}
print(b["example"]) # -> "foo"
How do I instead reassign the value referenced by a? Something like:
*a = {"example": "bar"}
print(b["example"]) # -> "bar"
I can understand if this isn't possible, as Python would need a double pointer under the hood.
EDIT Most importantly, I need this for reassigning an object value, similar to JavaScript's Object.assign function. I assume Python will have double pointers for objects. I can wrap other values in an object if necessary.
Python variables simply do not operate this way, and simple assignment won't do what you want. Instead, you can clear the existing dict and update it in-place.
>>> a = dict(example="foo")
>>> b = a
>>> a.clear()
>>> a
{}
>>> a.update({'example': 'bar'})
>>> b
{'example': 'bar'}
You are creating 2 dictionaries, so that's 2 different objects in memory. If you don't want that, keep 1 dictionary only.
a = {"example": "foo"}
b = a
a["example"] = "bar"
print(b["example"])
Related
I need to create multiple dictionaries in one line, I tried like following.
a,b,c = dict(), dict(), dict()
Is there any pythonic way to achieve this? I tried with
a = b = c = dict()
But in this, if I change a it also reflects with other dicts
a['k'] = 'val'
a
{'k': 'val'}
b
{'k': 'val'}
c
{'k': 'val'}
I'm just posting some thoughts here:
Pep 8 is a style guide for python code: https://www.python.org/dev/peps/pep-0008/. However nothing about declaring variables there.
Although these work:
a,b,c = dict(), dict(), dict()
a, b, c = [dict() for _ in range(3)]
I think this is the most readable:
a = dict()
b = dict()
c = dict()
Reason:
You can always expect that variables are defined on separate rows. What about if you were to assign 20 items, would it be: a,b,c,d,e.... ??
Anyhow, another way of doing it would be to nest them inside one dictionary, and here too only one variable is declared:
dicts = {letter:dict() for letter in list("abc")} # {'a': {}, 'b': {}, 'c': {}}
Your first method is fine. use
a,b,c = dict(), dict(), dict()
The explanation for the second method :
Python variables are references to objects, but the actual data is
contained in the objects.
a = b = c = dict() is not creating three dict. In python, variables don't store the value. Variables point to the object and objects store the value, so here a,b,c variable pointing same object which contains one dict(). you can check
print(id(a),id(b),id(c))
4321042248 4321042248 4321042248
That's why when you change in one, it changes the other too because they are holding the same dict value.
This is the code I type. Here the value of int has not changed outside of function but value of list has changed.I was expecting the value of list will not change. What is the reason?
>>> def p1(list1):
list1[0]=1000
>>> def p2(i):
i+=10
>>> li=[1,2,3,4,5]
>>> int1=10
>>> p1(li)
>>> p2(int1)
>>> li
[1000, 2, 3, 4, 5]
>>> int1
10
Note that in p1, you are not assigning a value to list1, which is the name of a variable local to p1. You are actually assigning to the first element of the list object referenced by list1, which is the same list object referenced by li in the enclosing scope.
In p2, on the other hand, i+=10 does assign a value to the local variable i, not the variable int1 in the enclosing scope. This is because the += operator on objects of type int do not actually modify the object, but return a new object instead. (That is, for an int, i+=10 is equivalent to i = i + 10.)
Just to show that += can operate on the underlying object directly, consider this function:
def p3(list1):
list1 += [10]
Then run it on a list:
>>> foo = [1,2,3]
>>> p3(list1)
>>> foo
[1, 2, 3, 10]
Here, the call list1 += [10] is really equivalent to list1.extend([10]), not list1 = list1 + [10], due to how list.__iadd__ is defined. Here, you are again not assigning a value to the name list1, but rather invoking a method on the object referenced by list1 (which is the same object referenced by foo).
(Update: as pointed out by user2357112, technically you do assign to list1, but list.__iadd__ is designed to properly assign the same list back, so that the end result is that you still have a reference to the same mutable object you started with.)
Assigning to a variable, like i+=10, is an operation on a variable, while index assignment, like list1[0]=1000, is an operation on the object a variable refers to.
When you call p2(int1), the local variable i gets set to refer to the int int1 referred to, and then the i+=10 statement redirects i to refer to a new, larger integer. int1 still refers to the old integer.
When you call p1(li), the local variable list1 gets set to refer to the list li referred to, and then the list1[0]=1000 statement sets the first cell of the list to refer to 1000. li still points to this list throughout the modification, and after the function returns, li still reflects the change.
(There's another complexity here in that += also requests that an object mutate itself if it's mutable, in addition to performing an assignment, but that doesn't come up in this code.)
A list is like a pointer to a list object.
#For example
a =[0,0]
b = a
b[0]=1
resulting in
b
[1,0]
Where as an int is an a different beast
#For Example
a = 0
b = a
b +=1
resulting in
a
1
to get the int behaviour from a listyou can make a clone of a list by passing it to list()
#for example
a = [0,0]
b = list(a)
b[0]=1
resulting in
a
[0,0]
and if you want the list behaviour from an int I guess you would have to just put it in a list.
I am trying to understand when are objects copied in Python.
The easy case is explicit copy, for example:
A = [ 1,2,3 ]
B = list(A) # this is a copy of A
Are there scenarios which implicitly copy an object? For example some languages using "pass by value" will copy objects used as functions arguments (I know that this is not the case in Python). Are there such examples of implicit copy in Python?
Hopefully it will better illustrate what is happening in your code:
>>> a = object()
>>> b = object()
>>> A = [a, b]
>>> B = list(A)
>>> A
[<object object at 0x1002b7090>, <object object at 0x1002b70a0>]
>>> B
[<object object at 0x1002b7090>, <object object at 0x1002b70a0>]
>>> A is B
False
What you can see is list() actually creates a new instance of a list based on A. This is why A is B returns false. However the contents of both list are identical
In practical terms, any indirect assignment of an immutable object can be considered a copy. For example:
a = "abc"
b = a
a += "def"
print b
--> "abc"
Technically, there is no copying occurring. When you add to a, you are actually creating a new object and assigning the variable name "a" to it while the variable "b" continues to reference the original string.
As far as functions go, there is no copying that occurs in passed variables; however, the same rules apply for mutable and immutable arguments. If you were to pass an immutable object, any changes would only impact the local "copy".
list() is not doing anything special in your example.
list(iterable):
Return a list whose items are the same and in the same order as
iterable‘s items. iterable may be either a sequence, a container that
supports iteration, or an iterator object. If iterable is already a
list, a copy is made and returned, similar to iterable[:]. For
instance, list('abc') returns ['a', 'b', 'c'] and list( (1, 2, 3) )
returns [1, 2, 3]. If no argument is given, returns a new empty list,
[].
Say I have a list
my_list = ['a','b','c']
and I have a set of values
my_values = [1,2,3]
Is there a way to iterate through my list and set the values of my_list equal to my_values
for i in range(len(my_list)):
## an operation that instantiates my_list[i] as the variable a = my_values[i]
...
>>> print a
1
I just want to do this without copying the text of file that holds the program to a new file, inserting the new lines as strings where they need to go in the program. I'd like to skip the create, rename, destroy, file operations if possible, as I'm dealing with pretty large sets of stuff.
This is probably hackery that you shouldn't do, but since the globals() dict has all the global variables in it, you can add them to the global dict for the module:
>>> my_list = ['a','b','c']
>>> my_values = [1,2,3]
>>> for k, v in zip(my_list, my_values):
... globals()[k] = v
...
>>> a
1
>>> b
2
>>> c
3
But caveat emptor, best not to mix your namespace with your variable values. I don't see anything good coming of it.
I recommend using a normal dict instead to store your values instead of loading them into the global or local namespace.
>>> def test():
... a.remove(1)
>>> a = [1,2]
>>> test()
>>> print a
[2]
Why does a equal [2] rather than [1,2]?
List is mutable. If you pass it to a function, and the function changes it, it stays changed.
Use an immutable structure: tuple: a = (1,2)
Pass a copy of original list: b = list(a); b.remove(1) — now a and b have different contents, a hasn't changed.
Also, try not to use mutable global data. Either pass a to the function, or have a as an attribute of an object, and the function as its method.
It's not clear what you want. Your test() function modifies the global 'a' list, so it's unsurprising that 'a' gets modified.
If you want 'test' to work on a copy of a instead directly on a, you may copy it first.
For example,
def test():
a2 = list(a)
a2.remove(1)
Lists are mutable objects, they are meant to be changed. If you want to forbid changes, convert it to a tuple (e.g. a = (1, 2)) instead. Tuples are immutable, so it's not possible to change them without copying and re-assigning the variable.
Because the list a exists in the global namespace and when you call a remove on it, the value 1 is removed.
If you don't want it to be modified, simply create a new list. If you call remove on the list a, of course it going to remove the value.