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
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'}
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]
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
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.
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.
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.
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.
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