Kodokon kodokon.com

函数:def、参数、return 与作用域

把代码组织成可复用的函数,掌握默认值,并理解变量的作用域。

10 分钟 · 3 题

在 Kodokon 中打开本课

你已经会写循环和条件了;现在该把代码组织起来了。函数把一项具体任务隔离在一个清晰的名字背后:你只写一次,只测试一次,却可以到处调用。def 声明函数,参数接收传入的值,return 把结果送回给调用方。请记住一件经常被忽略的事:没有 return 的函数会返回 None

PYTHON
def net_price(price, tax_rate):
    total = price * (1 + tax_rate)
    return round(total, 2)

result = net_price(100, 0.2)
print(result)  # 120.0
函数接收两个参数,并用 return 送回一个值。

默认值让函数变得灵活,而不必衍生出一堆变体:把它们声明在必填参数之后。调用时,关键字实参currency="USD")能说明你的意图。在专业代码里,只要一个函数超过两个参数,就会用上它们:无需打开函数定义,调用处就一目了然。

PYTHON
def format_price(amount, currency="EUR", digits=2):
    return f"{amount:.{digits}f} {currency}"

print(format_price(19.9))                  # 19.90 EUR
print(format_price(19.9, currency="USD"))  # 19.90 USD
print(format_price(19.9, digits=0))        # 20 EUR
关键字实参让你只需指定发生变化的部分。
PYTHON
def add_item(item, items=None):
    if items is None:
        items = []
    items.append(item)
    return items

print(add_item("pen"))   # ['pen']
print(add_item("book"))  # ['book']
采用 None 模式后,每次调用都从一个全新的列表开始。

作用域决定了一个变量在哪里存在。在函数内部创建的变量是局部的:调用结束时它就消失了。函数可以读取全局变量,但任何赋值都会创建一个新的局部变量 - 全局变量原封不动。好习惯:与其修改全局变量,不如传入参数并返回结果;这样你的代码就变得可预测、可测试。

PYTHON
rate = 0.2

def apply_tax(price):
    return round(price * (1 + rate), 2)

def set_rate(new_rate):
    rate = new_rate  # local variable, no effect

print(apply_tax(100))  # 120.0
set_rate(0.1)
print(apply_tax(100))  # 120.0, the global is untouched
读取全局变量可行;给它赋值则会创建一个局部变量。

知识检测

确认你已牢记本课的重点内容。

  1. 一个没有 return 语句的 Python 函数会返回什么?
    • 0
    • None
    • 一个空字符串
    • 抛出一个错误
  2. 为什么应该避免 def add_item(item, items=[])?
    • 默认列表只创建一次,并被所有调用共享
    • 列表不能用作默认值
    • 它会在定义时抛出 SyntaxError
  3. 当已经存在同名的全局变量时,在函数内部给一个变量赋值会发生什么?
    • Python 修改那个全局变量
    • Python 创建一个局部变量,全局变量原封不动
    • Python 抛出命名冲突错误