6. Variables and assignments#

Author: Tue Nguyen

6.1. Outline#

  • Assignments, variables, objects, and values

  • Equality comparison

  • Object identities

  • Python interning

  • Formatted printing

6.2. Variables, assignments, objects, and values#

  • From last tutorial, we know a variable is created through an assignment

  • Ex: x = 1000

    • x: variable name

    • 1000: value

  • Warning: many people think that x contains value 1000. It’s NOT true

  • Under the hood

    • First, Python evaluates the right hand side (RHS) of the assignment and comes up with value 1000

    • Python then creates an object in the memory to hold that value

    • Finally, Python links the object to a variable named x on the left hand side (LHS)

  • You should think as follows

    • Object = a box

    • Value = what’s inside the box

    • Variable = a label pasted on the box

    • We use the label the retrieve the thing inside the box

  • Why use variables?

    • It is extremely complicated for us, as human beings, to deal with objects directly

    • Variables help

      • Abstract away all unnecessary technical complications

      • Allow us to focus on solving our main problem at a higher level

6.3. Equality comparision#

  • In Python, = is used for assignment, not comparision

  • To check if two things are equal (in terms of value), we use ==

    • If they are indeed equal, True will be returned

    • Otherwise, False will be returned

# Init a variable
x = 1000
x
1000
# Check if x is equal to 1000
x == 1000
True
# Check if x is equal to 50
x == 50
False
# Check if x is equal to "abc"
x == "abc"
False

6.4. Object identity#

  • In Python, everything is an object

  • Each object has an unique ID (like a person has an ID)

  • We use id(x) to get the ID of the object that variable x is pointing to

  • We might say “ID of x” but the correct sentence should be “ID of the object associated with x

Some notes on saying

  • We might say “ID of x” but the correct sentence should be “ID of the object associated with x

  • Suppose id(x) gives us 2350614735152, then we say

    • x is pointing to the object with ID 2350614735152

    • x is referring to the object with ID 2350614735152

  • In the statement x = 1000, we say

    • x is assigned value 1000

    • 1000 is assigned to x

    • NOT: “x is assigned to 1000

  • On the first assignment on x we use the word initialize (or init for short)

  • On the next assignment on x we use the word assign

a) Ex 1: get ID

# Init a variable
x = 1000
# View the value associated with x
x
1000
# View ID of the object associated with x
# Note: the value you see might differ between Python sessions
id(x)
139751297467184

b) Ex 2: two assignments are handled separately

# Assignments
x = 1000
y = 1000
# View values
print(x)
print(y)
1000
1000
# View ID
print(id(x))
print(id(y))
139751297467472
139751297466576
# Compare values
x == y
True
# Compare IDs
id(x) == id(y)
False

Why different IDs?

  • First assignment

    • Python evaluates RHS, comes up with value 1000, and creates an object to hold that value

    • Then Python links that object to variable x

  • Second assignment

    • Python evaluates RHS, also comes up with value 1000, but it creates another different object to hold that value

    • Then Python links that object to variable y

  • Thus, different objects have different IDs

  • Think of it this way: there are two boxes (objects) containing the same thing (values) and having two different labels (variables)

c) Ex 3: compare identities

# Method 1: we can check if x and y are pointing to the same object
# using == as in the previous example
id(x) == id(y)
False
# Method 2: we can do the same thing using keyword is
x is y
False

d) Ex 4: garbage collector

# Now re-assign y to 2000
y = 2000
# Print value of y
y
2000
# Print ID of y
id(y)
139751263500080

What just happened?

  • When we run x = 2000, Python evaluates RHS, comes up with value 2000, and creates an object with ID shown above to hold the value

  • Python detect y is already linked to a different object, so it delete the current link, and re-link y to the new object

  • That’s why when we print x or id(x) we get new values

What happened to the old object?

  • When Python detect an object with no variables referring to it, Python will summon the garbage collector to destroy that object and release memory to the system for future assignments

  • How can we verify it? We can’t because we only have access to an object through its associated with it

e) Ex 5: assignment to avariable An assignment to a variable will not create a new object

# Now assign x to z
z = x
# They will have the same value
print(x)
print(z)
1000
1000
# But they also pointing to the same underlying object
print(id(x))
print(id(z))
print(x is z)
139751297467472
139751297467472
True

What happened?

  • When the RHS of an assignment is just a variable name, no new object is created

  • You can think of it as we have two labels pasted on the same box

  • Either we use x or z, we get the same thing back

f) Ex 6: assignment to an expression involving a variable

If the RHS is an expression involving a variable, then a new object is created as usual

# Assign x + 500 to variable t
# Python will evaluates the RHS to come up with 1500
# then create an object to hold this value
# and finally link this object to variable t
t = x + 500
# Print values
print(x)
print(t)
1000
1500
# Print IDs
print(id(x))
print(id(t))
print(x is t)
139751297467472
139751263498544
False

g) Ex 7: garbage collector only destroys objects with no reference

# In Ex 5, we know x and z are pointing to the same object
print(id(x))
print(id(z))
print(x is z)
139751297467472
139751297467472
True
# Now re-assign 3000 to z
# Python will delete the binding between z and the current object
# and establish a new binding between z and the object holding 3000 
z = 3000
# Check ID of z
id(z)
print(x is z)
False
# What happened to the old object that z was pointing to?
# It still exists because x is still pointing to it
# In short, only boxes without a label will be destroyed
print(x)
print(id(x))
1000
139751297467472

6.5. Python interning#

  • We already saw that the theory works for some large numbers such as 1000 and 2000

  • But for the theory is NOT true for every case

  • Consider the following example

# In principle, 2 assignmens below will create 2 different objects
# Thus, x and y should be 2 labels pasted on 2 different boxes
x = 10
y = 10
# It seems true when we compare the values
print(x)
print(y)
print(x == y)
10
10
True
# But in fact, x and y are pointing to the same object
print(id(x))
print(id(y))
print(x is y)
139751383028288
139751383028288
True

What happened?

  • This weird behavior (called Python interning) is due to some optimization decision of the Python core team (which I will not discuss here)

  • Basically, maintaining only one single copy helps save memory and make comparisons a lot faster

  • And the core team accepted this language inconsistency in exchange for performance

  • You can see Python interning behavior for small integers (normally from -5 to 128, but it depends on specific implementations) and for short strings

  • Key take away: never compare identities for small integers and short strings

a) Ex 1: test with integers

# Test with -5
x = -5
y = -5
print(x is y)
True
# Test with 128
x = 128
y = 128
print(x is y)
True
# Test with -10
x = -10
y = -10
print(x is y)
False
# Test with 300
x = 300
y = 300
print(x is y)
False

b) Ex 2: test with strings

# Test with a short string
x = "Hello"
y = "Hello"
print(x is y)
True
# Test with a long string
x = "Hello. Nice to meet you."
y = "Hello. Nice to meet you."
print(x is y)
False

Remarks

  • The theory is true in general, but be aware of Python interning behavior in some special cases

  • Never compare identities of small integers and short strings

  • In practice, you rarely compare identities, so it won’t matter much

6.6. Formatted printing#

Now, you already gained some more understanding of how Python works. It’s time to introduce some more useful tips for printing.

6.6.1. Normal printing#

# Print strings
print("Hello")
Hello
# Print variables
x = 1000
print(x)
1000
# Print expressions
print(x + 500)
1500

6.6.2. Formatted printing#

A formatted string is a string having some placeholders that will be filled by the values of some variables

a) Ex 1: use .format()

name = "Thor"
place = "Asgard"
s = "I am {} from {}".format(name, place)

print(s)
I am Thor from Asgard

What happened?

  • Here, the string s has two placeholders in it (denoted by {})

  • Each placeholder will be filled with the values of name and place respectively

b) Ex 2: use string interpolation

  • Avaiable for Python >= 3.6 only

  • You place an f (meaning “formatted”) before the beginning quote and put the variable names inside the corresponding placeholders

  • This behavior is called string interpolation

age = 20
name = "Rob"

print(f"This is {name}. He is {age} years old")
This is Rob. He is 20 years old

6.7. Summary#

Assignments, variables, objects, and values

  • Syntax: variable_name = value

  • How an assignment works

    • Python always evaluates the RHS first

    • Comes up with a value

    • Creates an object to hold the value

    • And finally links the object to a variable name on the LHS

  • Variables are just symbolic names; they don’t contain values

  • Only objects contain values

  • We, as human beings, don’t manipulate object directly but through variables

The box model

  • Object = a box

  • Value = what’s inside the box

  • Variable = label pasted on the box

  • At a given point in time

    • A box can have multiple label pasted on it

    • But a label can be pasted on one box only (because if not, when we use the variable, Python cannot decide know which box to open)

Object identity

  • Everything that contains value or data is an object

  • In Python, almost everything is an object

  • An object have a unique ID

  • Use id(x) to get ID of the object associated with x

Equality comparision

  • Use = for assignments

  • Use == to compare values

  • Use is to comapre identities

Various types of assignment

  • x = 1000 and y = 1000 will creates two different objects although x and y have the same value

  • z = x will not create a new object: x and z now are referring to the same object

  • When re-use a variable x in a new assignment, Python will delete the binding between x and the old object and establish a new binding between x and the new object

Garbage collector

  • When Python notices a box without any label, it will immediately summon the garbage collector to destroy that box and return the memory to the system

  • Only objects without references will be destroyed

Python interning

  • When assigning the same small integer or short string to two different variables x and y, then it might be that only one object is created and both x and y are pointing to that object

  • This is called Python interning behavior

  • Python interning happens in assignment with

    • Small integers (normally from -5 to 128)

    • Short strings

Formatted printing

  • When a print statement involve a formatted string, it is called formatted printing

  • A formatted string has some placeholders in it that will be filled with values of some variables

  • Two syntaxes

    • Use .format(): s = "I am {} from {}".format(name, place)

    • Use string interpolation: s = f"This is {name}. He is {age} years old"

Other notes

  • The theory on assignment is true in general

  • Just be aware of Python interning behavior

  • Never compare identity of small integers and short strings

  • In practice, you rarely compare identities, so it won’t matter much

6.8. Practice#

To be updated