资讯动态

Python入门篇之函数

发布时间:2026/10/16 12:50:06 来源:尧图企业网站定制
前言刚开始学 Python最容易被两个问题卡住一是「为什么要把代码写成函数」二是「函数里的变量到底归谁管」。前者关系到代码能不能复用和维护后者关系到你会不会在某个深夜突然收到NameError或UnboundLocalError。这篇入门篇不追求面面俱到只把函数最基本的三件事讲透怎么定义、怎么传参、怎么拿返回值。常见的误解有三类。第一类是把函数当成「压缩代码行数的工具」觉得几行代码直接写就行何必包成函数——其实函数的价值在复用和命名不在省行数。第二类是以为「函数里能随便改外面的变量」结果一赋值就报错。第三类是带着 Python 2 的习惯写print x在 Python 3 里直接语法报错。顺便把版本讲清楚Python 2.7 已于 2020 年 1 月 1 日停止维护。Python 2 里print是语句可以写print helloPython 3 里print是函数必须写print(hello)。同理 Python 2 的raw_input在 3 里改叫inputdict.iteritems()在 3 里已移除要用dict.items()。本文一律用 Python 3 的写法。一、函数是什么给一段代码起名字把完成某件事的代码写成一个函数就是给这段逻辑起了个名字以后用名字调用它即可# 适用于 Python 3.8def say_hello():print(你好欢迎学习 Python 函数)say_hello()say_hello()这里的def是 define 的缩写。say_hello是函数名()是参数表这里为空冒号后面缩进的部分是函数体。调用时写函数名加圆括号。函数带来的直接好处是逻辑只写一次想用几次就调用几次以后要改行为只改函数体一处。这比到处复制粘贴可靠得多。二、让函数接收数据参数没有参数的函数只能做固定的事。要让函数处理不同的数据就在参数表里声明参数parameter调用时把数据实参argument传进去# 适用于 Python 3.8def greet(name):print(f你好{name})greet(小明) # 你好小明greet(小红) # 你好小红函数可以接收多个参数按位置一一对应# 适用于 Python 3.8def introduce(name, age):print(f{name} 今年 {age} 岁)introduce(小明, 18) # 小明 今年 18 岁如果参数有合理的缺省情况可以给默认值。默认值让调用方可以少传# 适用于 Python 3.8def greet(name, greeting你好):print(f{greeting}{name})greet(小明) # 你好小明greet(小明, 早上好) # 早上好小明greet(小明, greeting嗨) # 嗨小明调用时既可以按位置传也可以写成名字值的形式关键字参数。但关键字参数必须写在位置参数后面。一个必须记住的点默认值只在函数定义时求值一次。如果默认值是可变的比如列表或字典就会出现「上一次调用的残留」。正确做法是用None当哨兵# 适用于 Python 3.8def add_item(item, bucketNone):if bucket is None:bucket []bucket.append(item)return bucketprint(add_item(a)) # [a]print(add_item(b)) # [b]而不是 [a, b]三、拿回结果return 与 None函数做完事可以用return把结果交回给调用方# 适用于 Python 3.8def add(a, b):return a btotal add(3, 5)print(total) # 8return会立即结束函数后面的代码不再执行# 适用于 Python 3.8def check(n):if n 0:return 负数return 非负数print(check(-1)) # 负数print(check(5)) # 非负数如果函数没有return或者写了光秃秃的return它返回的是None。这是新手最容易忽略的地方# 适用于 Python 3.8def show(msg):print(msg)value show(一条消息) # 打印一条消息print(value) # None所以像lst.sort()这种原地排序的方法返回的是None千万不要写result lst.sort()。想让「排序后得到新列表」用内置函数sorted()# 适用于 Python 3.8data [3, 1, 2]new sorted(data)print(new) # [1, 2, 3]print(data) # [3, 1, 2]原列表没变return想一次给出多个结果时把它们用逗号隔开实际上会打包成元组接收方可以用多个变量接# 适用于 Python 3.8def divmod_like(a, b):return a // b, a % bq, r divmod_like(7, 3)print(q, r) # 2 1顺便说标准库的内置函数divmod(a, b)做的就是这件事返回(a // b, a % b)。四、作用域函数里的名字归谁管函数体是一个新的作用域。函数内部可以读外层的变量但一旦在里面给某个名字赋值这个同名变量就会被当成函数的局部变量# 适用于 Python 3.8name 全局def show():print(name) # 读取外层变量没问题show() # 全局# 适用于 Python 3.8count 0def bump():count count 1 # 这里 count 被当作局部变量自引用时报错# bump() # UnboundLocalError: local variable count referenced before assignment要在函数里修改全局变量必须用global声明要修改外层函数的变量用nonlocal# 适用于 Python 3.8count 0def bump():global countcount 1bump()bump()print(count) # 2新手记住一句话就够了函数里看到赋值默认就当局部变量。想动外面的先声明。实战一个完整可运行的小程序下面把定义、参数、默认值、返回值、作用域揉进一个小例子可以直接复制进hello_functions.py运行。# 适用于 Python 3.8def bmi(weight, height, /):根据体重千克和身高米计算 BMI 指数。if height 0:return Nonereturn weight / (height ** 2)def grade(value, *, thresholds(18.5, 24.0, 28.0)):把 BMI 数值映射为中文档位只接受关键字参数。if value is None:return 输入无效low, mid, high thresholdsif value low:return 偏瘦if value mid:return 正常if value high:return 偏胖return 肥胖def report(weight, height):value bmi(weight, height)if value is None:print(身高必须大于 0)returnprint(fBMI {value:.1f}档位{grade(value)})if __name__ __main__:report(70, 1.75)report(50, 1.60)report(70, 0)逐段说明def bmi(weight, height, /)里的/表示这两个参数是仅位置参数Python 3.8 起支持只能按位置传不能写bmi(weight70, height1.75)。def grade(value, *, thresholds...)里的*表示后面的thresholds是仅关键字参数调用时只能写thresholds...。两个函数都有明确的返回bmi在非法输入时返回Nonegrade对None单独处理。report用f...格式化{value:.1f}表示保留一位小数。常见坑点忘了调用只写了函数名❌def work(): ...之后写work—— 只是引用了函数对象什么都不会执行。 ✅ 写work()带上圆括号才是调用。可变默认参数❌def add(item, bucket[]): bucket.append(item); return bucket—— 默认列表被所有调用共享。 ✅def add(item, bucketNone): bucket [] if bucket is None else bucket; ...把None当有效返回值用❌if find_user(uid) 0:—— 找不到时函数返回None和数字比较会TypeError。 ✅ 先判断result find_user(uid)再写if result is None: ...。误以为sort()返回新列表❌result data.sort()——result是Nonedata已被原地排序。 ✅ 要新列表用result sorted(data)要原地改就用data.sort()且不接收返回值。函数内赋值忘了global/nonlocal❌ 直接count 1想改全局count结果UnboundLocalError。 ✅ 先global count外层函数则用nonlocal count再count 1。关键字参数写在位置参数前面❌greet(name小明, 早上好)—— 位置参数跟在关键字参数后SyntaxError。 ✅greet(小明, 早上好)或greet(小明, greeting早上好)。拿 Python 2 的语法写 Python 3❌print 你好、raw_input()、d.iteritems()—— 前者是 Python 2 语句后两个在 Python 3 里已改名或移除。 ✅print(你好)、input()、d.items()。总结概念一句话要点定义def 名字(参数):加缩进函数体调用函数名加圆括号别漏括号参数位置参数、关键字参数、默认值默认值定义时求值一次可变默认值换成None哨兵调用内新建返回值无return返回None多值返回是元组作用域函数内赋值默认为局部改外层要global/nonlocal入门阶段把这几条理顺写函数基本不会出大问题先把「参数怎么进、返回值怎么出」想清楚再记住「默认值只算一次」和「内部赋值即局部」这两条作用域规律。剩下的等对函数更熟了再去接触*args、**kwargs、闭包和装饰器这些进阶玩法。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑