函数是Python里增强代码重用性最有力的工具。
函数的定义
函数是组织好的,可以重复使用的,用来实现单一功能的代码。
def 函数名(参数):
函数体
return 语句
函数名:
1. 名字最好能体现函数的功能,一般用小写字母和单下划线、数字等组合
2. 不可与内置函数重名(内置函数不需要定义即可直接使用)
参数:根据函数功能,括号里可以有多个参数,也可以不带参数,命名规则与函数名相同
规范:括号是英文括号,后面的冒号不能丢
函数体:函数的执行过程,体现函数功能的语句,要缩进,一般是四个空格
return语句:后面可以接多种数据类型,如果函数不需要返回值的话,可以省略
例如,我们可以定义如下的数学函数
def math(x):
y = x ** 2 + x
return y
#调用函数:输入函数名和参数所对应的值,这个过程在函数里叫作参数的传递(pass)。
a = math(10)
print(a)
运行结果
110
函数的组成
a = len('万物的终极答案是42')
print(a)
b = len(['弦论小女孩','光束骑士','金色小鸟','宇宙蜂鸟'])
print(b)
len是一个求列表长度的函数。'万物的终极答案是42'是这个函数的参数。
自己写函数求字符串长度
def my_len(words):
counter = 0
for i in words:
counter = counter + 1
return counter
a = '我最爱的就是弦论小女孩'
print(my_len(a))
#等价于print(my_len('我最爱的就是弦论小女孩'))
参数类型
def opening():
print('欢迎大家来到弦论世界')
print('我是弦论小女孩')
print('我是光束骑士的助教')
opening()
这里定义了一个opening()函数,但是括号里没有带参数,原因是这个函数的功能是打印出固定的三句话,不需要参数的参与。需要强调的是,即便是没有参数,我们在调用函数的时候也不能省略括号,如此例中的opening()。在这个例子里,也不需要return语句,原因是这个函数直接在屏幕打印出内容,不需要返回值。事实上,没有return语句的函数,Python也会在末尾隐性地加上return None,即返回None值。
现在来看一个带参数的例子
def menu(easy, difficult):
print('首先你要学:' + easy)
print('然后你要学:' + difficult)
menu('广义相对论','超弦理论')
这里的'广义相对论'和'超弦理论'是对应参数的位置顺序传递的,所以easy和difficult被叫作【位置参数】,当有多个参数的时候,我们就必须按照顺序和数量传递,这也是最常见的参数类型
运行结果
首先你要学:广义相对论
然后你要学:超弦理论
另外一种参数传递方法也能给出相同的结果
menu(easy = '广义相对论', difficult = '超弦理论')
现在我们来学【默认参数】,直接在定义函数的时候给参数赋值。需要注意的是:默认参数必须放在位置参数之后。我们来看看代码:
def menu(easy, difficult, middle = '量子力学'):
print('首先你要学:' + easy)
print('然后你要学:' + difficult)
print('这个你也要学:' + middle)
menu('广义相对论','超弦理论')
运行结果
首先你要学:广义相对论
然后你要学:超弦理论
这个你也要学:量子力学
如果一个函数的某个参数值总是固定的,那么设置默认参数就免去了每次都要传递的麻烦。不过默认参数并不意味着不能改变
def menu(easy, difficult, middle = '量子力学'):
print('首先你要学:' + easy)
print('然后你要学:' + difficult)
print('这个你也要学:' + middle)
menu('广义相对论','超弦理论')
menu('广义相对论','超弦理论','量子场论')
运行结果
首先你要学:广义相对论
然后你要学:超弦理论
这个你也要学:量子力学
首先你要学:广义相对论
然后你要学:超弦理论
这个你也要学:量子场论
因为前两个位置参数已经有对应的值传递,Python会自动将'量子场论'传递给参数middle,替换了默认参数的默认值。要学的课太多啦,思思要哭了,这时候【不定长参数】就能派上用场,即传递给参数的数量是可选的、不确定的。
def name(*course):
return course
learn = name('广义相对论','超弦理论','量子场论')
#括号里的这几个值都会传递给参数course
print(learn)
print(type(learn))
运行结果
('广义相对论', '超弦理论', '量子场论')
你会发现函数返回的是这样的结果:('广义相对论', '超弦理论', '量子场论'),我们用type()函数可以知道这种数据类型叫作元组(tuple),曾在之前的笔记中与你打过照面。我们来稍微复习下:元组的写法是将数据放在小括号()中,它的用法和列表用法类似,主要区别在于列表中的元素可以随时修改,但元组中的元素不可更改。和列表一样,元组是可迭代对象。我们可以用for循环来遍历它,代码如下:
def name(*course):
for i in course:
print('要学的课:' + i)
name('广义相对论', '超弦理论')
name('广义相对论', '超弦理论', '量子场论')
运行结果
要学的课:广义相对论
要学的课:超弦理论
要学的课:广义相对论
要学的课:超弦理论
要学的课:量子场论
下面我们来看一些python内置函数的文档。比如说我们都非常熟悉的print函数
print(*objects, sep = ' ', end = '\n', file = sys.stdout, flush = False)
可以看到第一个参数objects带了*号,为不定长参数——这也是为什么print()函数可以传递任意数量的参数。其余四个为默认参数,我们可以通过修改默认值来改变参数,对比一下下列代码的输出结果。
print('广义相对论', '超弦理论', '量子场论')
print('广义相对论', '超弦理论', '量子场论', sep = '+')
# sep控制多个值之间的分隔符,默认是空格
print('超弦理论', '广义相对论', '量子场论', sep = '+', end = '=?')
# end控制打印结果的结尾,默认是换行)
运行结果
广义相对论 超弦理论 量子场论
广义相对论+超弦理论+量子场论
超弦理论+广义相对论+量子场论=?
返回多个值
函数,不仅可以支持输入多个参数,而且也可以同时输出多个值吗。接下来,我们就来讲讲如何用return语句来返回多个值。
妈妈看见思思在学广义相对论,推门进来,说:”你学这些没用的做什么!你得学应用!“
思思不解,问妈妈“什么是应用?”
妈妈说:“宇宙学,粒子物理,凝聚态和量子信息。”
思思于是写了如下程序。如果学完广义相对论还剩五小时就在宇宙学,粒子物理和凝聚态三门课中选一门学习,如果学完广义相对论之后还剩五到十小时就在宇宙学,粒子物理和凝聚态三门课中选一门学习,另外再加一门量子信息课。
思思写的程序如下
import random
application = ['宇宙学','粒子物理','凝聚态']
def mustlearn(time):
if time < 5:
a = random.choice(application)
return a
elif 5 <= time < 10:
b = random.choice (application)
return b, '量子信息'
print(mustlearn(4))
print(type(mustlearn(6)))
运行结果
粒子物理
没错,表示返回的数据类型又是我们刚才提到的元组。在这个例子中,该元组是由两个元素构成的。
多个函数间的配合 局部变量vs全局变量
程序中的变量并不是在哪个位置都可以被使用的,使用权限决定于这个变量是在哪里赋值的。关于这个概念,目前我们只需要掌握下面两点即可:
第一点:一个在函数内部赋值的变量仅能在该函数内部使用(局部作用域),它们被称作【局部变量】,如cost()函数里的gr和qft。
第二点:在所有函数之外赋值的变量,可以在程序的任何位置使用(全局作用域),它们被称作【全局变量】,如第一行的time。
那有没有一个能在函数内修改的方法呢?这时候global语句就能派上用场了,它可以将局部变量声明为全局变量,仔细看第四行代码。
time = 1
def cost():
global time_cost
gr = int(input('请输入今日学习广义相对论的时间'))
qft = int(input('请输入今日学习量子场论的时间'))
time_cost = gr + qft
print('今日学习GR和QFT时长是' + str(time_cost))
def sum_cost():
sum = time + time_cost
print('今日学习总时长是' + str(sum))
cost()
sum_cost()
运行结果
请输入今日学习广义相对论的时间5
请输入今日学习量子场论的时间5
今日学习GR和QFT时长是10
今日学习总时长是11
思思今天学了五小时广义相对论,五小时量子场论,一小时宇宙学,总学习时长11小时。
global语句一般写在函数体的第一行,它会告诉Python,“我希望time_cost是个全局变量,所以请不要用这个名字创建一个局部变量”。所以sum_cost()函数内部现在可以直接使用声明后的全局变量time_cost。
今天考试结果下来了,思思终于得了100分,噢耶!
def bonus(time):
if time < 6:
score = 60
return score
elif 6 <= time <= 10:
score = time * 10
return score
else:
score = 100
return score
def info(name, time):
gain = bonus(time)
print('%s每天花%s小时学习,得了%s分' % (name, time, gain))
info('思思',11)
思思查成绩时显示了如下结果
思思每天花11小时学习,得了100分
今天老师让同学们合作,思思写了如下计算程序,计算自己需要找几个合作者
# 请直接运行并体验代码
import math
# 变量key代表循环运行程序的开关
key = 1
# 采集信息的函数
def myinput():
choice = input('请选择计算类型:(1-所需时间计算,2-所需合作者人数计算)')
if choice == '1':
size = float(input('请输入project大小:(1代表标准大小,请输入小数)'))
number = int(input('请输入合作者数量:(请输入整数)'))
time = None
return size,number,time
# 这里返回的数据是一个元组
if choice == '2':
size = float(input('请输入project大小:(1代表标准大小,请输入小数)'))
number = None
time = float(input('请输入你计划花掉的时间:(请输入小数)'))
return size,number,time
# 这里返回的是一个元组
# 完成计算的函数
def estimated(my_input):
# 把元组中的数据取出来
size = my_input[0]
number = my_input[1]
time = my_input[2]
# 所需合作者人数计算
if (number == None) and (time != None):
number = math.ceil(size * 80 / time)
print('项目大小为%.1f个标准项目,如果需要在%.1f个小时完成,则需要合作者人数为:%d人' %(size,time,number))
# 所需时间计算
elif (number != None) and (time == None):
time = size * 80 / number
print('项目大小为%.1f个标准项目,使用%d个合作者完成,则需要时间为:%.1f个' %(size,number,time))
# 询问是否继续的函数
def again():
# 声明全局变量key,以便修改该变量
global key
a = input('是否继续计算?继续请输入y,输入其他键将结束程序。')
if a != 'y':
# 如果用户不输入'y',则把key赋值为0
key = 0
# 主函数
def main():
print('欢迎使用工作量计算小程序!')
while key == 1:
my_input = myinput()
estimated(my_input)
again()
print('感谢使用工作量计算小程序!')
main()
下课了,同学在玩石头剪刀布,思思却在一个人和电脑玩石头剪刀布,思思写了如下程序
import random
# 出拳
punches = ['石头','剪刀','布']
computer_choice = random.choice(punches)
user_choice = ''
user_choice = input('请出拳:(石头、剪刀、布)') # 请思思输入选择
while user_choice not in punches: # 当思思输入错误,提示错误,重新输入
print('输入有误,请重新出拳')
user_choice = input()
# 亮拳
print('————战斗过程————')
print('电脑出了:%s' % computer_choice)
print('你出了:%s' % user_choice)
# 胜负
print('—————结果—————')
if user_choice == computer_choice: # 使用if进行条件判断
print('平局!')
elif (user_choice == '石头' and computer_choice == '剪刀') or (user_choice == '剪刀' and computer_choice == '布') or (user_choice == '布' and computer_choice == '石头'):
print('你赢了!')
else:
print('你输了!')
底下是思思登录石头剪刀布游戏的用户名和密码的程序
n=0
while n<3:
username = input("请输入用户名:")
password = input("请输入密码:")
if username == '思思' and password == '123':
print("登录成功")
break
else:
n=n+1
print("输入有误")
else:
print("你输错了三次,登录失败")