Python Programming

Lecture 7 Modules, Game of Life

7.1 Modules

  • Module is a Python file, followed with .py

  • Storing Your Functions in Modules


def make_pizza(size, *toppings):
    print("\nMaking a " + str(size) +
        "-inch pizza with the following toppings:")
    for topping in toppings:
        print("- " + topping)
  • It is saved as "pizza.py" file.

  • We make a separate file called making_pizzas.py in the same directory as pizza.py.


import pizza

pizza.make_pizza(16, 'pepperoni')
pizza.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
  • Be Careful!


def make_pizza(size, *toppings):
    print("\nMaking a " + str(size) +
        "-inch pizza with the following toppings:")
    for topping in toppings:
        print("- " + topping)

make_pizza(16, 'pepperoni')

#saved as pizza.py

import pizza

#in another python file

Making a 16-inch pizza with the following toppings:
- pepperoni
  • A way to solve it


def make_pizza(size, *toppings):
    print("\nMaking a " + str(size) +
        "-inch pizza with the following toppings:")
    for topping in toppings:
        print("- " + topping)

if __name__ == '__main__': 
    make_pizza(16, 'pepperoni')

#saved as pizza.py

import pizza

#in another python file

Importing Specific Functions


#from module_name import function_name
#from module_name import function_0, function_1, function_2

from pizza import make_pizza

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

Using as to Give a Function an Alias


from pizza import make_pizza as mp
mp(16, 'pepperoni')
mp(12, 'mushrooms', 'green peppers', 'extra cheese')

Using as to Give a Module an Alias


import pizza as p
p.make_pizza(16, 'pepperoni')
p.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
  • Importing All Functions in a Module


from pizza import *
make_pizza(16, 'pepperoni')
make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
  • The asterisk in the import statement tells Python to copy every function from the module pizza into this program file. Because every function is imported, you can call each function by name without using the dot notation.

  • However, it's best not to use this approach when you're working with larger modules that you didn't write: if the module has a function name that matches an existing name in your project, you can get some unexpected results.

Search for Modules

  • When a module named is imported, the interpreter first searches for a built-in module with that name. If not found, it then searches for a file named xxx.py in a list of directories given by the variable sys.path. sys.path is initialized from these locations:

  • The directory containing the input script (or the current directory when no file is specified).

  • PYTHONPATH (a list of directory names, with the same syntax as the shell variable PATH).

  • The installation-dependent default.


import sys
print(sys.path)

Packages

  • Packages are namespaces which contain multiple packages and modules themselves. They are simply directories, but with a twist.

  • Each package in Python is a directory which MUST contain a special file called __init__.py. This file can be empty, and it indicates that the directory it contains is a Python package, so it can be imported the same way a module can be imported.


mycompany
├─ __init__.py
├─ abc.py
└─ xyz.py
  • The name of modules are mycompany.abc and mycompany.xyz

  • Be careful! The name of modules you created should not be in conflict with the name of any system module, or any build-in function.

Third party modules


import urllib
dir(urllib)
  • For Python only, open the cmd.

  • 
    pip install pillow
    
  • For Anaconda only, open the anaconda prompt.

  • 
    conda install pillow
    pip install pillow
    
  • If you want to use both the Python and Anaconda, there might be some conflicts. Thus, please change file name in the Anaconda. D:\Anaconda\Scripts, pip.exe and pip-script.exe to condapip.exe and condapip-script.exe

  • 
    condapip install pillow #anaconda
    
Uninstall the package

pip uninstall pillow
conda uninstall pillow
List all the packages

pip list
conda list
Examples

conda install you-get 
conda install pyperclip
conda install itchat 

import pyperclip
pyperclip.copy("abc")

import itchat
itchat.auto_login()

friends = itchat.get_friends(update=True)[0:]


male = 0
female = 0
other = 0
for i in friends[1:]:
    sex = i['Sex']
    if sex == 1:
        male = male + 1
    elif sex ==2:
        female = female + 1
    else:
        other = other + 1
total = len(friends[1:])

print('男性好友: {}%'.format(male/total*100))
print('女性好友: {}%'.format(female/total*100)) 
print('其他: {}%' .format(other/total*100))

itchat.logout() 

7.2 Example: Game of Life

生命演化游戏

Complex System

  • The system consists of many parts.

  • These parts are often quite simple to understand and to model individually. (The Butterfly Effect)

  • 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.

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.

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


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

  • Demo: glider

  • Glider gun

Summary

  • Functions
    • Reading: Python for Everybody, Chapter 10.1-10.5, 10.7-10.8
    • Reading: Python Crash Course, Chapter 8