Python Programming

Lecture 6 Functions, Modules

6.1 Functions Basics

Create functions

  • A function is a named sequence of statements that performs a computation.

  • Build-in Functions: int(), float(), str(), type(), and etc.

  • Follow two steps: 1. define a function(定义) 2. call a function(调用)

  • 
    def lyrics():
        print("I'm okay.")
    
    lyrics()
    
  • The first line of the function is called the header. The rest is called the body.

  • 
    def repeat_lyrics():
        lyrics()
        lyrics()
    
    repeat_lyrics()
    
    
    I'm okay.
    I'm okay.
    

Parameters and arguments (形参和实参)


def print_twice(bruce): 
    print(bruce)
    print(bruce)

print_twice('Spam')
print_twice(17)

Spam
Spam
17
17

michael = 'Eric, the half a bee.'
print_twice(michael)

Eric, the half a bee.
Eric, the half a bee.

Multiple parameters

  • Positional Arguments


def describe_pet(type, name):
    print(f"My {type}'s name is {name}.")

describe_pet('hamster', 'Harry')
describe_pet('dog', 'Willie')

My hamster's name is Harry.
My dog's name is Willie.

describe_pet('harry', 'Hamster') #Order Matters

My harry's name is Hamster.
  • Keyword Arguments (关键字参数)


def describe_pet(type, name):
    print(f"My {type}'s name is {name}.")

describe_pet(type='hamster', name='harry')
describe_pet(name='harry', type='hamster')

Fruitful functions and void functions

  • A fruitful function returns a value, while a void function performs an action but does not return a value.

  • To return a result from a function, we use the return statement in our function.

  • Return means the termination of a function. If you have two returns, only the first one will take effect.


def addtwo(a, b):
    added = a + b
    return added 
x = addtwo(3, 5)
print(x)


8

def addtwo(a, b):
    added = a + b 

x = addtwo(3, 5)
print(x)

None

def addtwo(a, b):
    added = a + b 
    print(added)

x = addtwo(3, 5)
print(x)

8
None

def addtwo(a, b):
    added = a + b 
    print(added)
    return added
x = addtwo(3, 5)
print(x)

8
8
  • If we want to return multiple values, the function returns a tuple.


def addtwo(a, b):
    added = a + b
    return a, b, added

x = addtwo(3, 5)
print(x)

(3, 5, 8)
  • A function can return any kind of value you need it to, including more complicated data structures like lists and dictionaries.


def build_person(first, last):
    person = {1: first, 2: last}
    return person

musician = build_person('jimi', 'hendrix')
print(musician)

{1: 'jimi', 2: 'hendrix'}

Exercise: 可乐瓶换饮料问题

  • 小明喝可乐的习惯是: 每喝完一瓶,就可以用 3 个空瓶 换一瓶新的可乐。如果他一开始有 n 瓶可乐,请编写一个函数,计算他总共能喝到多少瓶可乐。完成下面的代码。
  • 提示思路:用 while 循环判断每轮是否还能换,用整数除法 // 计算每轮能换到多少新的可乐,取余 % 计算每轮剩余的空瓶子
  • 
    def total_cola(n):
        total = n         # 喝掉的总数
        bottles = n       # 当前拥有的空瓶数
    
        # 把你的代码填到这里
    
        return total
    

6.2 Modules(模块)

  • Module is a Python file, followed with .py

  • Storing Your Functions in Modules

  • 
    def make_pizza(size):
        print(f"Making a {size}-inch pizza")
    
  • 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)
    

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)

Using as to Give a Function an Alias(别名)


from pizza import make_pizza as mp

mp(16)

Using as to Give a Module an Alias


import pizza as p

p.make_pizza(16)
  • Importing All Functions in a Module


from pizza import *

make_pizza(16)
  • 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 (当前工作目录).

  • PYTHONPATH (a list of directory names:标准库路径,第三方库路径)


import sys
print(sys.path)

Install third-party packages

  • Anaconda already includes many useful packages, and you can install additional ones as needed.
  • For Windows, open the anaconda prompt for anaconda, or open the cmd for original Python.

  • 
    
    pip install pillow
    #conda install pillow
    
  • For macOS, open the terminal.

  • 
    pip install pillow
    #conda install pillow
    
  • Uninstall the package

  • 
    pip uninstall pillow
    #conda uninstall pillow
    
  • List all the packages

  • 
    pip list
    #conda list
    

Some third-party packages


import random

print(random.randint(1, 10))         # 产生 1 到 10 的一个整数型随机数
print(random.random())               # 产生 0 到 1 之间的随机浮点数

print(random.choice('tomorrow'))     # 从容器中随机选取一个元素

a = [1, 3, 5, 6, 7]                
random.shuffle(a)                    # 将列表a中的元素顺序打乱
you-get安装使用说明

pip install you-get 
# youtube-dl
Free Python Games官网

pip install freegames

6.3 Blackjack (21点游戏)

简化版21点游戏规则

  • 游戏开始时,玩家会获得两张牌。每张牌都有一个点数:

  • 2 到 10 按照数字本身计算,J、Q、K 都记为 10,A 先按 11 计,如果总点数超过 21 点(爆了)就变成 1。

  • 接下来,玩家可以反复做一个选择:是否继续抽一张牌。

  • 每抽一张牌,都会把点数加入当前总和中。如果总点数:
    • 超过 21,游戏结束(爆掉输了)

    • 等于 21,游戏结束(最佳结果)

    • 小于 21,可以继续选择是否抽牌

    • 玩家可以在任何时候选择停止抽牌,此时游戏结束,最终点数就是当前总和。

真实 21 点游戏中的额外规则

  • 首先,玩家自己选择把A当成11或者1(简化版只做了最基本处理)。

  • 其次,游戏中不仅有玩家,还有庄家(dealer)。庄家会按照固定规则(例如点数小于 17 必须继续要牌)行动,玩家需要与庄家比较点数来决定输赢。

  • 此外,还存在一些额外操作,例如:
    • Blackjack(黑杰克):前两张牌正好是 21,通常有更高奖励

    • 分牌(split):当两张牌相同时可以拆分成两手

    • 加倍(double down):加注并只再抽一张牌

教学视频: 赌棍 The Gambler (2014)

import random

# 2-10直接用数值表示,JQK作为10,A作为11(可以调整为1)
def create_deck():
    values = [2,3,4,5,6,7,8,9,10,10,10,10,11] 
    deck = values * 4  # 4种花色
    random.shuffle(deck)
    return deck

# 计算手牌点数(考虑 A=11 变 A=1 的情况)
def calculate(cards):
    total = sum(cards)
    aces = cards.count(11) # 数A个数
    while total > 21 and aces > 0:
        total -= 10  # 将A从11变1
        aces -= 1
    return total

def player_turn(deck):
    player_hand = []
    while True:
        score = calculate(player_hand)
        print("玩家手牌:", player_hand, "当前点数:", score)
        
        if score > 21:
            print("爆了!")
            break
        
        move = input("是否要牌?(y/n): ")
        if move == 'y':
            player_hand.append(deck.pop())
        else:
            break
    
    return score


deck = create_deck()
score = player_turn(deck)
print("最终点数:", score)

Exercise: 德州扑克随机发牌(也类似Balatro小丑牌)

    改写下面代码中的函数,完成发牌
  1. 先给玩家 2 张牌(hole cards)
  2. 再出公共牌 5 张(community cards)

# 改写这段代码
def create_deck():
    values = [2,3,4,5,6,7,8,9,10,10,10,10,11] 
    deck = values * 4  # 4种花色
    random.shuffle(deck)
    return deck


# 输出示例
['♠8', '♠K']
['♦2', '♦10', '♥K', '♥8', '♣A']


提示:用如下代码定义点数和花色

ranks = ["J", "Q", "K", "A"]
for x in range(2,11):
    ranks.append(str(x))
print(ranks)
suits = ["\u2660", "\u2665", "\u2663", "\u2666"]

# 上面的代码会得到
# ranks = ['J', 'Q', 'K', 'A', '2', '3', '4', '5', '6', '7', '8', '9', '10']
# suits = ["♠", "♥", "♣", "♦"]

Summary

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