1 函数定义

关键字def引入函数定义。它后面必须跟函数名和括号中的形式参数列表

def fib(n):    # write Fibonacci series less than n
    """Print a Fibonacci series less than n."""
    a, b = 0, 1
    while a < n:
        print(a, end=' ')
        a, b = b, a+b
    print()

# 调用函数
fib(2000)

函数体的第一个语句可以是一个字符串,就是函数的文档。函数的执行会引入一个新的符号表*,用于存储函数的局部变量。实际参数(实参)在被调用函数被调用时引入到其局部符号表中,实参是使用传递的(其中始终是对象引用*,而不是对象的值)。

没有 return语句的函数也会返回一个值None

2 定义可变参数的函数

2.1 默认参数值

def ask_ok(prompt, retries=4, reminder='Please try again!'):
    while True:
        reply = input(prompt)
        if reply in {'y', 'ye', 'yes'}:
            return True
        if reply in {'n', 'no', 'nop', 'nope'}:
            return False
        retries = retries - 1
        if retries < 0:
            raise ValueError('invalid user response')
        print(reminder)
# 调用
ask_ok('Do you really want to quit?')
ask_ok('OK to overwrite the file?', 2)
ask_ok('OK to overwrite the file?', 2, 'Come on, only yes or no!')        

2.2 关键字参数

调用的时候可以无序使用key=value调用

def connect(host, port=80, timeout=10):
    print(f"连接到 {host}:{port},超时 {timeout}s")
# 定义可以跟默认参数值一样定义
connect(host="example.com", timeout=5)
connect(timeout=5, host="example.com")

*name 接收一个元组

**name 接收一个字典

*name必须出现在**name之前,

def cheeseshop(kind, *arguments, **keywords):
    print("-- Do you have any", kind, "?")
    print("-- I'm sorry, we're all out of", kind)
    for arg in arguments:
        print(arg)
    print("-" * 40)
    for kw in keywords:
        print(kw, ":", keywords[kw])
        
#调用
cheeseshop("Limburger", "It's very runny, sir.",
           "It's really very, VERY runny, sir.",
           shopkeeper="Michael Palin",
           client="John Cleese",
           sketch="Cheese Shop Sketch")
#返回结果
-- Do you have any Limburger ?
-- I'm sorry, we're all out of Limburger
It's very runny, sir.
It's really very, VERY runny, sir.
----------------------------------------
shopkeeper : Michael Palin
client : John Cleese
sketch : Cheese Shop Sketch                   

2.3 特殊参数

def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):

/的左侧: 必须使用位置传递 f(1, 2)

/和*之间: 可以按位置或关键字传递