【学习笔记】《Python编程 从入门到实践》第8章:函数定义、参数传递与模块导入
第8章 函数系列第 8 篇本文是《Python编程 从入门到实践》读书笔记系列的第 8 篇。本文内容函数定义、位置实参与关键字实参、默认值、返回值、传递列表、任意数量实参、函数存储在模块中。本章目标定义和调用函数传递参数的各种方式返回值将函数存储在模块中。开篇这篇解决什么问题函数不是为了让代码看起来高级而是为了把一段有明确目的的逻辑收起来需要时再调用。写脚本时只要某段逻辑出现第二次就可以考虑封装成函数。本篇你会学到什么如何定义和调用函数位置参数、关键字参数、默认参数怎么用函数如何返回值列表传给函数时要注意什么如何把函数放进模块里复用场景案例封装一条任务通知不使用函数时代码可能这样写task_namedaily_reportowneraliceprint(Task task_name is assigned to owner.)如果很多地方都要输出类似通知就可以封装成函数defnotify_task(task_name,owner):Print a simple task notification.print(Task task_name is assigned to owner.)notify_task(daily_report,alice)notify_task(data_backup,bob)函数让重复逻辑有了名字也让代码更容易复用。知识点拆解1. 定义函数defgreet_user():Display a simple greeting.print(Hello!)greet_user()def用来定义函数缩进里的代码是函数体。函数定义后不会自动执行必须调用才会运行。2. 向函数传递信息defgreet_user(username):Display a greeting to the user.print(Hello, username.title()!)greet_user(alice)username是形参alice是实参。3. 位置实参位置实参按顺序匹配defdescribe_task(task_name,owner):print(task_name - owner)describe_task(daily_report,alice)如果顺序写反结果也会跟着变错。所以位置参数适合数量少、顺序很清楚的情况。4. 关键字实参关键字实参直接写参数名defdescribe_task(task_name,owner):print(task_name - owner)describe_task(owneralice,task_namedaily_report)这种写法顺序不重要可读性更强。5. 默认参数defdescribe_task(task_name,statuspending):print(task_name is status)describe_task(daily_report)describe_task(data_backup,done)默认参数要放在没有默认值的参数后面。6. 返回值函数可以用return返回结果defbuild_task_name(project,task):full_nameproject-taskreturnfull_name.lower()namebuild_task_name(WorkBuddy,Report)print(name)输出workbuddy-report7. 返回字典defbuild_task(task_name,owner,statuspending):task{name:task_name,owner:owner,status:status,}returntask new_taskbuild_task(daily_report,alice)print(new_task)函数返回字典很常见适合封装结构化数据。8. 传递列表defprint_tasks(tasks):fortaskintasks:print(- task)todo_tasks[write report,check email]print_tasks(todo_tasks)9. 函数中修改列表列表传给函数后函数内部可以修改它deffinish_tasks(pending_tasks,finished_tasks):whilepending_tasks:taskpending_tasks.pop()finished_tasks.append(task)pending[write report,check email]finished[]finish_tasks(pending,finished)print(pending)print(finished)如果不希望修改原列表可以传副本finish_tasks(pending[:],finished)10. 任意数量的位置实参defmake_tags(*tags):fortagintags:print(#tag)make_tags(python,note,beginner)*tags会把多个位置实参收集成元组。11. 任意数量的关键字实参defbuild_profile(username,**info):profile{username:username}forkey,valueininfo.items():profile[key]valuereturnprofile profilebuild_profile(alice,roleadmin,locationbeijing)print(profile)**info会把关键字实参收集成字典。12. 导入模块可以把函数放到单独文件里比如task_utils.pydefnotify_task(task_name,owner):print(Task task_name is assigned to owner.)在另一个文件中导入fromtask_utilsimportnotify_task notify_task(daily_report,alice)不建议为了省事到处使用from module import *。明确导入需要的函数可读性更好。初学者容易踩的坑问题常见原因建议函数定义了但没执行忘记调用定义后写function_name()参数顺序传错位置实参依赖顺序参数多时用关键字实参默认参数位置错误默认参数放在普通参数前面默认参数放最后函数返回None忘记写return需要结果时必须return函数修改了原列表传入的是同一个列表对象不想修改时传副本list[:]工作里能怎么用场景函数可以怎么用读取配置load_config()保存结果save_result()发送通知notify_task()校验输入validate_input()处理列表filter_tasks()示例判断任务是否可以执行defcan_run(task):returntask.get(status)pendingtask{name:daily_report,status:pending}ifcan_run(task):print(Run task.)小结函数用def定义用函数名加括号调用位置实参按顺序匹配关键字实参按名称匹配可读性更强默认参数适合给常用值设置默认行为return用来返回结果函数可以接收列表也可能修改列表*args接收任意数量位置实参**kwargs接收任意数量关键字实参模块化能让函数跨文件复用下一篇下一篇继续讲类。函数能整理动作类可以把数据和动作放在一起更适合表达任务、用户、订单这类对象。