Variables, Assignment and Constants in Python

A Python variable is a name bound to an object, not a box holding a value. That one distinction explains multiple assignment, swapping, dynamic typing and aliasing.

A variable is a label, not a box

In many languages a variable is a piece of memory of a fixed size, and assignment copies a value into it. Python does not work that way. In Python:

  • Values are objects that live somewhere in memory.
  • A variable is a name bound to an object.
  • Assignment rebinds the name. It does not copy the object.
count = 10        # create the integer 10, bind the name count to it
count = 20        # bind count to a different object; 10 is untouched
   count ────────► 10          after line 1

   count ────────► 20          after line 2
                   10          now unreferenced, and will be reclaimed

Everything else in this note is a consequence of that picture.

Assignment

price = 249.50            # simple assignment
label = "invoice"
is_paid = False

There is no declaration step and no type to write. The name comes into existence at the moment it is first assigned. Using a name before assigning it is a NameError.

print(total)   # NameError: name 'total' is not defined
total = 0

Multiple and chained assignment

# Multiple assignment: pair the names with the values, position by position.
name, age, city = "Meera", 27, "Pune"

# Chained assignment: one object, three names bound to it.
x = y = z = 0

# Swapping, with no temporary variable.
a, b = 1, 2
a, b = b, a
print(a, b)      # 2 1

The swap works because the right hand side is fully evaluated before anything is assigned. Python builds the pair (2, 1) first, then unpacks it into a and b.

Chained assignment binds every name to the same object. With immutable values such as 0 that never matters. With a mutable value it matters a great deal: a = b = [] gives two names for one list, and appending through a changes what b sees.

Unpacking with a star

first, *rest = [10, 20, 30, 40]
print(first)     # 10
print(rest)      # [20, 30, 40]

head, *middle, tail = [1, 2, 3, 4, 5]
print(middle)    # [2, 3, 4]

Dynamic typing

A name is not tied to a type. Rebinding it to a different kind of object is entirely legal.

value = 42
print(type(value))     # <class 'int'>

value = "forty two"
print(type(value))     # <class 'str'>

Legal is not the same as advisable. Reusing one name for two different kinds of thing makes code hard to follow and defeats the type checkers covered later in this path. Rebind a name to a new value of the same kind; use a new name for a new kind of thing.

Dynamic but strong

print(2 + 3)         # 5
print("2" + "3")     # 23
print(2 + "3")       # TypeError: unsupported operand type(s) for +: 'int' and 'str'

Python will not guess what you meant. That refusal is what strongly typed means, and it is a feature: the error appears immediately instead of a wrong answer appearing much later.

Aliasing, and why it surprises people

first = [1, 2, 3]
second = first        # not a copy; a second name for the same list

second.append(4)
print(first)          # [1, 2, 3, 4]

Nothing unusual happened. second = first bound a second name to one object, exactly as the label picture predicts. To get an independent list you must ask for one:

second = first.copy()     # or list(first), or first[:]
second.append(5)
print(first)              # unchanged

The same effect does not appear with numbers and strings, because those objects cannot be modified in place. Shallow and deep copying are covered fully in the internals notes later in this path.

Constants by convention

Python has no const keyword. Nothing prevents reassignment. The convention is to write a constant in capitals, which tells every reader that the value is not meant to change.

MAX_RETRIES = 3
TAX_RATE = 0.18
APP_NAME = "NoteHub"

MAX_RETRIES = 5     # Python permits this. A reviewer will not.

Group constants at the top of the module. If a value appears twice in your code, or appears once but needs explaining, make it a named constant.

The del statement

temp = "scratch value"
del temp
# print(temp)    # NameError: the name no longer exists

del removes the name, not necessarily the object. If another name still refers to the same object, that object stays alive.

Naming that earns its keep

WeakBetterWhy
ddays_overdueA reader should not have to search for the meaning.
list1invoicesName the contents, not the container type.
flagis_verifiedA boolean reads best as a yes or no question.
tmpprevious_totalTemporary is a lifetime, not a description.
l, O, Ianything elseSingle letters that look like digits in most fonts.

Common mistakes

  • Reading a name before assigning it, and being surprised by NameError.
  • Assuming b = a copies a list or a dictionary. It does not.
  • Writing a = b = [] and later discovering both names change together.
  • Shadowing a built in: list, str, dict, id, type, sum, max and input are all easy to overwrite by accident.
  • Expecting capitals to enforce immutability. They document intent only.

Best practices

  • Assign a name close to where it is used, and give it the narrowest useful scope.
  • Keep one name for one kind of thing throughout its life.
  • Use multiple assignment when the values genuinely belong together, not to compress unrelated lines.
  • Put constants at the top of the module in capitals, and refer to them everywhere instead of repeating literals.

Practice

  1. Draw the name to object diagram for a = [1]; b = a; b.append(2) and predict what a prints.
  2. Swap three variables so that a takes b's value, b takes c's and c takes a's, in one statement.
  3. Explain why x = y = 5 is harmless but x = y = {} deserves a second look.
  4. Predict the output of first, *rest = "python" and explain the result.
  5. Assign len = 5 and then call len("abc"). Explain the error and how to recover in the same session.

Conclusion

Assignment binds a name to an object; it never copies. Once that picture is fixed in your mind, multiple assignment, swapping, aliasing, dynamic typing and the whole later discussion of mutability follow from it without any further rules.

Written by Lorens Mishra

Default administrator account created by the installer.

Continue reading

All Python notes →
Python

Introduction to Python

Python is a high level, dynamically typed, interpreted language whose whole design goal is that a program should be as easy to read as it was to write...

Read more

Discussion

0 comments
Sign in to join the discussion.

No comments yet. Be the first to say something.