一、为什么需要函数
先看一段大家都会写的代码:想跟三个同学打招呼,最直接的办法是抄三遍:
print('你好,小明')
print('你好,小红')
print('你好,小刚')
能跑。但如果要跟全班 40 个同学打招呼,抄 40 遍就太傻了。
真正麻烦的是:如果打招呼的话术要改(比如改成「你好,小明同学,欢迎来上课」),你得回去改 40 处,漏一处就出错。同一段逻辑出现第三遍,就该把它收起来——这就是函数。
把「打招呼」做成一个函数,以后想跟谁打招呼,只要报一下名字就完事:
def greet(name):
print('你好,' + name)
greet('小明')
greet('小红')
greet('小刚')
输出:
你好,小明
你好,小红
你好,小刚
话术只写在一处,想改改一处。这就是函数最大的好处:一次写好,到处复用。
函数能帮我们做什么
| 场景 | 没有函数 | 有函数 |
|---|---|---|
| 打招呼 | 抄 N 遍 print | 写一次 greet,调用 N 次 |
| 算平均分 | 每换一份成绩单重写一遍累加 | 写一次 average,传不同列表 |
| 判奇偶 | 每处都写 if n%2==0 | 写一次 is_even,到处用 |
下面三件事,就是函数的全部:怎么定义、怎么调用、怎么把外面的值传进去、把里面的值拿回来。
课程思政|工匠精神与严谨求实 · 写第三遍,就该收起来
同一段「打招呼」的话,你抄了三遍,要改的时候就得回去改三处,漏一处就出错。函数的价值就在这儿:把重复的逻辑收成一个按钮,改只改一处。这不只是省事,是怕自己出错。以后无论是算平均分还是写报表,看到自己开始复制粘贴,就该警觉——那是代码在提醒你,该动手收拾一下了。
二、定义与调用
函数长这样,记住四个零件:
# 示意:把「函数名」「参数」「要做的事」换成真实的
def 函数名(参数):
要做的事(记得缩进)
可以写很多行
最后用 return 把结果交出来(也可以不交)
这是长相,不是能直接跑的代码——函数名、参数 还没定义呢。看一个真能跑的:
def greet(name):
print('你好,' + name)
greet('小明')
输出 你好,小明。
零件 1:def 关键字
def 是英文 define(定义)的缩写,告诉 Python「我要定义一个函数了」。少了它就不是函数。
零件 2:函数名
起名规则和变量一样:字母、数字、下划线,不能以数字开头,不能用关键字(def、if 等)。建议见名知意:greet、area、is_even。
def 1func(): # 报错:数字不能开头
print('hi')
SyntaxError: invalid decimal literal
零件 3:括号和冒号
函数名后面必须跟 ( 和 ),哪怕没有参数也要写空括号 ();这一行结尾必须有英文冒号 :。
def greet(name) # 报错:漏了冒号
print(name)
SyntaxError: expected ':'
零件 4:缩进的函数体
冒号下面、缩进四格的那几行,才是函数真正要做的事。缩进错了,Python 不知道哪些代码属于函数。
必须先定义,后调用
函数要先 def 定义好,才能 greet(...) 调用。调用写在定义前面会找不到它:
print(greet('小明')) # 报错:greet 还没定义
def greet(name):
return '你好,' + name
NameError: name 'greet' is not defined
调用时别忘了括号
很多人写 greet 想让它运行,却忘了加 ()。不加括号,Python 只把「函数本身」给你,不会真的执行:
def greet(name):
return '你好,' + name
print(greet) # 少了括号:打印的是函数对象,不是结果
print(greet('小明'))
输出:
<function greet at 0x...>
你好,小明
第一行那串 0x... 是函数在内存里的地址,说明你拿到的是「函数这个东西」,而不是它的运行结果。想运行,一定加上 ()。
三、参数:位置、默认、关键字
函数名后面括号里的 name 叫参数(也叫形参)。调用时传进去的 '小明' 叫实参。参数让函数能处理不同的情况。
位置参数:按先后对号入座
调用时给的值,按顺序一一对应括号里的参数:
def calc(a, b, op):
if op == '+':
return a + b
if op == '-':
return a - b
print(calc(6, 3, '+'))
print(calc(6, 3, '-'))
输出 9、3。
def add(a, b):
return a + b
print(add(1)) # 少传一个
TypeError: add() missing 1 required positional argument: 'b'
def add(a, b):
return a + b
print(add(1, 2, 3)) # 多传一个
TypeError: add() takes 2 positional arguments but 3 were given
默认值参数:可传可不传
在定义时给参数写上 = 默认值,调用时就可以不传,自动用默认值:
def greet(name='同学'):
return '你好,' + name
print(greet())
print(greet('小明'))
输出:
你好,同学
你好,小明
规则:有默认值的参数必须排在「没有默认值」的参数后面。下面这样写会报错:
def greet(name='同学', age): # 报错:默认值参数不能在前面
return name
SyntaxError: parameter without a default follows parameter with a default
关键字参数:指名道姓地传
调用时写成 参数名=值,就不必按位置排,还能让代码更好懂:
def greet(name, age):
return name + '今年' + str(age) + '岁'
print(greet(age=18, name='小明'))
输出 小明今年18岁。注意关键字调用时顺序可以打乱,但名字必须和定义里的参数名一致:
def greet(name, age):
return name
print(greet(n='小明', age=18)) # 报错:没有叫 n 的参数
TypeError: greet() got an unexpected keyword argument 'n'
四、返回值 return
return 的意思是「把结果交出去」。没有它,函数干完活也什么都没带回来。
没有 return,得到的是 None
def f():
x = 1
def g():
return 1 + 2
print(f())
print(g())
输出:
None
3
None 表示「什么都没有」。函数里只算了 x=1 却没 return,调用结果就是 None。
return 之后,后面的代码不执行
函数一旦碰到 return 就立刻收工,后面写什么都不会跑:
def f():
return 1
print('这行永远不会执行')
print(f())
输出只有 1,那句 print 根本没机会运行。
return 以为会自动显示——不会。return 只是把值交回给调用处,要看到结果还得在调用处 print。返回多个值,其实是返回一个元组
写成 return a, b, c,Python 会把它们打包成一个元组交回来:
def fx():
return 1, 2, 3
print(fx())
print(type(fx()))
输出:
(1, 2, 3)
<class 'tuple'>
所以「返回多个值」不是特殊语法,就是返回了一个元组。你也可以用多个变量一次接住:
a, b, c = fx()
print(a, b, c)
输出 1 2 3。
return 是「把结果交给别人用」,print 是「在屏幕上显示给人看」。如果后面还要拿这个结果继续算,一定要用 return,别用 print。课程思政|诚信与职业操守 · 交出去,才算做完
函数算了半天,没有 return,外面拿到的还是 None——活儿干了,成果却没交出去。这很像做事:自己心里「做完了」不算数,把手里的结果实实在在交到该接的人手上,一件事才算闭环。团队里最怕的就是「我以为他做了」,所以该交的值、该报的数,别留在自己这儿,明确地交出去。
五、print 和 return 的区别
这是新手最容易混的一对。一句话记住:print 是给人看的,return 是给程序用的。
print(x) | return x | |
|---|---|---|
| 作用 | 把 x 显示在屏幕上 | 把 x 交回调用处,存进变量 |
| 之后还能算吗 | 不能,只是显示了 | 能,y = f() 拿到 x 继续算 |
| 不接住会怎样 | 屏幕上多一行字 | 得到 None |
看这个对比,差别一目了然:
def f():
print('hi')
x = f()
print('x =', x)
输出:
hi
x = None
f() 只打印了 hi,但没有 return,所以 x 拿到的是 None。
def g():
return 'hi'
y = g()
print('y =', y)
输出 y = hi。g() 把 'hi' 交回来,y 才真正拿到了它。
一个常见的错误
想算平均分却用 print,结果拿不到数:
def average(scores):
print(sum(scores) / len(scores)) # 只打印,没 return
a = average([88, 92, 75])
print('及格线以上:', a + 10) # 报错:None 不能加 10
TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'
average 没 return,a 是 None,None + 10 直接报错。把 print(...) 改成 return ... 就正常了。
六、变量作用域
函数里面定义的变量,外面一般看不到。这叫作用域。
局部变量:函数里的「私人物品」
def fx():
x = 10 # x 只在 fx 里面有效
print(x)
fx()
print(x) # 报错:外面的世界没有 x
NameError: name 'x' is not defined. Did you mean: 'fx'?
全局变量:函数外面定义的
函数外面定义的变量,函数可以读,但不能直接改:
count = 0
def inc():
count = count + 1 # 报错:想改全局,却没说 global
inc()
UnboundLocalError: cannot access local variable 'count' where it is not associated with a value
Python 看到函数里给 count 赋值,就以为你要建一个局部的 count,结果右边的 count + 1 找不到值,报错。
想改全局,要写 global
count = 0
def inc():
global count # 声明:我要用的是外面的那个 count
count = count + 1
inc()
print(count)
输出 1。加上 global count,函数里改的就是外面的全局变量了。
global;函数内的只在函数内有效。最省心的写法永远是「传进去、return 出来」。AI 助手小贴士|作用域规则里藏着一个经典对比,让 AI 摆出来。
打开任意 AI 对话工具(网页版或 App 都可以),试试这样问:为什么函数里改外面的列表不用 global 声明、重新赋值一个 int 却要?给两个对照的小例子讲清楚
课程思政|数据安全与法治素养 · 各管各的边界
函数里的变量是「私人物品」,外面看不见;外面的变量函数能读、却默认改不了,要改还得专门写 global。这套规矩不是多余的,它划的就是边界。谁能看见、谁能改动,事先说清楚,系统才不乱。做数据的人对这条尤其要敏感:不同岗位、不同权限能碰到的东西本就该不一样,越界读写一次,信任就少一分。
七、函数的嵌套:函数里再定义函数
函数的定义可以写在另一个函数里面,这叫嵌套函数。
def outer():
def inner():
print('我是内层函数')
inner() # 在外层里调用它
outer()
关键点:内层函数只在外层函数「被执行」的时候才被定义,出了外层就找不到了。
def outer():
def inner():
print('你好')
outer()
inner() # 在外层外面调用 → 找不到
运行后会报错(逐字照抄解释器):
NameError: name 'inner' is not defined. Did you mean: 'iter'?
内层函数能看到外层的变量
def outer():
msg = '你好'
def inner():
print(msg) # 直接用了外层的变量
inner()
outer()
输出:
你好
不用写任何关键字,内层函数就能读到外层的变量。但要在内层修改它,就需要 nonlocal 了——这正是下一节要讲的。
嵌套有什么用:把「只有自己用得到」的辅助逻辑藏起来
def average(scores):
def clean(nums): # 只给 average 用的小工具
return [n for n in nums if n >= 0]
data = clean(scores)
return round(sum(data) / len(data), 1)
print(average([90, -1, 80, 100]))
输出:
90.0
clean 这个名字只存在于 average 内部,不会跑到外面去占用名字——这正是嵌套的第一个好处:辅助函数不外泄。
| 普通的全局函数 | 嵌套函数 | |
|---|---|---|
| 定义在哪 | 最外层 | 另一个函数内部 |
| 谁能调用 | 任何地方 | 只有外层函数内部 |
| 能不能看到外层变量 | 看不到 | 能看到(读没问题) |
| 典型用途 | 给很多地方复用 | 只服务外层那一小段逻辑 |
八、闭包:函数「记住」了外面的变量
如果外层函数不直接调用内层函数,而是把它当成结果返回出去,奇妙的事情就发生了:内层函数会记住外层函数的变量,哪怕外层函数早就执行完了。
def make_adder(n):
def add(x):
return x + n # 用到了外层的 n
return add # 把内层函数返回出去
add5 = make_adder(5)
add10 = make_adder(10)
print(add5(1))
print(add10(1))
print(add5(100))
输出:
6
11
105
make_adder(5) 返回的 add5 一直记着 n = 5;add10 记着 n = 10。这两个函数各自带着自己那份数据,互不干扰。
这种「内层函数 + 它记住的外层变量」的组合,就叫闭包(closure)。
经典用途:不开全局变量也能存状态
就像奶茶店的集点卡:每张卡各记各的杯数,互不串账——每个闭包也各存各的 count。
def make_counter():
count = 0
def step():
nonlocal count # 我要改的是外层的 count
count += 1
return count
return step
c = make_counter()
print(c())
print(c())
print(c())
输出:
1
2
3
nonlocal count 的意思是:「我要改的是外层函数里的那个 count,不要在函数里新建一个」。只读可以不写,要改就必须写——忘写就会悄悄新建一个局部变量,然后报错:
def make_counter():
count = 0
def step():
count = count + 1 # 忘了 nonlocal
return count
return step
c = make_counter()
print(c())
运行后会报错(逐字照抄解释器):
UnboundLocalError: cannot access local variable 'count' where it is not associated with a value
三个作用域关键字,一次分清
| 写法 | 作用 | 用在哪 |
|---|---|---|
| 什么都不写 | 只读外层变量没问题;一旦赋值就新建局部变量 | 绝大多数情况 |
global x | 声明「我要用并修改全局的那个 x」 | 改全局变量时 |
nonlocal x | 声明「我要用并修改外层函数的那个 x」 | 闭包里改外层变量时 |
每个闭包各存各的
def make_counter():
count = 0
def step():
nonlocal count
count += 1
return count
return step
c1 = make_counter()
c2 = make_counter()
c1()
c1()
print('c1:', c1())
print('c2:', c2())
输出:
c1: 3
c2: 1
funcs = []
for i in range(3):
def f():
return i
funcs.append(f)
print([f() for f in funcs]) # 全是 2,不是 0 1 2
输出:
[2, 2, 2]
九、参数进阶 *args/**kwargs
有时你不知道要收几个参数,比如「把所有分数加起来」。这时候用 *args 和 **kwargs。
*args:收下任意多个位置参数
前面加一个星号,所有位置参数会被装进一个元组:
def f(*args):
print(args)
f(1, 2, 3)
f(1)
输出:
(1, 2, 3)
(1,)
**kwargs:收下任意多个关键字参数
前面加两个星号,所有 名字=值 会被装进一个字典:
def f(**kwargs):
print(kwargs)
f(a=1, b=2)
输出 {'a': 1, 'b': 2}。
参数顺序口诀
一个函数里几种参数同时出现,顺序固定为:普通参数 → 默认值参数 → *args → **kwargs。
def f(a, b=0, *args, **kwargs):
print(a, b, args, kwargs)
f(1, 2, 3, 4, c=5)
输出 1 2 (3, 4) {'c': 5}。1 给 a,2 给 b(默认值被覆盖),3,4 进 args,c=5 进 kwargs。
SyntaxError。记不住就背这句口诀:普通 → 默认 → *args → **kwargs,从左到右越来越「宽」。起步阶段用得少,先认识长相即可。*args / **kwargs 常用于「写工具函数」或「不确定收多少参数」的场景。日常自己写函数,先老老实实用普通参数,需要了再用它们。十、文档字符串
函数写出来是给别人(包括以后忘了的自己)用的。在 def 下面用三引号 ''' 写一段说明,就是文档字符串(docstring)。
def area(r):
'''计算半径为 r 的圆的面积'''
return 3.14 * r * r
print(area.__doc__)
输出 计算半径为 r 的圆的面积。
别人想看你怎么用,可以调 help():
help(area)
输出:
Help on function area in module __main__:
area(r)
计算半径为 r 的圆的面积
help() 显示的,正是你写的文档字符串。所以写函数时顺手写一句它是干啥的,非常值。
课程思政|科技自立自强 · 让别人也用得起来
函数写出来是给别人用的,顺手用三引号补一句说明,别人调 help() 一下就明白怎么用。别小看这句话——能把工具写清楚、交得出去,才算真正掌握了它。我们用的很多基础库都来自国外,它们能流行,靠的不只是功能强,还有规范的文档。把命名、注释、说明当成习惯,将来你写的函数,才可能被更多人放心地拿去用。
十一、十个基础案例
下面十个例子都很短,建议每个都亲手敲一遍、跑一遍。它们覆盖函数最常见的用法。
1. 奶茶店点单
def order(drink, size='中杯'):
return size + drink + ',请慢用'
print(order('珍珠奶茶'))
print(order('美式', '大杯'))
输出:
中杯珍珠奶茶,请慢用
大杯美式,请慢用
2. 快递运费计算
def shipping(weight):
return 8 + weight * 2
print(shipping(1))
print(shipping(3))
输出:
10
14
3. 外卖满减判断
def can_free(total):
if total >= 20:
return True
return False
print(can_free(25))
print(can_free(12))
输出:
True
False
4. 演唱会验票
def check_ticket(age, has_ticket):
if age >= 18 and has_ticket:
return '验票通过,可以入场'
return '验票不通过,不能入场'
print(check_ticket(20, True))
print(check_ticket(20, False))
输出:
验票通过,可以入场
验票不通过,不能入场
5. 算一份成绩的平均分
def average(scores):
return sum(scores) / len(scores)
print(average([88, 92, 75, 96]))
输出 87.75。
6. 外卖券后价
def pay(price, coupon):
if coupon == '满30减10':
return price - 10
if coupon == '新客减5':
return price - 5
return price
print(pay(32, '满30减10'))
print(pay(18, '新客减5'))
print(pay(18, '无'))
输出:
22
13
18
7. 体测成绩等级
def level(score):
if score >= 90:
return '优秀'
if score >= 80:
return '良好'
if score >= 60:
return '及格'
return '不及格'
print(level(95))
print(level(73))
print(level(45))
输出:
优秀
及格
不及格
8. 校园卡号校验
def check_card(card):
if len(card) == 8 and card.isdigit():
return '卡号有效'
return '卡号无效'
print(check_card('20261309'))
print(check_card('123'))
输出:
卡号有效
卡号无效
9. 宿舍点名
def count_in(replies):
n = 0
for r in replies:
if r == '到':
n += 1
return n
print(count_in(['到', '到', '缺', '到']))
输出 3:4 个床位里有 3 个人答了「到」。
10. 歌词生成器
def make_lyric(singers):
result = []
for s in singers:
result.append(s + '唱一句')
return result
print(make_lyric(['我', '你', '他']))
输出 ['我唱一句', '你唱一句', '他唱一句']:把每个人接一句,拼成一段词。
十二、常见坑
坑 1:忘写 return,结果拿到 None
def add(a, b):
a + b # 算了却没 return
print(add(2, 3)) # 输出 None
输出 None。想拿到和,必须 return a + b。
坑 2:调用时忘加括号
def greet(name):
return '你好,' + name
print(greet) # 少了 (),打印的是函数对象
输出类似 <function greet at 0x...>。记住:想运行函数,括号不能省。
坑 3:参数个数对不上
def add(a, b):
return a + b
print(add(1)) # 少一个,报 TypeError
TypeError: add() missing 1 required positional argument: 'b'
坑 4:默认参数写成可变对象
这是个经典大坑:把默认值设成列表 [],这个列表会在多次调用之间共用,导致数据串味:
def add_item(x, lst=[]):
lst.append(x)
return lst
print(add_item(1))
print(add_item(2))
输出:
[1]
[1, 2]
第二次调用本想从空列表开始,结果却带着上一次的 1。正确做法:默认用 None,在函数里新建:
def add_item(x, lst=None):
if lst is None:
lst = []
lst.append(x)
return lst
print(add_item(1))
print(add_item(2))
输出 [1]、[2],两次互不干扰。
坑 5:函数里改了列表,外面也变了
列表是「引用传递」,函数里改它,外面的原列表跟着变:
def add_score(scores, s):
scores.append(s)
ns = [90]
add_score(ns, 80)
print(ns)
输出 [90, 80]。这不是 bug,但新手常以为函数「动不到外面的东西」。如果不想影响外面,就传一份副本:add_score(ns.copy(), 80)。
AI 助手小贴士|函数设计题要先想签名再动手,让 AI 当教练。
打开任意 AI 对话工具(网页版或 App 都可以),试试这样问:出 3 道函数设计题:温度转换、判断质数、计算购物小票。要求我先写函数签名和文档字符串再写实现,写完你点评
十三、报错手册
下面这些报错都是真实运行出来的,照抄本机解释器原文。看到眼熟的,直接对照处理。
print(greet('小明'))
def greet(name):
return '你好,' + name
NameError: name 'greet' is not defined
原因:调用写在定义前面。Python 从上往下读,读到调用时还没见过 greet。
def add(a, b):
return a + b
print(add(1))
TypeError: add() missing 1 required positional argument: 'b'
原因:位置参数少传了一个。补上第二个值即可。
def add(a, b):
return a + b
print(add(1, 2, 3))
TypeError: add() takes 2 positional arguments but 3 were given
原因:位置参数多传了。要么少传一个,要么把第三个参数改成关键字参数。
def greet(name='同学', age):
return name
SyntaxError: parameter without a default follows parameter with a default
原因:有默认值的参数不能排在没有默认值的参数前面。把 age 放到 name 前面。
def greet(name):
return name
print(greet(n='小明'))
TypeError: greet() got an unexpected keyword argument 'n'
原因:关键字调用的名字必须和定义里的参数名一样。这里没有叫 n 的参数。
def greet(name)
print(name)
SyntaxError: expected ':'
原因:函数定义那一行结尾漏了冒号。
def 1func():
print('hi')
SyntaxError: invalid decimal literal
原因:函数名不能以数字开头。改成 func1 之类。
count = 0
def inc():
count = count + 1
inc()
UnboundLocalError: cannot access local variable 'count' where it is not associated with a value
原因:函数里想改全局变量 count 却没写 global count。
def f():
print('hi')
x = f()
print(x + 10)
TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'
原因:f() 只 print 没 return,x 是 None,None + 10 报类型错。把 print 改成 return。
def greet(name):
return '你好,' + name
print(greet)
<function greet at 0x...>
注意:这不是报错,而是「忘了加括号」。打印出来的是函数对象,要加 () 才运行。
十四、函数也是值:赋值、传参、lambda
到了这里,你其实可以把函数当成和普通数字、字符串一样的东西来用:能存进变量、能当参数传来传去。理解这一点,后面学列表、学数据处理会轻松很多。
函数可以赋给变量
函数名本身就是一个「值」,可以把它赋给另一个名字,用新名字也能调用:
def greet(name):
return '你好,' + name
say_hi = greet # 把函数本身赋给 say_hi
print(say_hi('小明'))
输出 你好,小明。say_hi 和 greet 指向同一个函数。
函数可以当参数传进去
把函数作为另一个函数的参数,让对方在合适的时机调用它。最常见的是 max / min 配 key=:
drinks = ['珍珠奶茶', '柠檬水', '芋泥啵啵奶茶', '美式']
print(max(drinks, key=len))
输出 芋泥啵啵奶茶(名字最长)。key=len 告诉 max「按名字长度比大小」,而不是按字母顺序。
lambda:一句话写个小函数
有些函数只用一次、逻辑很短,可以用 lambda 当场写,省得专门 def:
menu = [('珍珠奶茶', 15), ('柠檬水', 8), ('美式', 12)]
print(sorted(menu, key=lambda x: x[1]))
输出:
[('柠檬水', 8), ('美式', 12), ('珍珠奶茶', 15)]
lambda x: x[1] 的意思是「取每个元组的第 2 项(价格)来比大小」,它等价于临时写一个 def price(x): return x[1] 的小函数,只是写在了一行里。初学阶段不要求会用 lambda,认识长相即可;正规写函数还是推荐 def,更清楚。
def 定义、调用、参数、返回值练熟,lambda 和「函数当参数」以后自然就懂了。一张总览表
| 概念 | 一句话 | 例子 |
|---|---|---|
| 定义 | 用 def 造一个函数 | def greet(name): |
| 调用 | 写函数名加括号才运行 | greet('小明') |
| 参数 | 把外面的值传进去 | def add(a, b) |
| 返回值 | 用 return 把结果交出来 | return a + b |
| 复用 | 一次写好,到处调用 | 调用十次只写一遍逻辑 |
AI 助手小贴士|函数写完别急着交,让 AI 当评审:参数设计、返回值、命名是否达意——评审意见比自己闷头改有价值。
打开任意 AI 对话工具(网页版或 App 都可以),试试这样问:请评审我写的这个函数:参数设计合不合理、该不该有返回值、函数名和注释是否达意?按「问题→建议→改进示例」的格式回答:<粘贴函数>
十五、随堂自测(12 题)
点击选项即可判分,选错的题会立刻展开解析。做完可以看到正确率和错题清单,也可以重新答题。
1想定义一个函数,必须用哪个关键字开头?
- A.
def - B.
func - C.
function - D.
define
def,后面跟函数名、括号和冒号。B/C 是别的语言的说法,define 是 def 的英文全称但不是关键字。2一个函数里只写了计算、没写 return,调用它得到什么?
- A.
0 - B.
None - C.
空字符串 - D. 会报错
return,函数就没有把任何值交回来,调用结果一律是 None。「没写 return」和「报错」要分清。3print(x) 和 return x 最关键的区别是什么?
- A.
print把 x 存进变量,return只是显示 - B.
print和return完全一样 - C.
print是给人看的显示,return是把值交给程序继续用 - D.
return不能用于函数里
print 只在屏幕显示给人看,后面没法接着算;return 把值交回调用处,能被变量接住继续用。需要下一步计算一定要用 return。4关于「先定义后调用」,下面说法正确的是?
- A. 函数可以写在调用之后,Python 会自动去找
- B. 调用必须写在
def定义之后 - C. 定义和调用谁先谁后都行
- D. 函数必须在文件最前面定义
NameError。5写出 def f(*args): 后,调用 f(1, 2, 3),args 收到的是什么类型?
- A.
列表 list - B.
元组 tuple - C.
字典 dict - D.
字符串 str
*args 把所有位置参数装进一个元组;两个星号的 **kwargs 才装进字典。6函数定义 def greet(name='同学'):,调用时写 greet() 会发生什么?
- A.
报错,必须传 name - B.
name 变成 None - C.
用默认值,打印/返回 '你好,同学' - D. 打印函数对象
'同学'。greet('小明') 才会覆盖成小明。7要在函数里修改函数外面的全局变量,必须怎么做?
- A. 直接赋值就行,不用特别写
- B. 用
global声明 - C. 把变量当参数传进去
- D. 不可能修改
global 变量名 声明,否则 Python 会当成一个新的局部变量,报 UnboundLocalError。8函数写 return 1, 2, 3,调用处用变量接,实际上拿到的是什么?
- A. 报错
- B.
三个独立的值 - C.
一个元组 (1, 2, 3) - D.
一个列表 [1, 2, 3]
a, b, c = f() 可以一次拆开接住。9一个函数里同时有普通参数、默认值参数、*args、**kwargs,正确顺序是?
- A. 普通 → 默认值 → *args → **kwargs
- B. 默认值 → 普通 → *args → **kwargs
- C. **kwargs → *args → 普通 → 默认值
- D. 随便排都行
SyntaxError。10为什么默认参数不要写成 def f(x, lst=[]): 这样的可变对象?
- A. 列表不能当默认参数,会报错
- B. 这个默认列表会在多次调用之间共享,数据会串味
- C. 默认值只能是数字
- D. 调用时无法传列表进去
None 当默认、函数内新建。11关于嵌套函数,下面说法正确的是?
- A. 内层函数可以直接使用外层函数里定义的变量
- B. 内层函数必须写
global才能看到外层变量 - C. 外层函数不能调用内层函数
- D. 嵌套函数只能写在类里面
nonlocal。内层函数只在外层里可见,出了外层就访问不到。12下面哪一种描述说的正是「闭包」?
- A. 把函数赋值给一个变量
- B. 在函数里调用自己
- C. 把一个列表当参数传给函数
- D. 内层函数被返回后,仍然记得外层函数的变量
make_adder(5) 返回的函数一直记着 n = 5)。在函数里调用自己那是递归。