Week 8 Tutorial: Fundamentals of Python Programming I

POP77001 Computer Programming for Social Scientists

Naming Conventions

It is a good practice to follow usual naming convention when writing code.

  • Use UPPER_CASE_WITH_UNDERSCORE for named constants (e.g. variables that remain fixed and unmodified)
  • Use lower_case_with_underscores for function and variable names
  • Use CamelCase for classes (more on them later)

Code Layout

  • Limit all lines to a maximum of 79 characters.
  • Break up longer lines:
my_list = [
    1, 2, 3,
    4, 5, 6,
    ]
result = some_function_that_takes_arguments(
    'a', 'b', 'c',
    'd', 'e', 'f',
    )
income = (gross_wages
          + taxable_interest
          + (dividends - qualified_dividends)
          - ira_deduction
          - student_loan_interest)

Reserved Words

There are 35 reserved words (keywords) in Python (as of version 3.9) that cannot be used as identifiers.

---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
File ~/Decrypted/Git/POP77032_QTA/lib/python3.12/site-packages/pandas/compat/_optional.py:158, in import_optional_dependency(name, extra, min_version, errors)
    157 try:
--> 158     module = importlib.import_module(name)
    159 except ImportError as err:

File /usr/lib/python3.12/importlib/__init__.py:90, in import_module(name, package)
     89         level += 1
---> 90 return _bootstrap._gcd_import(name[level:], package, level)

File <frozen importlib._bootstrap>:1387, in _gcd_import(name, package, level)

File <frozen importlib._bootstrap>:1360, in _find_and_load(name, import_)

File <frozen importlib._bootstrap>:1324, in _find_and_load_unlocked(name, import_)

ModuleNotFoundError: No module named 'tabulate'

The above exception was the direct cause of the following exception:

ImportError                               Traceback (most recent call last)
Cell In[3], line 2
      1 # display(HTML(reserved_words.to_html(header = False, index = False)))
----> 2 Markdown(reserved_words.to_markdown(index = False, headers = ['', '', '', '', '']))

File ~/Decrypted/Git/POP77032_QTA/lib/python3.12/site-packages/pandas/core/frame.py:2983, in DataFrame.to_markdown(self, buf, mode, index, storage_options, **kwargs)
   2981 kwargs.setdefault("tablefmt", "pipe")
   2982 kwargs.setdefault("showindex", index)
-> 2983 tabulate = import_optional_dependency("tabulate")
   2984 result = tabulate.tabulate(self, **kwargs)
   2985 if buf is None:

File ~/Decrypted/Git/POP77032_QTA/lib/python3.12/site-packages/pandas/compat/_optional.py:161, in import_optional_dependency(name, extra, min_version, errors)
    159 except ImportError as err:
    160     if errors == "raise":
--> 161         raise ImportError(msg) from err
    162     return None
    164 # Handle submodules: if we have submodule, grab parent module from sys.modules

ImportError: `Import tabulate` failed.  Use pip or conda to install the tabulate package.
try = 5 # Watch out for reserved words
  Cell In[4], line 1
    try = 5 # Watch out for reserved words
        ^
SyntaxError: expected ':'

Defining Variables

  • Assignment statement binds the variable name and an object.
x = 5 # Variable 'x' is bound to object 5 of type integer
x
5
  • The same object can have multiple names (⚠️ more on aliasing and copying below)
y = x
y
5
# Note that x was overwritten even with addition operation as integers are immutable
x += 3 
x
8
y
5

Strings

  • String (str) - immutable ordered sequence of characters.
  • Immutable - individual elements cannot be modified.
  • Ordered - strings can be sliced (unlike in R).
s = 'test'
s
'test'
s[0] = 'r' # immutability
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[10], line 1
----> 1 s[0] = 'r' # immutability

TypeError: 'str' object does not support item assignment
s[0] # slicing (indexing starts from 0!)
't'

String Methods

s.capitalize()
s.title()
s.upper()
s.lower()
s.find(some_string)
s.replace(one_string, another_string)
s.strip(some_string)
s.split(some_string)
s.join(some_list)

Method Chaining

  • Recall from the lecture that methods can be chained
  • E.g. s.strip().replace('--', '---').title()
  • It provides a shortcut (does not necessitate intermediate objects)
  • However, it can reduce code legibility! 📜

Exercise: Working with Strings

  • Remove trailing whitespaces (before and after the sentence) in the string below;
  • Replace all double whitespaces with one;
  • Format it as a sentence with correct punctuation;
  • Print the result.
s = "   truth  can  only be  found in  one place:  the  code "

Lists

  • List (list) - mutable ordered sequence of elements.
  • Mutable - individual elements can be modified.
  • Ordered - lists can be sliced (like strings).
l = [1, 2, 3]
l
[1, 2, 3]
l[1] = 7 # mutability
l
[1, 7, 3]
l[0] # slicing
1

List Methods

l.append(some_element)
l.extend(some_list)
l.insert(index, some_element)
l.remove(some_element)
l.pop(index)
l.sort()
l.reverse()
l.copy()

Aliasing vs Copying - Immutable

  • Having multiple names for the same object doesn’t usually create a problem with immutable types, as the entire object just gets overwritten.
x = 5
y = x # Object 5 of type integer is not copied, y is just an alias!
x
5
y
5
id(x) # function id() prints out unique object identifier
11759912
id(y)
11759912
x += 3
print(x)
print(y)
print(id(x))
print(id(y))
8
5
11760008
11759912

Aliasing vs Copying - Mutable

l = [1, 2, 3]
# Object [1, 2, 3] of type list is not copied, l1 is just an alias!
l1 = l
# Both [:] slicing notation and copy method create copies
l2 = l[:]
l3 = l.copy() 
l1.pop(0) # Remove (and return) first element of the list
l2.insert(0, 0) # Insert 0 as the first element of the list
l3.append(4) # Append 4 to the end of the list
print(l)
print(l1)
print(l2)
print(l3)
[2, 3]
[2, 3]
[0, 1, 2, 3]
[1, 2, 3, 4]

Exercise: Working with Lists

  • Below is a shuffled version of the first 11 elements of Fibonacci sequence.
  • Create a copy of the shuffled list;
  • Remove the last element;
  • Sort it from smaller integers to larger;
  • Select the second smallest and the third largest integers in the sequence; Print them out;
  • Replace them in the list with the string, containing word corresponding to that number (e.g. ‘two’ for 2);
  • Print out the results.

fib_shuffled = [34, 5, 3, 1, 13, 55, 21, 2, 8, 0, 1]

Week 8 Exercise (unassessed)

  • Practice working with built-in Python data structures