函数 function:
什么是函数:函数是可以重复执行的语句块,可以重复调用
作用:
1、用于封装可重复执行的语句,提高语句的可重用性
2、定义用户级别的函数
函数定义语句 def语句的语法:
def 函数名(参数列表):
语句块(代码块)函数的语法说明:
1、函数的名字就是语句块的名称2、函数名的命名规则与变量名命名规则相同(必须为标识符)
3、函数名是一个变量(不要轻易对其赋值)
4、函数的自己的名字空间,在函数内部可以访问外部的变量,但外部的语句不能访问函数内部的变量
5、函数如果不需要传入参数,则参数列表可以为空
6、语句部分不能为空,如果为空需要填充pass语句
示例1:
def say_hello():
print('hello world')
print('hello tarena')
print('hello everyone')
函数调用:
函数名(实际调用传递参数)注:
实际调用传递参数简称'实参'
调用说明:
1、函数调用是一个表达式2、如果没有return语句,函数执行完以后返回None对象
3、如果函数需要返回其他的对象,需要用到return语句
示例2:
# 带有参数的函数的定义
# ! /usr/bin/python3
# 此示例示意定义一个带有参数的函数
def mymax(a, b):
if a > b:
print('最大数是:', a)
else:
print('最大数是:', b)
# 调用带有参数的函数,第一个实参100给形参a,第二个……
mymax(100, 200)
mymax(10000, 5000)
函数定义格式如下:
def print_even(n):pass
函数内部有独立的运行空间,函数外部不能访问函数内的变量
示例:# ! /usr/bin/python3
def test():
x = 100 # 此变量是局部变量,只能在函数内部使用
print(y) # 这是合法的此函数可以访问函数以外的全局变量
y = 200
test() # 调用test
# print(x) # 此时没有x这个变量
return语句:
语法:return[表达式]
注:[]代表其中的内容可以省略
作用:
用于函数中,结束当前函数的执行,返回到调用函数的地方,同时返回一个对象的引用关系
说明:
1、return语句后跟的表达式可以省咯,省咯后相当于return None
2、如果函数内没有return语句,则函数执行
完最后一条语句后返回None(相当于在最后加了一条return None语句)
3、函数调用能够返回一个对象的引用
示例:
# ! /usr/bin/python3
# 此示例示意return语句的用法
def hello():
print('hello world')
print('hello tarena')
return # 用于返回到调用的地方
print('hello everyone')
v = hello()
print(v)
练习:
'''
1、写一个函数mymax,返回两个数的最大值:
'''
def mymax(x, y):
if x >= y:
return x
return y
print(mymax(100, 200))
print(mymax(200, 100))
print(mymax('acd', 'abcd'))
'''
2、写一个函数input_number()
此函数用于读取用户输入的多个整数(用户输入负数时结束输入)
将用户输入的数形成列表返还给调用者
'''
# 方法一
# ! /usr/bin/python3
def input_number():
number = []
while True:
n = int(input('请输入正整数:'))
if n < 0:
break
number.append(n)
return number
if __name__ == '__main__':
n = input_number()
print(n)
print('您输入的最大数是', max(n))
print('您输入数的和是', sum(n))
# 方法二
# ! /usr/bin/python3
def input_number2():
number = []
while True:
n = int(input('请输入正整数:'))
if n < 0:
return number
number.append(n)
if __name__ == '__main__':
n = input_number2()
print(n)
print('您输入的最大数是', max(n))
print('您输入数的和是', sum(n))
python函数的参数传递
传递方式:
位置传参序列传参
关键字传参
字典关键字传参
位置传参:
实际调用参数(实参)的对应关系与形式参数(形参)的对应关系是按位置来一次对应的示意:
def fx(a, b, c):
pass
# ^ ^ ^
fx(1, 2, 3)
序列传参:
序列传参是在函数地调用过程中,用*将序列拆解后按位置进行传递的参数方式
实参和形参通过序列传递和匹配
示例:
def fx(a, b, c):
pass
s1 = [11, 22, 33]#列表
fx(*s1)# 将s1序列拆解后按位置传入fx中
# ! /usr/bin/python3
# 此示例示意序列传参
def fx(a, b, c):
print('a=', a)
print('b=', b)
print('c=', c)
s1 = [11, 22, 33]
# 索引传参
# fx(s1[0],s1[1],s1[2])
# 序列传参
fx(*s1) # * 代表要讲s1 拆解后在依次传入
fx(*'ABC')
fx(*(101, 202, 303))
# fx(*'ABCD') # 有错,序列中有四个参数,但形参是三个
print(*'abc') # 等同于print('a','b','c')
关键字传参:
是指传参时,按着形参的名称给形参赋值实参和形参按名称进行pip
示例:
def fx(a, b, c):
pass
fx(b=22, c=33, a=11) # 11-->a, 22-->b, 33-->c
注:
实参和形参按形参名进行匹配,可以不按位置进行匹配
#! /usr/bin/python3
def fx(a, b, c):
print('a=', a)
print('b=', b)
print('c=', c)
fx(b=22, c=33, a=11)
# fx(b=22, c=33, b=55) # 错的
字典关键字传参
实参为字典,用**拆解字典后在进行关键字传参示例:
def fx(a, b, c):
pass
d = {'c':33, 'b':22, 'a':11}
fx(**d) # 拆解字典在依次按关键字传参
说明:
字典的键名和形参名必须一致
字典的键名必须为字符串
字典的见面要在形参中存在
#! /usr/bin/python3
def fx(a, b, c):
print('a=', a)
print('b=', b)
print('c=', c)
d = {'c': 33, 'b': 22, 'a': 11}
fx(**d) # 拆解字典在依次按关键字传参
# fxc=33, b=22, a=11)
综合传参:
函数的传参方式在能确定形参能唯一匹配到兴宁实参的情况下可以任意组合注:
通常位置传参和序列先传递,其次是关键字传参和字典关键字传参
示例:
def fx(a, b, c, d, e, f):
pass
fx(10, *[20, 30], e=50, **{'d': 40, 'f': 60})
# 以下是错误做法
fx(e=50, **{'d': 40, 'f': 60}, 10, *[20, 30])
*************************以下将函数的形参**********************
函数的缺省参数:
语法:def 函数名(形参名1=默认实参, 形参名2=默认实参2,……):
语句
示例:
#! /usr/bin/python3
def info(name, age=1, address='不详'):
print('我叫', name, '我今年:', age, '岁,家庭住址:', address)
info('张飞', 30, '中原')
info('Tarena', 10)
info('赵云')
# 运行结果
我叫
张飞
我今年: 30
岁,家庭住址: 中原
我叫
Tarena
我今年: 10
岁,家庭住址: 不详
我叫
赵云
我今年: 1
岁,家庭住址: 不详
说明:
缺省参数必须自右至左依次存在
缺省参数可以有0个1个或多个,甚至全部都有缺省参数
缺省参数的绑定对象存在于函数内,同函数的生命周期一致
重要**示例:
def fn(a, lst=[]): # ***重要****
^
|
# 不会删除,不会定义新列表
lst.append(a)
print(lst)
L = [1, 2, 3, 4]
fn(5, L) # [1, 2, 3, 4, 5]
fn(6, L) # [1, 2, 3, 4, 5, 6]
fn(1.1) # [1.1]
fn(2.2) # [1.1, 2.2]
函数的形参定义方式:
1、位置形参2、星号元组形参
3、命名关键字形参
4、双星号字典形参
位置形参:
def 函数名(形参名1,形参名2,……):语句块
星号元组形参:
语法:def 函数名(*元组形参名):
语句块
作用:
收集多余的位置参数
示例:
#! /usr/bin/python3
# 此示例示意星号元组形参
def func(*args):
print('实参个数是:', len(args))
print('args的值是:', args)
func(1, 2, 3)
func('ABCD', 3.14, 100, True, None)
命名关键字形参:
语法:def 函数名(*, 命名关键字形参):
语句块
或
def 函数名(*args,命名关键字形参):
语句块
作用:
所有的命名关键字形参都强制调用者采用关键字传参或字典关键字传参的方式传递
示例:
#! /usr/bin/python3
def myfun(a, *, k):
print('a=', a)
print('k=', k)
# myfun(100, 200) # 错的
myfun(100, k=200) # k强制使用命名关键字传参
myfun(100, **{'k': 200}) # 字典关键字传参
双星号字典形参:
语法:def 函数名(**字典形参名)
语句块
作用:
收集多余的关键字传参
注:
字典形参名通常叫"kwargs"
示例:
#! /usr/bin/python3
# 此示例示意双星号字典形参的用法
def func(**kwargs):
print('关键字参数的个数是:', len(kwargs))
print('kwargs =', kwargs)
func(name='tarena', age=15)
# 运行结果:
# 关键字参数的个数是: 2
# kwargs = {'name': 'tarena', 'age': 15}
func(a=1, b='BBBB', c=[2, 3, 4], d=True)
# 运行结果:
# 关键字参数的个数是: 4
# kwargs = {'a': 1, 'b': 'BBBB', 'c': [2, 3, 4], 'd': True}
函数参数说明:
位置形参,缺省参数,星号元组形参数,命名关键字形参,双星号字典形参可以混合使用函数参数自左向右的顺序为:
1、位置形参
2、星号元组形参
3、命名关键字形参
4、双星号字典形参
示例:def fn(a, b, *args, c, **kwargs):
pass
fn(100, 200, 300, 400, *'AB', **{'d':'D'}, c=100)
#! /usr/bin/python3
def fn(a, b, *args, c, **kwargs):
print('a=', a)
print('b=', b)
print('args=', args)
print('c=', c)
print('kwargs=', kwargs)
fn(100, 200, 300, 400, *'AB', **{'d': 'D'}, c=100)
'''
上面的结果
a= 100
b= 200
args= (300, 400, 'A', 'B')
c= 100
kwargs= {'d': 'D'}
'''
可以接受任意位置传参和关键字传参的函数:
def fn(*args, **kwargs):pass
#! /usr/bin/python3
def fn(*args, **kwargs):
print('args=', args)
print('kwargs=', kwargs)
fn()
'''
args= ()
kwargs= {}
'''
fn(a=100)
'''
args= ()
kwargs= {'a': 100}
'''
fn('a', a=100)
'''
args= ('a',)
kwargs= {'a': 100}
练习:
#! /usr/bin/python3
'''
1、写一个函数,mysum,可以传入人一个实参的数字,返回所有实参的和
def mysum(...):
...
print(mysum(1,2,3,4))#10
print(mysum(5,6,7,8,9))#35
'''
def mysum(*args):
return sum(args)
if __name__ == '__main__':
print(mysum(1,2,3,4))
print(mysum(5,6,7,8,9))
#! /usr/bin/python3
'''
2、已知内建函数max的帮助文档为:
max(...):
max(iterable) -> value
max(arg1,arg2,*args) -> value
仿造max,写一个mymax函数,实现功能与max完全相同
测试用例:
print(mymax([6,8,3,5]))#8
print(mymax(100,200))#200
print(mymax(1,3,9,7,5))#9
'''
# 方法一:
'''
def mymax(*args):
if len(args)==1:
L=list(*args)
elif len(args)>1:
L=list(args)
L.sort(reverse=True)
return L[0]
'''
'''
# 方法二:
def mymax(a, *args):
if len(args) == 0:
m = a[0]
i = 1
while i < len(a): # 遍历之后的每一个元素
if m < a[i]: # 如果此元素比m大,则让m绑定
m = a[i]
i += 1
return m # 最后m一定绑定一个最大的
else:
m = a
for i in args:
if m < i:
m = i
return m
'''
# 方法三:
def mymax(a, *args):
def _max(*args):
# 此函数用于求args元组的最大值
m = args[0] # 先假设第一个数最大
i = 1
while i < len(args): # 遍历之后的每一个元素
if m < args[i]: # 如果此元素比m大,则让m绑定
m = args[i]
i += 1
return m # 最后m一定绑定一个最大的
if len(args) == 0:
return _max(*a)
return _max(a, *args)
if __name__ == '__main__':
print(mymax([6, 8, 3, 5])) # 8
print(mymax(100, 200)) # 200
print(mymax(1, 3, 9, 7, 5)) # 9
#! /usr/bin/python3
'''
3、写一个函数minmax,可以给出任意个数字实参,返回这些实参的最小数和最大数,
要求两个数字组成元组后返回(最小数在前,最大数在后)
调用此函数,能得到实参的最小值和最大值
xiao,da = minmax(5,7,9,3,1)
print('最小数是:',xiao)
print('最大数是:',da)
'''
def minmax(*args):
return (min(args), max(args))
pass
xiao, da = minmax(5, 7, 9, 3, 1)
print('最小数是:', xiao)
print('最大数是:', da)
函数变量:
函数名是变量,他在创建时绑定一个函数def f1(lst=[]):
print('f1函数被调用')
f1()
f1 = None
f1() # 出错,f1绑定的是None
示例:
def f1():
print('hello')
def f2():
print('world')
f1, f2 = f2, f1
f1() # world
一个函数可以作为另一个函数的参数(实参)传递
示例:def f1():
print('f1函数被调用')
def f2():
print('f2函数被调用')
def fx(fn):
print('fn绑定的函数是', fn)
# 在fx内调用fn绑定的函数
fn()
fx(f1) # 调用fx,把f1作为实参传数
fx(f2) # 用fx间接调用f2
fx(f2()) # f2加括号先执行f2(),将返回的None作为实参传递给fx(),fn()会报错
# 看懂下列代码在做什么?为什么?
def goodbye(L):
for x in L:
print('再见:', x)
def hello(L):
for x in L:
print('欢迎:', x)
def fx(fn, L):
print('fx被调用')
fn(L)
fx(hello, ['Tom', 'Jerry', 'Spiker'])
'''
运行结果
fx被调用
欢迎:Tom
欢迎:Jerry
欢迎:Spiker
'''
fx(goodbye, ['小张', '小李'])
'''
运行结果
fx被调用
再见:小张
再见:小李
'''
-------------------------------------------------------------------------------------------------------------------
def fx(fn,L):
print('结果是:',fn(L))
lst = [3,9,7,5,2]
fx(max,lst)
fx(sum,lst)
函数可以作为另一个函数的返回值:
函数可以返回另一个函数示例:
#! /usr/bin/python3
def get_op():
s = input('请输入您的操作:')
if s == '求最大':
return max
elif s == '求最小':
return min
elif s == '求和':
return sum
L = [2, 4, 6, 8, 10]
print(L)
f = get_op()
print(f(L))
函数嵌套定义:
def 语句的作用是用来创建一个函数
def 语句可以写在函数内部,在函数执行时可以动态创建一个函数
示例:#! /usr/bin/python3
# 此示例示意函数的嵌套定义
def get_func(value):
if value == 1:
def myadd(x, y):
return x + y
return myadd
elif value == 2:
def mysub(x, y):
return x - y
return mysub
fx = get_func(1)
print(fx(400, 300)) # 700
fx = get_func(2)
print(fx(400, 300)) # 100
全局变量和局部变量
局部变量:
1、定义在函数内部的变量成为局部变量(函数的形参也是局部变量)2、局部变量只能在函数内部使用
3、局部变量在函数调用时才能被创建,在函数调用后会自动销毁
全局变量:
定义在函数外部,模块内部的变量称为全局变量全局变量所有的函数都可以直接访问(但函数内部不能修改全局变量的绑定关系)
示例:
#! /usr/bin/python3
# 此示例用来说明全局变量和局部变量
a = 100
b = 200
def fn(c):
d = 400
# print(a, b, c, d) #此时a变量还不存在,报错
a = 500 # 创建一个局部变量
print(a, b, c, d)
fn(300)
print('a=', a)
print('b=', b)
'''
运行结果:
500 200 300 400
a= 100
b= 200
'''
局部变量说明:
1、在函数内首次对变量赋值是创建局部变量,再次为变量赋值是修改局部变量的绑定关系2、在函数内不得赋值语句不会对全局变量造成影响
python作用域:
作用于也叫命名空间,是访问变量时查找变量名的范围空间python的四个作用域LEGB
作用域 | 英文解释 | 英文简写 |
---|---|---|
局部作用域(函数内) | Local(function) | L |
外部嵌套函数作用域 | Enclosing function locals | E |
函数定义所在模块的作用域 | Global(module) | G |
python内置模块的作用域 | Builtin(python) | B |
示例:
#! /usr/bin/python3
v = 100 # 全局变量
def fun1():
v = 200
print('fun1里的v的值是:', v)
# 定义另一个函数fun2,然后调用一下
def fun2():
print('fun2里的v=',v)
fun2()
fun1()
print('全局的v=', v)
变量名的查找规则(顺序)
1、本地变量2、查找包裹此函数的外部嵌套函数内部的变量
3、全局变量
4、内置变量
globals() / locals() 函数
globals() 返回全局作用域内变量的字典locals() 返回局部作用域内变量的字典
示例:
#! /usr/bin/python3
a = 100
b = 200
def fx(b, c):
print(a, b, c)
# 思考在此函数内部能够获取到全局变量b绑定的值
print('全局变量的字典是:', globals())
print('局部变量的字典是:', locals()) # {'c': 400, 'b': 300}
print('此处访问全局的b的值是:', globals()['b'])
fx(300, 400)
练习:
#! /usr/bin/python3
'''
写一个函数mysum(n),此函数的功能是返回
1+2+3+4+5+6+7+8+……+n
def mysum(n):
……
print(mysum(100))35050
'''
def mysum(n):
a = 0
while n > 0:
a += n
n -= 1
return a
print(mysum(100))
'''
2、写一个函数mysum2
此函数可以传入一个参数,两个参数和三个参数
1)当传入一个参数时这个参数代表终止式
2)当传入两个参数时,第一个参数代表起始值,第二个参数代表终止值
3)当传入三个参数时,第三个参数代表步长
此函数的功能是返回从开始到终止值的和
如:
print(mysum2(5)) #10 (0+1+2+3+4=10)
print(mysum2(4,6)) #9 (4+5=9)
print(mysum2(5,10,2)) #21(5+7+9)
'''
# 方法一
def mysum2(*args):
a = 0
if len(args) == 1:
for i in range(args[0]):
a += i
elif len(args) == 2:
for i in range(args[0], args[1]):
a += i
elif len(args) == 3:
for i in range(args[0], args[1], args[2]):
a += i
else:
a = '输入错误'
return a
print(mysum2(5)) # 10 (0+1+2+3+4=10)
print(mysum2(4, 6)) # 9 (4+5=9)
print(mysum2(5, 10, 2))
# 方法二
def mysum2(*args):
a = 0
if len(args) == 1:
r = range(args[0])
elif len(args) == 2:
r = range(args[0], args[1])
elif len(args) == 3:
r = range(args[0], args[1], args[2])
else:
a = '输入错误'
for i in r:
a += i
return a
print(mysum2(5)) # 10 (0+1+2+3+4=10)
print(mysum2(4, 6)) # 9 (4+5=9)
print(mysum2(5, 10, 2))
# 方法三
def mysum2(start, stop=None, step=1):
m = 0
if stop == None:
stop = start
start = 0
for i in range(start, stop, step):
m += i
return m
print(mysum2(5)) # 10 (0+1+2+3+4=10)
print(mysum2(4, 6)) # 9 (4+5=9)
print(mysum2(5, 10, 2))
# 方法四
def mysum2(start, stop=None, step=1):
if stop == None:
stop = start
start = 0
return sum(range(start, stop, step))
print(mysum2(5)) # 10 (0+1+2+3+4=10)
print(mysum2(4, 6)) # 9 (4+5=9)
print(mysum2(5, 10, 2))
# 方法五
def mysum2(*args):
return sum(range(*args))
print(mysum2(5)) # 10 (0+1+2+3+4=10)
print(mysum2(4, 6)) # 9 (4+5=9)
print(mysum2(5, 10, 2))
global语句:
作用:1、告诉解释执行器,global语句声明的是一个或多个变量,这些变量的作用域为模块级的作用域的变量,也称作全局变量
2、全局声明(global)将赋值变量映射到模块文件内部的作用域
语法:
global 变量1, 变量2, ……
示例:
global ga, gb
global gc
global声明示例:
#! /usr/bin/python3
v = 100
def fx():
global v #声明v为全局变量不是局部变量
v = 200#修改全局的v怎么办
fx()
print(v)
说明:
1、全局变量如果需要在函数内部被赋值,则必须经过全局声明(否则会被认为是局部变量)2、全局变量在函数内部不经过声明就可以直接访问
3、不能先声明局部变量,再用global声明为全局变量,此做法不合法
4、global变量列表里的变量名不能出现在此作用域内的形参列表里
nonlocal语句
作用:告诉解释器,nonlocal声明的变量不是局部变量也不是全局变量,而是外部嵌套函数内的变量
语法:
nonlocal 变量名1, 变量名2, ……
示例:
#! /usr/bin/python3
# 此示例示意nonlocal语句的作用
v = 100
def outter():
v = 200
print('ourrer里的v=', v)
# 在函数内建一个函数并调用
def inner():
nonlocal v # 声明v为外部嵌套函数
v += 1
print('innter里的v=', v)
inner()
print('调用inner后,outter里的v=', v)
outter()
print('全局里的v值是:', v)
'''
运行结果
ourrer里的v= 200
innter里的v= 201
调用inner后,outter里的v= 201
全局里的v值是: 100
'''
说明:
1、nonlocal语句只能在被嵌套到的函数内部进行使用2、访问nonlocal变量将对外部嵌套函数作用域内的变量进行操作
3、当有两次或两层以上函数嵌套时,访问nonlocal变量只对最近一层的变量进行操作
4、nonlocal语句的变量列表的变量名不能出现在此函数的参数列表里
说明三示例:
# ! /usr/bin/python3
def f1():
v = 100
def f2():
v = 200
def f3():
nonlocal v
v += 1 # 此时只对f2的v进行操作
f3()
f2()
练习:
#! /usr/bin/python3
'''
创建一个列表L=[]
写一个函数input_number读取数据放入列表L中
程序如下:
L=[]
def input_number():
#此处自己加代码
while True:
i=int(input('请输入数字:'))
……
#此处自己完成
input_number()
print('您刚才输入的整数值是:',L)
'''
L = []
# 方法一
def input_number():
# 此处自己加代码
while True:
i = int(input('请输入数字(-1结束):'))
if i != -1:
L.append(int(i)) # 此时没有改变L绑定关系,只改变列表内部
else:
break
input_number()
print('您刚才输入的整数值是:', L)
# 方法二
def input_number2():
l = []
while True:
i = int(input('请输入数字(-1结束):'))
if i != -1:
l.append(int(i)) # 此时没有改变L绑定关系
else:
break
global L
L = l # 改变变量
input_number2()
print('您刚才输入的整数值是:', L)
#! /usr/bin/python3
# 第二题
'''
2、写一个函数isprime()
判断x是否是素数,如果为素数返回True,否则返回False
测试代码:
if isprime(5):
print('素数')
'''
def isprime(n):
if n < 2:
return False
for i in range(2, n):
if n % i == 0:
return False
return True
if isprime(5):
print('素数')
# 第三题
'''
3、写一个函数prime_m2n(m,n)返回从m开始,到n结束范围内素数的列表,并打印
L=prime_m2n(10, 20)
print(L) # [11, 13, 17, 19]
'''
def prime_m2n(m, n):
L = []
for i in range(m, n):
if isprime(i):
L.append(i)
return L
# 以下是用函数式编程解决此问题
# return list(filter(isprime,range(m,n)))
L = prime_m2n(10, 20)
print(L) # [11, 13, 17, 19]
# 第四题
'''
4、写一个函数primes(n),返回小于n的所有素数的列表
L=primes(10)
print(L) # [2, 3, 5, 7]
'''
def primes(n):
return prime_m2n(2, n)
L = primes(10)
print(L) # [2, 3, 5, 7]