1、函数
- 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
- 函数能提高应用的模块性,和代码的重复利用率。
- Python提供了许多内建函数,比如print()。也可以自己创建函数,这被叫做用户自定义函数。
2 、定义一个函数
你可以定义一个由自己想要功能的函数,以下是简单的规则:
- 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()。
- 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
- 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
- 函数内容以冒号起始,并且缩进。
- return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。
一般格式如下:
def 函数名(参数列表):
函数体
retrun 返回值
函数里面嵌套函数:
def toto():
print('name is toto')
def age():
print('age is 16')
age()
toto()
3、调用函数
定义一个函数:给了函数一个名称,通过函数名来调用函数
#定义函数
def toto():
print('name is toto')
#定义函数
def age():
print('age is 16')
age() # 通过函数名称来调用函数
toto() # 通过函数名称来调用函数
输出结果为:
name is toto
age is 16
4 、参数
参数分为形参和实参:
定义函数的时候的变量,叫形参(形参可以任意起名)
调用函数的时候,真实的数据信息,调用函数的时候传递的参数叫实参
形参:位置参数 默认参数 可变参数 关键字参数
1 位置参数
位置参数:形参和实参必须保持一致,定义函数的时候参数的顺序和调用函数的时候输入参数的顺序必须一致
def stuinfo(name,age):
print('%s is %d' %(name,age))
stuinfo('toto',17)
#输出结果:
toto is 17
def stuinfo(name,age):
print('%s is %s' %(name,age))
stuinfo(17,'toto') # 当输入的实参和形参的顺序不一致的时候,出现输出异常
#输出结果:
17 is toto
def stuinfo(name,age):
print('%s is %s' %(name,age))
stuinfo(age=17,name='toto') # 传入实参的时候 可以将形参和实参对应起来
#输出结果:
toto is 17
2 默认参数
在定义函数的时候,给定一个参数默认值,当调用函数的时候,如果没有给该形参传入实参,则使用该默认值进行运算。
def add(x,y=10): # 定义函数,其中第二个形参的默认值为10
print(x+y)
add(5,3) # 当调用函数的时候,传入两个实参,则使用传入的值进行运算
add(5) # 当只传入一个值的时候,另一个使用默认参数值进行运算
输出结果:
8
15
3 可变参数
当参数的个数不确定的时候,可以使用可变参数,来表示该函数可以接收任意个参数
在使用可变参数的时候:
其中*a 表示对参数进行解包,将序列中的元素一个一个的拿出来。
a的对象类型是一个元组。
def mysum(*a): # 定义函数的形参数是任意个
print(*a)
print(a)
sum = 0
for item in a:
sum += item
print(sum)
nums = [1,2,3,4]
nums1 = (1,2,3,4)
nums2 = {1,2,3,4}
mysum(*nums)
mysum(*nums1)
mysum(*nums2)
运行结果:
# 当实参是一个列表的时候,返回值
1 2 3 4 # 解包列表的得到的数据
(1, 2, 3, 4) # a的对象类型为一个元组
10 # 最后的返回值
# 当实参是一个元组的时候,返回值
1 2 3 4 # 解包元组的得到的数据
(1, 2, 3, 4) # a的对象类型为一个元组
10 # 最后的返回值
# 当实参是一个集合的时候,返回值
1 2 3 4 # 解包集合的得到的数据
(1, 2, 3, 4) # a的对象类型为一个元组
10 # 最后的返回值
4 关键字参数
关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict
def person(name, age, **kw):
print('name:', name, 'age:', age, 'other:', kw)
函数person除了必选参数name和age外,还接受关键字参数kw。在调用该函数时,可以只传入必选参数:
person('Michael', 30) # 调用函数
name: Michael age: 30 other: {} # 输出的结果
也可以传入任意个数的关键字参数:
person('Bob', 35, city='Beijing') # 调用函数的时候传入一个关键字参数
name: Bob age: 35 other: {'city': 'Beijing'} # 该关键字参数被放置在字典中
person('Adam', 45, gender='M', job='Engineer') # 调用函数的时候传入2个关键字参数
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'} # 该关键字参数被放置在字典中
关键字参数有什么用?它可以扩展函数的功能。比如,在person函数里,我们保证能接收到name和age这两个参数,但是,如果调用者愿意提供更多的参数,我们也能收到。试想你正在做一个用户注册的功能,除了用户名和年龄是必填项外,其他都是可选项,利用关键字参数来定义这个函数就能满足注册的需求。
和可变参数类似,也可以先组装出一个dict,然后,把该dict转换为关键字参数传进去:
extra = {'city': 'Beijing', 'job': 'Engineer'} # 组装一个字典,将关键字参数写成键值对的形式
person('Jack', 24, city=extra['city'], job=extra['job']) # 把字典中的键值对转化成关键字参数传进函数
name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'} # 输出结果正常
当然,上面复杂的调用可以用简化的写法:
extra = {'city': 'Beijing', 'job': 'Engineer'}
person('Jack', 24, **extra)
name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
**extra
表示把extra这个dict的所有key-value(键值对)用关键字参数传入到函数的**kw参数,kw将获得一个dict,注意kw获得的dict是extra的一份拷贝,对kw的改动不会影响到函数外的extra。
5、函数的返回值
- 返回值:函数运算的结果,还需要进一步操作,给函数一个返回值
- return用来返回函数执行的结果,如果函数没有返回值,默认返回None
- 一旦遇到return 函数执行结束,后面的代码不会执行多个返回值的时候,python会帮我们封装成一个元组类型
1 当函数没有指定返回值的时候,默认返回值是None
def getStuInfo(name,age):
print(name)
print(age)
a = getStuInfo('toto',16)
print(a)
#显示结果:
toto
16
None # 函数没有返回值,函数执行的结果默认返回None
2 当函数存在返回值的时候,一旦遇到return 直接结束 后面的代码就不会在再执行
def getStuInfo(name,age):
print(name)
if name == 'toto' :
return 'name is toto' # 函数的返回值
print(age)
a = getStuInfo('toto',16)
print(a)
#输出结果:
toto
name is toto # 存在返回值,并且成功返回该返回值,之后的代码将不会再执行
6 、变量的作用域
- Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的。
- 局部变量:在函数内部定义的变量,只在函数内部起作用,函数执行结束后,变量会自动删除
变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。Python的作用域一共有4种,分别是:
- L (Local) 局部作用域
- E (Enclosing) 闭包函数外的函数中
- G (Global) 全局作用域
- B (Built-in) 内置作用域(内置函数所在模块的范围)
a = 1 # 全局作用域
def outer():
b = 2 # 闭包函数外的函数中
def inter():
c = 3 # 局部作用域
全局变量和局部变量
定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。
局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中
total = 0 # 这是一个全局变量
def sum(arg1, arg2):
# 返回2个参数的和
total = arg1 + arg2 # total在这里是局部变量.
print("函数内是局部变量 : ", total)
return total
# 调用sum函数
sum(10, 20)
print("函数外是全局变量 : ", total)
#输出结果:
函数内是局部变量 : 30
函数外是全局变量 : 0
**修改局部变量为全局变量 :格式:global 变量名称 **
total = 0 # 这是一个全局变量
print(total)
def toto():
global total # 指定函数中的局部变量为全局变量
total = 10 # 重新给变量赋值
print(total)
toto()
print(total)
输出结果:
0 # 原来的值
10 # 再函数中给定义为全局变量的变量赋值
10 # 再次再函数外面输出该变量,由于函数中指定函数中的局部变量为全局变量,所以该值被修改
如果要将局部作用域修改成嵌套作用域(enclosing 作用域,外层非全局作用域),需要 nonlocal 关键字了
num = 0
print('全局第一次输出值:' ,num)
def outer():
num = 10
print('外层函数第一次输出值:' ,num)
def inner():
nonlocal num # nonlocal关键字声明
num = 100
print( '修改局部变量作用域为闭包函数外的函数中后重新赋值:' ,num)
inner()
print('变量作用域修改后并且重新赋值后,外层函数中变量的值:' ,num)
outer() # 函数调用
print( '再次输出全局变量的值:' ,num)
#输出结果:
全局第一次输出值: 0
外层函数第一次输出值: 10
修改局部变量作用域为闭包函数外的函数中后重新赋值: 100
变量作用域修改后并且重新赋值后,外层函数中变量的值: 100
再次输出全局变量的值: 0
应用练习:
案例1:
编写一个函数cacluate, 可以接收任意多个数,返回的是一个元组.
元组的第一个值为所有参数的平均值, 第二个值是大于平均值的所有数.
def cacluate(*x):
sum = 0
for i in x :
sum += i
average = sum/len(x)
li = []
for k in x :
if k > average :
li.append(k)
return (average,li)
#调用函数,测试效果
a = cacluate(2,6,8,9,2,5,7)
print(a)
案例2:
编写一个函数, 接收字符串参数, 返回一个元组,‘ehllo WROLD’
元组的第一个值为大写字母的个数, 第二个值为小写字母个数.
def count(s):
upper_c = 0
lower_c = 0
for i in s :
if i.isupper() :
upper_c +=1
if i.islower() :
lower_c +=1
return (upper_c,lower_c)
print(count(input(':')))
效果演示:
[kiosk@foundation31 05 lianxi]$ python3 01.py
:WESAdfaga sdfagWRsdfa
(6, 14)
案例3:
编写函数, 接收一个列表(包含10个整形数)和一个整形数k, 返回一个新列表.
函数需求:
- 将列表下标k之前对应(不包含k)的元素逆序;
- 将下标k及之后的元素逆序;
[1,2,3,4,5] 2 [2,1,5,4,3]
#定义函数
def fun(alist,k):
if k <0 or k >len(alist):
return 'Error !!'
return alist[:k][::-1] + alist[k:][::-1]
#自动生成随机列表
import random
list = []
for i in range(10):
list.append(random.randint(1,100))
#测试函数是否达到效果
print(list)
print(fun(list,5))
运行效果:
[kiosk@foundation31 05 lianxi]$ python3 01.py
[75, 53, 38, 98, 62, 63, 21, 74, 25, 83]
[62, 98, 38, 53, 75, 83, 25, 74, 21, 63]
[kiosk@foundation31 05 lianxi]$ python3 01.py
[58, 22, 44, 78, 22, 31, 62, 16, 62, 56]
[22, 78, 44, 22, 58, 56, 62, 16, 62, 31]
题目:两个乒乓球队进行比赛,各出三人。
甲队为a,b,c三人,乙队为x,y,z三人。
已抽签决定比赛名单。有人向队员打听比赛的名单。
a说他不和x比,c说他不和x,z比,请编程序找出三队赛手的名单。
team = ['x','y','z']
all_order = []
for i in team :
for k in team :
if k != i :
for m in team:
if m !=k and m !=i :
all_order.append([i,k,m])
for t in all_order :
if t[0] !=team[0] and t[2] != team[0] and t[2] != team[2] :
print('a <——> %s ; b <——> %s ; c <——> %s ' %(t[0],t[1],t[2]))
运行效果演示:
[kiosk@foundation31 05 lianxi]$ python3 01.py
a <——> z ; b <——> x ; c <——> y
模拟轮盘抽奖游戏
轮盘分为三部分: 一等奖, 二等奖和三等奖;
#轮盘转的时候是随机的,
###如果范围在[0,0.08)之间,代表一等奖,
###如果范围在[0.08,0.3)之间,代表2等奖,
###如果范围在[0.3, 1.0)之间,代表3等奖,
###模拟本次活动1000人参加, 模拟游戏时需要准备各等级奖品的个数.
1 直接判断
import random
first_prize=second_prize=third_prize = 0
for i in range(1000):
k = random.random()
if 0 <= k <0.08 :
first_prize +=1
elif 0.08 <= k <0.3 :
second_prize +=1
else:
third_prize +=1
print('一等奖:%d \n 二等奖:%d \n 三等奖:%d' %(first_prize,second_prize,third_prize))
2 定义函数进行判断
import random
#创建函数,主要判断每一次的转盘是几等奖
def reward_level(f):
reward_dict = {
'first_prize':(0,0.08),
'second_prize':(0.08,0.3),
'third_prize':(0.3,1)
}
for k,v in reward_dict.items():
if v[0] <= f < v[1] :
return k
prize_count = {}
for i in range(1000):
reward = reward_level(random.random())
if reward in prize_count :
prize_count[reward] += 1
else:
prize_count[reward] = 1
for t in prize_count:
print('%s :%d' %(t,prize_count[t]))
运行演示:
[kiosk@foundation31 05 lianxi]$ python3 01.py
third_prize :694
second_prize :228
first_prize :78
[kiosk@foundation31 05 lianxi]$ python3 01.py
third_prize :694
first_prize :71
second_prize :235