Python Programming

Lecture 7 Variable Scope, Arbitrary Arguments

7.1 Variable Scope

Variable Scope (变量的作用域)

In Python, module, class, def, lambda can introduce new variable scope, if/elif/else/, try/except, for/while will not introduce new variable scope.


if True:
    msg = 'I am from Shanghai'
print(msg) # We can use msg.

def test():
    msg = 'I am from Shanghai'
print(msg) # error

Global and Local


msg_loc = "Shanghai" # Global
def test():
    msg = 'I am from Shanghai' # Local

New Assignment


msg = 'I am from Shanghai'
def test():
    msg = 'I am from Beijing'
    print(msg) 
test()
print(msg)

I am from Beijing
I am from Shanghai



Reference


msg = 'I am from Shanghai'
def test():
    print(msg) 
test()

I am from Shanghai


Modification


msg = 'I am from Shanghai'
def test():
    print(msg) 
    msg = 'I am from Beijing' 
test() 

UnboundLocalError: local variable 'msg' 
referenced before assignment


  • How to modify the variable outside? The global keyword


num = 1
def fun():
    global num
    num = 123
    print(num)
fun()
print(num)

123
123


 


num = 1
def fun():
    print(num)
    global num  
    num = 123
    print(num)
fun()

SyntaxError: name 'num' is used 
prior to global declaration





a = 10
def test():
    a = a + 1
    print(a)
test()

UnboundLocalError: local variable 'a' 
referenced before assignment



a = 10
def test():
    global a 
    a = a + 1
    print(a)
test()

11





a = 10
def test():
    a = 10
    a = a + 1
    print(a)
test() 
print(a) 

11
10




mutable vs. immutable


a = [1,2,3]
def test():
    print(a)
    a = [1,2,3,4]
test() 

UnboundLocalError: local variable 'a' 
referenced before assignment



a = [1,2,3]
def test():
    print(a)
    a.append(4)
test() 
print(a)

[1, 2, 3]
[1, 2, 3, 4]




a = {"color": "green"}
def test():
    print(a)
    a["color"] = "red"
    a["position"] = "left"
test() 
print(a)

{'color': 'green'}
{'color': 'red', 'position': 'left'}




Parameter and Argument

  • For immutable objects (number, string, tuple), the assignment inside a function cannot change the value of the variable outside the function even if the variable name inside is the same with the variable name outside.


def ChangeInt(a):
    a = 10
    return a

b = 2
print(ChangeInt(b))
print(b) 

10
2




  • For mutable objects (list, dictionary), the assignment inside a function cannot change the value of the variable outside the function. (the same with immutable objects!)


def changeme(mylist):
   mylist = [1,2]
   print("inside: ", mylist)
 
x = [10,20]
changeme(x)
print("outside: ", x)

inside:  [1, 2]
outside:  [10, 20]




  • However, the modification can change the value of the variable outside.


def changeme(mylist):
   mylist.extend([1,2])
   print ("inside: ", mylist)
 
x = [10,20]
changeme(x)
print ("outside: ", x)

inside:  [10, 20, 1, 2]
outside:  [10, 20, 1, 2]




7.2 Arbitrary Arguments


def make_pizza(toppings):
    print(toppings)

make_pizza('pepperoni')
  • If we want to pass multiple arguments, we may create a list at first.


x=['mushrooms', 'green peppers', 'extra cheese']
def make_pizza(toppings):
    for y in toppings:
        print(y, end=', ')

make_pizza(x)

def make_pizza(topping_1, topping_2, topping_3):
    print(topping_1, topping_2, topping_3)

make_pizza('mushrooms', 'green peppers', 'extra cheese')
  • However, sometimes we are not sure about the exact number of the arguments.

  • We can pass multiple arguments at once in the following way.


def make_pizza(*toppings):
    print(toppings)

make_pizza('pepperoni')
make_pizza('mushrooms', 'green peppers', 'extra cheese')
  • Note that Python packs the arguments into a tuple, even if the function receives only one value.


def make_pizza(*toppings):
    for topping in toppings:
        print("- " + topping)

make_pizza('pepperoni')
make_pizza('mushrooms', 'green peppers', 'extra cheese')

- pepperoni
- mushrooms
- green peppers
- extra cheese
  • Mixing Positional and Arbitrary Arguments

  • If you want a function to accept several different kinds of arguments, the parameter that accepts an arbitrary number of arguments must be placed last in the function definition.


def make_pizza(size, *toppings):
    print(str(size) + "-inch pizza:")
    for topping in toppings:
        print("- " + topping)

make_pizza(16, 'pepperoni')
make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')

16-inch pizza:
- pepperoni
12-inch pizza:
- mushrooms
- green peppers
- extra cheese
  • Using Arbitrary Keyword Arguments


def build_profile(**user_info):
    print(user_info)

build_profile(location='Shanghai',field='Management')

{'location': 'Shanghai', 'field': 'Management'}
  • Using Arbitrary Keyword Arguments


def build_profile(first, last, **user_info):
    profile = {}
    for key, value in user_info.items():
        profile[key] = value
    return first, last, profile

user_profile = build_profile('albert', 'einstein',
                            location='princeton',
                            field='physics')
print(user_profile)

('albert', 'einstein', 
{'location': 'princeton', 'field': 'physics'})

def build_profile(*name, **user_info):
    print(name)
    print(user_info)

build_profile('albert', 'einstein',
               location='princeton',
               field='physics')

('albert', 'einstein')
{'location': 'princeton', 'field': 'physics'}
  • As a tradition, we often use *args and **kw

  • Example


def test(x,y=1,*a,**b):
    print(x,y,a,b)

test(1)
test(1,2)
test(1,2,3)
test(1,2,3,4)
test(x=1,y=2)
test(1,a=2)
test(1,2,3,a=4)
test(1,2,3,y=4)

  • Result




1 1 () {}
1 2 () {}
1 2 (3,) {}
1 2 (3, 4) {}
1 2 () {}
1 1 () {'a': 2}
1 2 (3,) {'a': 4}
TypeError: test() got multiple values

7.3 Complex Systems

Complex Systems (复杂系统)

  • A complex system is a system composed of many components which may interact with each other.
  • These parts are often quite simple to understand and to model individually.
  • When these parts are put together, most complex systems display surprising and unpredictable behavior that can be difficult to explain just by looking at the parts separately.

  • Examples of complex systems are earth's global climate, organisms, the human brain, infrastructure such as power grid, transportation or communication systems, complex software and electronic systems, social and economic organizations (like cities), an ecosystem, a living cell, and ultimately the entire universe.

Example 1: bird flock (Complex Adaptive Systems, 复杂适应系统)

  • The rules are simple!
  • There is no "leader" or "control".
  • 1. Stay together; 2. Do not crash into each other; 3. Avoid predators and obstacles

Example 2: butterfly effect (Chaos Theory, 混沌理论)

  • In chaos theory, the butterfly effect is the sensitive dependence on initial conditions in which a small change in one state of a deterministic nonlinear system can result in large differences in a later state.
  • The term is closely associated with the work of mathematician and meteorologist Edward Norton Lorenz. He noted that butterfly effect is derived from the metaphorical example of the details of a tornado being influenced by minor perturbations such as a distant butterfly flapping its wings several weeks earlier.

Example 3: pattern formulation (Fractal Theory, 分形理论)

  • In mathematics, fractal is a term used to describe geometric shapes containing detailed structure at arbitrarily small scales, usually having a fractal dimension strictly exceeding the topological dimension.

Mandelbrot set (曼德勃罗集--“上帝的指纹”)

  • A complex number $c$ is a member of the Mandelbrot set if when starting with $z_0=0$ and applying the iteration repeatedly, the absolute value of $z_n$ remains bounded for all $n>0$.

Application

  • Complex theory:
    • Reduce the problem and understand the rule
    • build up the model and simulate the phenomenon
    • Predict the future
  • Disciplines: statistical physics, information theory, nonlinear dynamics, anthropology, computer science, meteorology, sociology, economics, psychology, and biology.
  • The 2021 Nobel Prize in Physics was awarded to Syukuro Manabe, Klaus Hasselmann, and Giorgio Parisi for their work to understand complex systems. Their work was used to create more accurate computer models of the effect of global warming on the Earth's climate.
  • 对此领域有兴趣可进一步了解:BBC纪录片-神秘的混沌理论(2009)

Can complex system be Designed?

Cellular Automaton (元胞自动机)

  • At the boundary of mathematics, computer science, and games lies a peculiar field that studies cellular automaton.

  • Cellular automaton is a simple set of rules governing the appearance of spaces, or cells, in a line or on a grid.

  • Each cell may be either black or white. The rules determine what causes a cell to change from black to white (or vice versa) and how the color of a cell influences the cells around it.

  • Mathematicians think of such a collection of rules as a hypothetical machine that operates by itself without human intervention. This is why they are called automata.

  • A cellular automaton starts with its cells in a given configuration (some white, some black) and then applies the rules to each cell to determine whether its color should change.

  • It does not change a cell immediately; it checks every cell in the grid first, marks the ones to be changed, and then changes them all before the next iteration. Then it repeats the process. Each iteration is called a generation.

7.4 Game of Life

Game of Life (生命演化游戏)

  • Probably the most famous cellular automaton was invented by John Conway and is called the Game of Life.

  • Conway was a Professor Emeritus of Mathematics at Princeton University in New Jersey.

  • Conway's automaton consists of cells that are laid out on a two-dimensional grid.

  • this grid goes on indefinitely in all directions. Each cell on the grid has eight neighbors: the cells that surround it orthogonally and diagonally. Each cell can be in two different states: It is either dead or alive.

  • In most examples, dead cells are rendered white, while live cells are colored black.

Rules

  • A live cell that has fewer than two live neighbors dies from loneliness.

  • A live cell that has more than three live neighbors dies from overcrowding.

  • A live cell that has two or three live neighbors stays alive.

  • A dead cell that has exactly three live neighbors becomes alive.

Example

  • When set into motion, the Game of Life usually has quite chaotic results, with a lot of activity exploding from its original live cells.

  • Demo: Game of Life (Random)

  • Frequently after a number of iterations the Game of Life settles in a more or less stable configuration, sometimes with a few groups of cells that oscillate between two states.


import os
import random

width = 60
height = 60
screen = []

Step 1: Initialization


def Init():
    for i in range(height):
        line = []
        for j in range(width):
            if random.random() > 0.8:
                line.append('#')
            else:
                line.append(' ')
        screen.append(line)

Step 2: Show the screen


def PrintScreen():
    for i in range(height):
        for j in range(width):
            print(screen[i][j] + ' ', end='')
        print()

Step 3: Get cells


def TryGetCell(i, j):
    i = i % height
    j = j % width
    return screen[i][j]

Step 4: Count cells nearby


def GetNearbyCellsCount(i, j):
    nearby = []
    nearby.append(TryGetCell(i - 1, j - 1))
    nearby.append(TryGetCell(i - 1, j))
    nearby.append(TryGetCell(i - 1, j + 1))
    nearby.append(TryGetCell(i, j - 1))
    nearby.append(TryGetCell(i, j + 1))
    nearby.append(TryGetCell(i + 1, j - 1))
    nearby.append(TryGetCell(i + 1, j))
    nearby.append(TryGetCell(i + 1, j + 1))
    num = 0
    for x in nearby:
        if x == '#':
            num = num + 1
    return num

Step 5: Update


def Update():
    global screen
    newScreen = []
    for i in range(height):
        line = []
        for j in range(width):
            line.append(' ')
        newScreen.append(line)
    for i in range(height):
        for j in range(width):
            count = GetNearbyCellsCount(i, j)
            if count == 3:
                newScreen[i][j] = '#'
            elif count < 2 or count > 3:
                newScreen[i][j] = ' '
            else:
                newScreen[i][j] = screen[i][j]    
    screen = newScreen

Step 6: Console (for win). For mac, replace "cls" by "clear".


def Start():
    os.system("cls")
    print('== Game of Life ==')
    print('Press any key...')
    input()
    os.system("cls")
    Init()
    PrintScreen()
    c = input()
    while c!= 'q':
        os.system("cls")
        Update()
        PrintScreen()   
        c = input()
    print('End')

Start()
  • One of the earliest questions that the researchers studying the Game of Life asked themselves was this: "Is there an initial configuration of live cells that expands forever?"

  • Glider

  • Glider gun

  • 史诗般的生命游戏

Summary

  • Functions
    • Reading: Python for Everybody, Chapter 4
    • Reading: Python Crash Course, Chapter 8