Objects, variables, and functions in Python
Python Names and Objects
People beginning Python may be confused by its rather unique approach to variables and values. How are objects stored? How are variables passed to functions?
In Python, everything is an object. Any list, or tuple, or string is an object. Functions, types, and even literals are objects. For instance, in languages like C, ‘7’ is a numeric constant. It is a value to be stored in a variable. But in Python, it is an instance of the int numeric type, and is an object in its own right, rather than only a numeric literal.
Compare this:
int foo = 7;
with this:
bar = 7
The first code block has a C statement that assigns the value 7 to the variable foo.
The second block contains a Python statement that binds the object 7 to the name or identifier bar.
Suppose we do the following:
bar = 42
Then, we are merely rebinding the name bar to another object(another numeric literal).
Every object is unique, and has a unique identifying value that is returned by the id function. For instance:
list_1 = [1, 2, 'spam']
tuple_1 = ('300 yen', 42)
x = 7
y = 7
print(id(list_1), id(tuple_1))
print(id(x), id(y))
The above snippet gives the following result:
139919612658888 139919612659848
139919612658888 139919612659848
An object’s id is guaranteed to be constant and unique during its lifetime.
Notice that the value of id is the same when we pass the variables x and y to it. This is because they are bound to the same object.
The type function, as its name suggests, returns the type of the object passed to it.
We can additionally use the is operator to check if two names refer to the same object.
Consider the following snippet:
spam = [1,2,3]
ham = spam
print(spam)
print(ham is spam)
ham[0] = "a"
print(spam)
foo = spam[:]
print(foo is spam)
Output:
[1, 2, 3]
True
['a', 2, 3]
False
After the second line, both spam and ham refer to the same object. So, if we apply the append method on ham, the list pointed to by spam is also changed. On the contrary, the penultimate line splices the original list, so that foo and spam refer to lists that have the same value but are essentially different objects.
Mutability
Objects are of distinctly two types: mutable and immutable.
The values of mutable objects can be changed. Lists, sets and dictionaries are some mutable types.
foo_list = [1, 2, 3, 4, 5]
print(foo_list, id(foo_list))
foo_list.append("shrubbery")
print(foo_list, id(foo_list))
We have used the append method to modify the list.
The code above gives the output:
[1, 2, 3, 4, 5] 139921008629000
[1, 2, 3, 4, 5, 'shrubbery'] 139921008629000
Notice that the id of the list remains the same, even when its value is changed.
The same cannot be said of immutable objects. Tuples have no method like append to modify a tuple object. You can only return a new tuple object from an old one, but you can never change its value. You can, however, ‘change’ a tuple’s value by changing the value of a mutable type contained in it.
li = []
tup = (1, "spam", li)
print(tup, id(tup))
li.append(5)
print(tup, id(tup))
Output:
(1, 'spam', []) 139999533869672
(1, 'spam', [5]) 139999533869672
The id of the tuple is the same. This is because li is a mutable type, and only its value has been changed. The tuple tup still contains the same list object. Therefore, it remains esssentially unchanged.
Python Functions and objects
How are variables passed to functions in Python? Does a function get a local copy, or does it directly get a reference to the object itself?
In Python, regarding functions, the terms pass by reference and pass by value do not hold much meaning. When we pass a variable/name as a function argument, the object itself is passed to the function. If the object is mutable, the function can change its value, and if it is immutable, it can merely read the value.
Demonstration:
x = [1, 2, 3]
print("x is ", id(x))
def f(z):
x = ["another", "list"]
z.append("thanks")
print("z is ", id(z))
return z
y = f(x)
print(x is y)
print(x)
Output:
x is 139793733100744
local x is 139793733100808
z is 139793733100744
True
[1, 2, 3, 'thanks']
As you can see, the function f has modified and returned the list passed to it.
The function’s local variable x with the same name is an entirely different object altogether, and does not affect the original variable as it is in a different scope.
I hope this clears up some confusion.