☰
c9-python-getting-started 实战教程:Python 函数入门——用 def 封装重复代码、参数传递与返回值
2026/10/15 19:02:47 网站建设 项目流程
  • 示例工程
  • 教程

【免费下载链接】c9-python-getting-started

Sample code for Channel 9 Python for Beginners course

项目地址:https://gitcode.com/gh_mirrors/c9/c9-python-getting-started
点击查看免费下载

本篇指南基于 c9-python-getting-started(Channel 9 Python for Beginners 课程)的 13 - Functions 章节,系统讲解 Python 函数的核心机制:def定义语法、声明顺序约束、参数传入与返回值提取。你将通过本仓库中「打印时间戳」「提取姓名首字母」「计算器挑战」三组循序渐进的可运行示例,掌握把重复代码重构为可复用函数的完整方法。

一、函数是什么:把重复代码收进一个「可调用模块」

在 13 - Functions/README.md 中,课程对函数给出了精炼的定义:

Functions allow you to take code that is repeated and move it to a module that can be called when needed.

即:函数允许你把反复出现的代码段抽离出来,放进一个可以在需要时随时调用的「模块」中。它的价值在于:

  • 消除重复:同一段逻辑只写一次,避免复制粘贴导致的维护灾难;
  • 按需调用:程序可以在任意需要的位置触发这段逻辑,而不用把代码原样写多遍;
  • 抽象细节:调用方只关心「调用函数能得到什么」,无需关心内部实现。

课程还强调了两条关于函数的硬性规则:

  1. 函数使用def关键字定义;
  2. 函数必须先声明(定义),之后才能在代码中调用——因为 Python 解释器自上而下顺序执行代码,调用发生在定义之前会直接抛出NameError。

函数还可以「接受参数」(parameters)并「返回值」(return values),这正是它与普通代码块拉开差距的关键能力。

二、函数基本语法:def模板逐行拆解

README 给出了函数的最小可运行模板:

def functionname(parameter): # code to execute return value

逐行拆解如下:

组成部分说明
def定义函数的关键字,Python 见到它就开始声明一个新函数
functionname函数名,遵循标识符命名规范,应能准确描述函数行为
(parameter)参数列表,函数接收的外部输入;可以有一个、多个,也可以为空(写())
缩进的函数体def下一行开始的所有缩进代码,是每次调用时真正执行的逻辑
return value返回值语句,把计算结果交还给调用方;return后可省略值表示仅结束函数

仓库中一个最简单、最标准的函数示例来自 get_initails_function.py:

def get_initial(name): initial = name[0:1].upper() return initial

这里name是参数,initial = name[0:1].upper()是函数体,return initial把首字母大写结果交还给调用方。整个结构正是 README 模板的落地实现。

三、实战一:用函数消灭重复代码(打印任务时间戳)

课程用一个非常贴近真实场景的例子说明「为什么要用函数」:在代码的不同阶段打印当前时间,用于观察每段代码的执行耗时。

3.1 重复代码版本(反面教材)

print_time_repeated_code.py 展示了没有函数时的写法——同样的三行逻辑被完整复制了两遍:

import datetime # print timestamps after each section of code # to see how long sections of code take to run first_name = 'Susan' print('task completed') print(datetime.datetime.now()) print() for x in range(0,10): print(x) print('task completed') print(datetime.datetime.now()) print()

问题很明显:print('task completed')、print(datetime.datetime.now())、print()三行代码出现了两次。如果日后要修改提示文案或时间格式,必须同步改两处,漏改一处就会造成行为不一致。

3.2 函数版本(推荐写法)

print_time_function.py 将这三行逻辑封装进print_time函数,调用处只需一行:

import datetime # Create a function called print_time # This function will print the message and current time def print_time(): print('task completed') print(datetime.datetime.now()) print() first_name = 'Susan' # Call print_time() function to display message and current time print_time() for x in range(0,10): print(x) # Call print_time() function to display message and current time print_time()

对比可见:函数体只维护一份,调用点print_time()两处完全一致,任何修改只需在def print_time():内部进行,一次改动全局生效。

3.3 顺带解决一个 import 细节

仓库还提供了 print_time_function_fix_import.py,它把import datetime改为from datetime import datetime:

from datetime import datetime def print_time(): print('task completed') print(datetime.now()) print()

这样函数体内的调用从datetime.datetime.now()简化为datetime.now(),缩短了调用链、提升了可读性。从源码结构可以推断,这个文件旨在演示:当函数体频繁使用某个类时,用from ... import ...方式导入能让函数代码更简洁。

四、实战二:参数与返回值——提取姓名首字母

时间戳例子中的函数没有参数、也没有返回值(print_time()只做输出)。课程紧接着用「提取姓名首字母」演示函数最核心的两项能力:接收参数与返回结果。

4.1 重复代码版本

get_initials.py 对三个名字分别重复执行「取切片 + 拼接」的逻辑:

# Ask for a name and return the initials first_name = input('Enter your first name: ') first_name_initial = first_name[0:1] middle_name = input('Enter your middle name: ') middle_name_initial = middle_name[0:1] last_name = input('Enter your last name: ') last_name_initial = last_name[0:1] print('Your initials are: ' + first_name_initial \ + middle_name_initial + last_name_initial)

name[0:1]这个取首字符的切片操作重复了三次——正是函数最擅长解决的场景。

4.2 函数版本

get_initails_function.py 先把取首字母的逻辑提炼成get_initial(name):

# Create function get_initial to accept a name and # return the first letter of the name in uppercase # Parameters: # name: the name of a person # Return value: # first letter of name passed in as a parameter in uppercase def get_initial(name): initial = name[0:1].upper() return initial # This program will ask for someone's name and return the initials first_name = input('Enter your first name: ') # Call get_initial to retrieve initial of name first_name_initial = get_initial(first_name) middle_name = input('Enter your middle name: ') # Call get_initial to retrieve initial of name middle_name_initial = get_initial(middle_name) last_name = input('Enter your last name: ') # Call get_initial to retrieve initial of name last_name_initial = get_initial(last_name) print('Your initials are: ' + first_name_initial \ + middle_name_initial + last_name_initial)

这个版本值得注意的细节:

  • 参数:get_initial(name)中的name接收调用时传入的字符串,函数内部使用name[0:1]取出首字符;
  • 返回值:return initial把大写首字母交还给调用处,赋值给first_name_initial等变量;
  • 行为增强:函数版本额外调用了.upper(),把首字母转为大写,比原重复代码多了一层健壮性——同样的改动只需发生一次,体现了封装带来的「一处修改、全局受益」。

五、参数化演进:让函数适配不同消息

时间戳函数最初硬编码了消息'task completed'。但如果不同阶段想打印不同的提示文案怎么办?仓库用两个文件展示了参数化改造的全过程。

5.1 发现问题

print_time_function_different_messages.py 中,代码仍在函数外重复写print('first name assigned')/print('loop completed')加上时间打印:

from datetime import datetime first_name = 'Susan' print('first name assigned') print(datetime.now()) print() for x in range(0,10): print(x) print('loop completed') print(datetime.now()) print()

消息各不相同,导致函数化的时间打印逻辑又退化回了复制粘贴。

5.2 用参数解决问题

print_time_with_message_parameter.py 给出了正解——给函数增加一个task_name参数:

from datetime import datetime # Define a function to print the current time and task name # Function the following parameters: # task_name: Name of the task to display to output screen def print_time(task_name): print(task_name) print(datetime.now()) print() first_name = 'Susan' # Call print_time() function to display message and current time # pass in name of task completed print_time('first name assigned') for x in range(0,10): print(x) # Call print_time() function to display message and current time # pass in name of task completed print_time('loop completed')

关键变化:print_time的形参task_name接收调用时传入的实参('first name assigned'、'loop completed'),函数体直接print(task_name)。从此「打印任务名 + 当前时间 + 空行」的逻辑只存在一份,而输出内容由调用方通过参数自由定制——这就是**参数让函数从「固定功能」走向「通用功能」**的典型演示。

六、综合挑战:用函数实现一个计算器

章节末尾的 code_challenge.py 给出了一道综合练习,把本章全部知识点(def、多参数、返回值、分支判断)串起来:

创建一个calculator函数,接收三个参数:first_number(参与运算的数值)、second_number(参与运算的数值)、operation(字符串'add'或'subtract')。函数根据operation的值返回两数相加或相减的结果。用6, 4, add测试应返回10,用6, 4, subtract测试应返回2。加分题:用6, 4, divide测试时,函数应返回一条错误提示而非计算结果。

参考答案解析

code_challenge_solution.py 的完整实现如下:

def calculator(first_number, second_number, operation): if operation.upper() == 'ADD': return(float(first_number) + float(second_number)) elif operation.upper() =='SUBTRACT': return(float(first_number) - float(second_number)) else: return('Invalid operation please specify ADD or SUBTRACT') # Test your function with the values 6,4, add # Should return 10 print('Adding 6 + 4 = ' + str(calculator(6,4,'add'))) # Test your function with the values 6,4, subtract # Should return 2 print('Subtracting 6 - 4 = ' + str(calculator(6,4,'subtract'))) # Test your function with the values 6,4, divide # Should return some sort of error message print('Dividing 6 / 4 = ' + str(calculator(6,4,'divide')))

这个参考答案包含三个值得学习的工程细节:

  1. 输入健壮性:operation.upper()把入参统一转为大写再比较,因此调用方传'add'、'Add'、'ADD'都能正确命中'ADD'分支;
  2. 类型容错:float(first_number)与float(second_number)显式转换,即使传入字符串形式的数字也能参与运算;
  3. 兜底分支:else分支对未识别的操作返回错误文案'Invalid operation please specify ADD or SUBTRACT',这正是加分题要求的行为——函数返回错误信息而非崩溃;
  4. 返回值的再加工:调用处用str(calculator(...))把返回的数值或字符串统一转成字符串,再拼接进print输出,说明返回值可以被调用方继续处理。

七、进阶技巧:直接在表达式中使用函数返回值

仓库还提供了一个「更精简但可读性存疑」的写法 getting_clever_with_functions_harder_to_read.py:

def get_initial(name): initial = name[0:1].upper() return initial #Ask for someone's name and return the initials first_name = input('Enter your first name: ') middle_name = input('Enter your middle name: ') last_name = input('Enter your last name: ') # Call get_initial function to return first letter of a name print('Your initials are: ' \ + get_initial(first_name) \ + get_initial(middle_name) \ + get_initial(last_name))

这里不再把返回值先存进中间变量,而是把get_initial(...)的调用直接嵌在print的字符串拼接表达式中。这样做省去了三个临时变量,代码更短;但从源码注释和文件名(harder_to_read,更难读)可以看出,课程的立场是明确的:这种写法降低了可读性,初学者应优先使用「先赋值、再使用」的清晰写法,待熟练后再权衡是否精简。这也是函数返回值灵活性的一体两面——它既可以赋值给变量,也可以作为表达式的一部分直接参与运算。

八、小结:本章函数知识点速查

  • 定义:def functionname(parameter):定义函数,函数体必须缩进,return value返回结果;
  • 顺序约束:函数必须在使用前完成定义,Python 自上而下执行,否则报NameError;
  • 参数:函数通过参数接收外部输入,多个参数用逗号分隔,调用时按位置传入实参(calculator(6, 4, 'add'));
  • 返回值:return把结果交还调用方,可直接赋值给变量,也可嵌入表达式;
  • 重构收益:从 print_time_repeated_code.py → print_time_function.py → print_time_with_message_parameter.py 的演进路线,展示了「重复代码 → 无参函数 → 带参函数」的完整重构路径;
  • 健壮性习惯:参考 code_challenge_solution.py 中的operation.upper()、float()转换与else兜底分支,让函数对异常输入更宽容。

以上所有示例均可直接在仓库对应目录下运行(如python3 "python-for-beginners/13 - Functions/get_initails_function.py")验证输出。函数是 Python 程序结构化的基石,掌握「封装重复逻辑、用参数表达差异、用返回值传递结果」之后,你就能顺畅进入下一章——函数参数默认值与命名参数等更精细的控制方式。

  • 示例工程
  • 教程

【免费下载链接】c9-python-getting-started

Sample code for Channel 9 Python for Beginners course

项目地址:https://gitcode.com/gh_mirrors/c9/c9-python-getting-started
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询