Python函数返回值详解:从笨办法学python练习21理解return与print区别

发布时间:2026/9/29 17:22:33
Python函数返回值详解:从笨办法学python练习21理解return与print区别 很多自学Python的人都会在《笨办法学python》这本书的某个练习卡住。我见过不少读者前面几课还顺风顺水一到练习21就懵了——因为这一课出现了全书第一个真正需要动脑的转折点函数返回值。它跟之前那些打印一行字、算个加法完全不是一个量级。别不好意思承认我当时也在这一课来回敲了三遍才彻底想通。如果你正在学Python或者已经翻到这一课但没完全消化这篇博文就是为你准备的。我会把练习21的代码逐行拆开讲清楚 return 和 print 的区别、函数嵌套调用的底层逻辑再用几个能直接跑的案例带你上手。不绕弯子、不堆术语保证你看完能照着复现还顺手帮你避开我当年踩过的一堆坑。1. 为什么偏偏是这一课1.1 一本书里的分水岭先交代一下《笨办法学python》这书的调性。作者 Zed Shaw 的教学思路说白了就是手打代码肌肉记忆每节课都短得要命但要求你一句一句敲进终端而不是复制粘贴。这种搞法前期特别劝退因为到处是重复的 print、重复的变量赋值你会觉得这不就是打字练习吗。但到了练习21情况变了。书里第一次让你写这样的代码一个函数把计算结果 还回来还回来的结果又被塞进另一个函数。这个抽象层级的变化正是我从会写Python脚本到会设计Python代码的分水岭。前面的练习只是教你怎么让机器输出东西第21课开始教你怎么让代码在内部传递东西。很多初学者这时候会陷入一个误区觉得return和print差不多反正屏幕上都能看到结果。这是完全错误的理解而且这个错误概念如果不尽早纠正后面学到数据清洗、接口调用、类方法的时候会四处碰壁。1.2 这一课到底在练什么练习21的核心内容其实就四个函数add、subtract、multiply、divide。每个函数做的事情都一样——接收两个参数打印一行说明文字然后把计算结果用return返回。最后再用一个嵌套调用的表达式把四个函数组合起来算出一个最终值。听起来特别简单对吧但它的威力在于函数调用的结果可以继续作为参数传给另一个函数。这个思想贯穿了后续所有内容也是写代码像拼积木这句话的真正起点。你定义一个函数它给你一个值这个值立刻变成下一个函数的输入——数据处理管线pipeline的雏形就这么出来了。我建议你重读这一课的时候别急着往下跑先把下面这几个问题问自己函数里不写return会怎样嵌套调用是从里往外算还是从外往里算一个函数里可不可以有多个return这些问题都答得上来才算真正吃透了第21课。1.3 适合谁来读读完能带走什么这篇文章主要写给三类人。第一类是《笨办法学python》读到练习21但脑子一团浆糊的自学者第二类是刚看完Python基础语法、正打算用笨办法练习函数定义的入门者第三类是已经工作但想回头把基础补扎实的开发者。你可以把本文当成练习21的伴读笔记先按本文思路敲一遍代码再回到原书做后面的加分题。另外提醒一句如果你还没装好Python环境记得先去python官网下载对应系统的最新稳定版装的时候勾选 Add Python to PATH编辑器用 VS Code 装个 Python 插件就够。环境配置这块不是本文重点但也是很多新手卡住的地方顺手解决掉再回来。2. 先把函数返回值这个脑筋急转弯掰开2.1 打印和返回一字之差差很远我先用一个最直白的例子说明print和return的本质区别。假设你去快递站取包裹柜台上有个电话机可以拨给快递员说一声我到了这叫打印包裹真正递到你手里这叫返回。前者只是通知后者是给你一个能继续使用的东西。def add_print(a, b): print(a b) def add_return(a, b): return a b result1 add_print(1, 2) # 屏幕上出现 3 result2 add_return(1, 2) # 屏幕上什么都没出现 print(result1) # None print(result2) # 3你看add_print明明在屏幕上打印了 3但变量result1拿到的是None因为函数没有返回任何值。而add_return没有打印任何东西但变量result2拿到的是 3这个 3 还可以做后续运算比如result2 100。这就是有返回值和没返回值最核心的区别返回值是把结果交给你打印只是给你看一眼。在《笨办法学python》第21课里所有函数都用return而不是print就是为了一口一口喂你理解这个差异。你现在觉得简单但很多人写自定义函数的时候写着写着就图省事把return换成了print等到要拿函数结果去算别的数据时就会得到一个None这时候排查半天才发现问题出在函数内部。2.2 返回值不是结果而是可继续加工的半成品再往深走一步。return返回的东西不一定是一个最终答案它更像个半成品方便你在代码旅程的下一站继续折腾它。教科书里常说函数是一等公民听着玄乎其实意思就是函数调用本身可以像一个数值一样参与表达式。举个例子你写一个函数square(x)返回x的平方。这个函数本身可以嵌套def square(x): return x * x print(square(square(3))) # 先算 square(3) - 9再算 square(9) - 81先算最里面的括号得到 9然后把 9 作为参数传给外层square得到 81。这就是嵌套函数调用的执行顺序跟数学里的复合函数一模一样。练习21最后那个拼图表达式正是这种嵌套的连环套what add(age, subtract(height, multiply(weight, divide(iq, 2))))。你可以把它想象成流水线作业一个工人处理完零件后把它传递到下一个工位。每个工位函数只负责自己的加工步骤最终拼出一个成品。理解这一点你再看那些复杂的数据处理代码就会发现它们不过是用一个又一个函数把数据滚雪球。3. 实操跟着练习21把代码敲一遍3.1 动笔前的小准备先别急着写代码。打开你的编辑器新建一个文件命名成ex21.py然后把键盘切换到英文输入法——中文标点在Python里经常引发莫名其妙的报错尤其是引号和括号。我当年就吃过这个亏写了个中文逗号编译器直接甩给我一个语法错误我还傻乎乎地找了半天。另外建议你先在脑中过一遍这几个概念def是函数定义的开始a、b是参数名可以随便起但要语义清晰return一旦执行函数就立刻结束后面即使还有代码也不会跑了。有了这几个基础点后面拆解原练习代码就不费劲。3.2 原练习代码逐行拆解下面这段代码是我按照《笨办法学python》练习21的结构整理的跟原书略有出入把格式化字符串换成了更现代的 f-string但逻辑和参数完全对应def add(a, b): print(fADDING {a} {b}) return a b def subtract(a, b): print(fSUBTRACTING {a} - {b}) return a - b def multiply(a, b): print(fMULTIPLYING {a} * {b}) return a * b def divide(a, b): print(fDIVIDING {a} / {b}) return a / b print(Lets do some math with just functions!) age add(30, 5) height subtract(78, 4) weight multiply(90, 2) iq divide(100, 2) print(fAge: {age}, Height: {height}, Weight: {weight}, IQ: {iq}) print(Here is a puzzle.) what add(age, subtract(height, multiply(weight, divide(iq, 2)))) print(That becomes: , what, Can you do it by hand?)运行之后屏幕上会先出现四行说明文字分别是ADDING 30 5、SUBTRACTING 78 - 4这些。注意这四行是函数内部的print打印出来的而不是return返回的内容。它们只是提示你这个函数开始干活了。真正被保存下来的是return后面的运算结果所以age、height、weight、iq这四个变量分别被赋值成了 35、74、180、50。接下来是最精彩的一行what add(age, subtract(height, multiply(weight, divide(iq, 2))))这行乍看像天书但其实遵循一条铁律从里往外算算完一层结果变成外层的新参数。第一步算最里面的divide(iq, 2)。iq是 50除以 2 得 25。于是这个子表达式变成了 25 这个值。第二步看multiply(weight, 25)。weight是 180180 乘以 25 得 4500。第三步看subtract(height, 4500)。height是 7474 减去 4500 得 -4426。第四步看add(age, -4426)。age是 3535 加上 -4426 得 -4391。所以最终what等于 -4391。你可以打开Python交互环境手算一遍验证35 (74 - (180 * (50 / 2)))结果就是 -4391。这一步手算验证非常重要千万不要偷懒跳过。很多初学者看完书上的代码觉得懂了但真要他手算这个嵌套表达式立刻两眼一抹黑。3.3 从加法机到计算器扩展练习原书在这一课后还留了几个加分题比如自己设计一个公式用这四个函数把它表示出来。我强烈建议你动手做一做哪怕照葫芦画瓢也好。这里给你一个我当年自己练过的例子假设你想表达10 20 * 3 - 40 / 5那么可以写成result subtract(add(10, multiply(20, 3)), divide(40, 5))我们来拆一下先算multiply(20, 3)得 60再算add(10, 60)得 70再算divide(40, 5)得 8最后算subtract(70, 8)得 62。用计算器验证10 60 - 8 62完全一致。再进阶一点函数不一定只处理数字。你可以让它拼接字符串、组合列表。比如def join_with_dash(a, b): return f{a}-{b} def repeat_twice(s): return s s print(repeat_twice(join_with_dash(hello, world)))输出结果是hello-worldhello-world。这个例子看起来没用但它告诉你一个重要的点返回值可以是任意类型数字、字符串、列表、字典都可以。你掌握了这一点后面写爬虫、写数据分析脚本时会非常受益。3.4 用打字来形成肌肉记忆《笨办法学python》最强调的其实是打字这件事。Zed 在书里反复说不要复制、不要粘贴一定要自己把代码一个字一个字敲进去。为什么因为敲代码的过程中你会自然留意到括号的配对、逗号的位置、缩进的层级这些是语法错误的重灾区。只看不敲手会很生敲得多了就算一时不理解原理手指也会先一步帮你把结构写对。我见过很多读者用抄代码的方式来读这本书抄的时候脑子放空抄完啥也没记住。正确的做法是每抄完一个小节就停下来盖住代码尝试自己默写一遍核心结构。默写错了没关系对照原文找差异这个找差异的过程才是真正锻炼代码直觉的过程。练习21的四个函数结构高度相似非常适合做这种默写训练——你把add写顺了剩下三个就是改改运算符和打印文本的事。4. 最容易翻车的几个坑我替你踩过了4.1 函数没有 return结果全是 None这是新手第一个大坑。很多人在自定义函数里辛辛苦苦算出结果却没写return或者直接用了print导致外面拿到的是None。我举个实际场景你想写一个函数输入一个价格返回加上了 10% 税后的金额。错误写法是def add_tax(price): new_price price * 1.1 # 忘了写 return new_price这样调用add_tax(100)得到的不是 110而是None。调试这种问题最直接的办法是在调用处打印返回值或者用type(result)看一眼是不是NoneType。我自己的排查习惯是如果一个变量明明应该在函数里被赋值了外面却显示None那九成是函数缺少return。4.2 return 后面的代码不会再执行Python 里return的另一个特性是一旦执行函数立刻结束当前函数体内剩余的所有代码都会被跳过。所以你在写函数时千万别在return后面再写清理工作或额外打印那部分代码永远不会跑。举个例子def test(x): return x * 2 print(这行永远不会输出)这行print成了死代码。有些代码检查工具会直接给你标黄提示 unreachable code不可达代码。如果你确实需要先打印再返回那就把print放到return前面。4.3 参数到底能不能被修改练习21里的参数都是数字数字属于不可变类型所以在函数内部做加减乘除并不会影响外部变量。这个结论在数字、字符串、元组上都成立。但如果你传入的是一个列表或字典情况就完全不同了——它们可以原地修改外面的原数据也会跟着变。def add_item(lst, item): lst.append(item) my_list [1, 2, 3] add_item(my_list, 4) print(my_list) # [1, 2, 3, 4]这个行为在《笨办法学python》前期还没怎么涉及但既然大家搜到了这个标题我就提前提一句如果你不希望函数修改外部列表可以在函数内部复制一份比如lst lst[:]或者lst.copy()。这个坑等你以后写项目时会频繁遇到早意识到早受益。4.4 作用域函数内部变量外面看不见还有一个很常见的困惑我在函数里定义了一个变量temp为啥出了函数就找不到了答案很简单——函数内部定义的变量属于局部变量作用域只在函数体内。你在外面访问它Python会直接报NameError。反过来函数内部想读取外部定义的全局变量虽然可以但我强烈建议你别在函数里直接改全局变量。global关键字确实能干这件事但滥用global会让代码的调试成本急剧上升因为你根本不知道变量是在哪里被改掉的。练习21阶段你只要记住一条原则函数的输入靠参数输出靠返回值需要什么数据就让调用者传进来想拿什么结果就让函数返出去不要偷偷摸摸地碰外部变量。我给读者整理过一个新手翻车速查表列在这儿方便你以后排查现象可能原因解决方法函数调用结果是 None函数缺 return或 return 拼写错误检查函数末尾是否有 return 语句屏幕有输出但变量是 None函数里用的是 print 而不是 return把 print 改成 return函数后面的代码不执行前面已经有 return把代码移到 return 前面或删除 return函数改不了外部变量重新赋值了不可变类型参数把新值作为返回值重新赋值给外部变量外面访问函数内变量报错局部作用域限制把变量作为返回值返回给外部这个表里的前四行几乎覆盖了初学者函数出错的大部分场景。5. 把笨办法用到真实的 Python 场景里5.1 用返回值写一个会干活的小项目光会算数还不够我建议你练完练习21以后马上写一个小项目巩固一下。目标是读取一个文本文件统计里面最长的单词并且把这个单词打印出来。第一步定义一个读取文件内容的函数它返回一个字符串。第二步定义一个把字符串拆成单词列表的函数。第三步定义一个找出最长单词的函数。每步一个函数用返回值串起来def load_text(path): with open(path, encodingutf-8) as f: return f.read() def split_words(text): # 把标点符号粗略替换成空格再按空白拆分 for ch in .,!?;:\n: text text.replace(ch, ) return text.split() def find_longest(words): if not words: return None longest words[0] for w in words[1:]: if len(w) len(longest): longest w return longest text load_text(poem.txt) words split_words(text) result find_longest(words) print(fThe longest word is: {result})你看这三个函数的共同特点就是输入一些数据处理一下把结果return出去。没有returntext就无法传到下一个函数没有returnwords就无法传给find_longest。这个项目虽然小但它已经把数据流的概念完整跑通了一遍。把这个流程跑顺你以后写爬虫解析HTML、写数据分析读CSV、处理字段时脑子里就会有一个清晰的函数拆分思路。5.2 继续往前走第21课之后的节奏《笨办法学python》从练习21之后开始进入新的领域比如对象、文件读写、排序等。你会发现几乎所有后续内容都建立在函数能返回值这个基础上。比如后面写猜数字游戏你需要一个返回随机数的函数还要一个判断玩家猜测的函数写Web服务器时你更需要通过函数返回值来构造HTTP响应。所以千万别急着跳着往后读。宁可把练习21反复做透后面的学习才会更顺。有不少人买这本书回来按部就班读到十几课就放弃了因为嫌前面太简单。但恰恰是那些简单的重复帮你把变量、函数、返回值这些基本概念焊死在脑子里。等到读后面难的章节你才不会一边看一边翻前面的基础。5.3 我的一个小建议给函数起个好名字最后聊一个可能没人强调、但真实影响开发效率的细节函数命名。练习21里大家为了省事会写add、sub、calc这种名字。在练习里无所谓但一旦你开始写真实项目函数名就是给未来自己看的文档。我以前写过一个数据处理脚本里面全是func1、func2、do_stuff这种鬼名字过了一周再看完全不记得哪个函数是干嘛的。后来我强迫自己遵守动词名词的命名规则比如calculate_total_price、filter_valid_records、merge_user_data。虽然打字多了一点但代码可读性提升了不止一个档次。这一课的原书函数名其实已经起得不错了但你完全可以试着把add改成add_numbers把divide改成divide_numbers体会一下语义清晰带来的好处。我在实际学习这本书的时候最大的体会是函数返回值这个概念很像学骑自行车——看别人骑觉得没什么轮到自己一上手就歪歪扭扭。我当时为了搞懂嵌套调用真的把练习21那段拼图表达式手算了十几遍又在纸上画了好几张调用顺序图直到某天突然通透了原来函数调用就是一个值哪里需要值它就可以出现在哪里。这个念头一旦通了后面学面向对象、学装饰器都觉得顺理成章了许多。这里还有一个小技巧分享给你如果你写出来的函数返回值总是不符合预期别急着查语法先在函数开头print一下参数看看进来的是什么再在返回前print一下结果看看出去的是什么。这种入口出口各插一个桩的办法比任何调试工具都直接。等你熟练了再慢慢把这些调试用的print删掉换成更专业的调试器也不迟。练习21虽然只是小小一课但它值得你花一个星期去消化。别怕慢笨办法之所以叫笨办法就是因为它不投机取巧但每一步都稳稳当当。把这一课踩实了后面的Python学习之路会越走越轻松。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询