函数是python为了代码最大程度的重用和最小化代码冗余而提供的最基本的程序结构。函数也是一种设计工具,使用函数,我们也可以把复杂的系统分解为可管理的部件
函数的相关语句和表达式
语句 | 例子 |
---|---|
Calls | my_function('Fir Arg','Sec Arg') |
def | def myfunction(fir_arg,sec_arg): |
return | return fir_arg+sec_arg |
global | global x;x=new_value |
nonlocal | nonlocal x;x=new_value |
yield | def my_sqr(x): for i in range(x): yield i **2 |
lambda | funcs=[lambda x: x*2,lambda x:x3] |
def是可执行的代码。在python里,只有def执行之后,才会生成相应的函数。要是def没有执行,相应的函数就不会生成。def语句在if、while语句甚至是其他def语句里也是合法的。
def语句将创建一个函数并将其赋值给一个变量名:
def <变量名>([参数1,参数2,...]):
<语句>
def语句的首行定义函数名,并引用函数对象,函数名的本质就是函数的内存地址。
参数个数是0或以上数目。
语句里,可以包含return语句,在调用函数时,会返回一个值。当没有return时,默认返回值为None。
函数里,也可以使用yield语句来生成返回值。
因为def是执行语句,因此函数是实时生成的
>>> def hanshu(x,y):
return x*y
>>> hanshu('abc',2)
'abcabc'
>>> hanshu(2,[1,2,3])
[1, 2, 3, 1, 2, 3]
在这个函数里,x*y的结果取决于x和y的对象类型,因为python本身不定义变量,因此传递的值的类型与返回的类型都不一定是固定的类型。
作用域针对的是变量。在使用同一个变量名时,会出现作用域问题。
>>> x=10 #全局变量
>>> def funx():
x=20 #本地变量
print(x)
>>> print(x) #打印的是全局变量
10
>>> funx() #打印的是本地变量
20
>>> x=10
>>> def funx():
print(x)
#本地变量没有定义的话会引用全局的变量
>>> print(x)
10
>>> funx()
10
变量名使用时,查找顺序:
>>> def newdef():
x=20
def newdef2():
print(x)
newdef2()
>>> newdef()
20
>>> x=10
>>> def newdef():
def newdef2():
print(x)
newdef2()
>>> newdef()
10
在函数内,想改变全局变量,可以使用global语句来定义此变量为全局变量。
>>> g='global'
>>> l='global'
>>> def glo():
global g
g='local'
l='local'
>>> g
'global'
>>> l
'global'
>>> glo()
>>> g
'local'
>>> l
'global'
在glo函数里,都重新赋值了g与l,但在函数执行后只有g改变了,当使用global之后,当前函数里所使用的所有对变量g的更改都会对全局变量g进行更改。
除了这个方法,还有引用自己的方法(交互模式里,可以import main)与sys.modules的方法(可以使用引用过的所有模块,交互模式里本身可用main方式)。
>>> x=10
>>> import __main__
>>> __main__.x
10
>>> def glo():
__main__.x+=1
>>> glo()
>>> x
11
>>> s=10
>>> import sys
>>> sys.modules['__main__'].s
10
>>> def glo():
sys.modules['__main__'].s+=1
>>> glo()
>>> s
11
被嵌套函数的作用域就是上级函数,在这里,想调用inner函数,必须是在函数outer里面,不能直接使用。可以使用返回内部函数的方法来提取内部函数:
>>> def outer():
def inner():
print('inner')
inner()
>>> func1=outer()
inner
工厂函数:根据要求的对象,一个能够记住嵌套作用域的变量值的函数。
>>> def printx(x):
def printy(y): #嵌套函数
return x*y #返回x*y的值
return printy #返回嵌套的函数
>>> a=printx(3) #定义x值为3后的嵌套函数赋值
>>> a(2)
6
>>> a(3)
9
nonlocal让内部函数中的变量在上一层及以下层函数中生效(父级级父级以下)
x=1
>>> def func1():
x=2
def func2():
nonlocal x
x=3
return x
func2()
print(x)
>>> func1()
3
>>> x
1
因为x并不是全局变量,所以只有在调用函数时nonlocal语句才会生效,这里x=3,当直接输出x而不调用函数时那么x=1
参数:argement或parameter,对象作为输入值传递给函数的方式。
参数传递时的简要关键点:
传递参数为可变对象与不可变对象时:
不可变对象通过值进行传递——数值、字符串等
可变对象是通过指针进行传递——列表、字典等
>>> a=3
>>> def printa(a):
a=a+1
print(a)
>>> a
3
>>> printa(a)
4
>>> a
3
在这里,b[:]方式会新生成一个列表对象,因此函数里的y与setlist(b[:])是两个不同的对象。这种方法可以避免可变参数的修改。
>>> def setlist(y):
y.append(3)
>>> a=[1,2]
>>> setlist(a[:])
>>> a
[1, 2]
>>> setlist(a)
>>> a
[1, 2, 3]
参数传递是由特定匹配规则的:
传递参数时,要注意顺序:非关键字参数->关键字参数->字典参数
>>> def myfunc(a,b):
print(a,b)
>>> myfunc(1,2)
1 2
>>> myfunc(b=1,a=2)
2 1
语法 | 位置 |
---|---|
func(value) | 调用者 常规参数:通过位置进行匹配 |
func(name=value) | 调用者 关键字参数:通过变量名匹配 |
func(*sequence) | 调用者 迭代传递所有元素 |
func(**dict) | 调用者 以‘键’为关键字,‘值’为相应值的方式传递字典所有元素 |
def func(name) | 函数 常规参数:通过位置或变量名进行匹配 |
def func(name=value) | 函数 默认参数值:如果没有在调用中传递的话 |
def func(*name) | 函数 匹配并收集(在元组中)所有包含位置的参数 |
def func(**name) | 函数 匹配并收集(在字典中)所有包含关键字的参数 |
def func(*arg,name) | 函数 参数必须在调用中按照关键字传递 |
常规参数函数用法:
>>> def myfunc(a,b):
result=a+b
print(result)
>>> myfunc(1,2)
3
关键字参数函数:
>>> def myfunc(a,b):
result=a+b
print(result)
>>> myfunc(b=1,a=3)
4
迭代传递参数用法:
>>> def myfunc(a,b,c):
result=a+b+c
print(result)
>>> myfunc(*[1,2,3])
6
在字典中匹配所有参数用法:
>>> def myfunc(a,b,c):
result=a+b+c
print(result)
>>> myfunc(**{'a':1,'b':2,'c':3})
6
>>> myfunc(1,**{'b':2,'c':3})
6
默认参数函数用法:
>>> def myfunc(a,b=3):
print(a+b)
#当有默认参数存在时,可以只传入其他的参数
>>> myfunc(3)
6
>>> myfunc(3,2)
5
可变参数函数用法:
可变参数,可以传递任意个参数
*args方式是把所有常规参数调用与迭代调用放进一个元组里:
>>> def myfunc(*a):
result=''.join(a)
print (result)
>>> myfunc('1,','2,','3')
1,2,3
>>> myfunc('first,',*['second,','third'])
first,second,third
**args方法是把任意个关键字参数与字典调用方式存放在变量名为args的字典里
>>> def myfunc(**a):
print(a)
>>> myfunc(a='1',b='2')
{'a': '1', 'b': '2'}
>>> myfunc(a='1',b='2',**{'c':'3'})
{'a': '1', 'b': '2', 'c': '3'}
必须使用关键字传递的方法:
函数里的参数:
常规——有/无默认值
*args——存放在列表
*args——存放在字典
在python3开始,在args与args中间可以加入一个“必须使用关键字传递的参数”
使用方法为是0个或多个常规参数+或args+“必须使用关键字传递的参数”+0个或1个args。
>>> def myfunc(*,b,**c):
print(b,c)
>>> myfunc(**{'b':4})
4 {}
>>> def myfun(*a,b,**c):
print(a,b,c)
>>> myfun(2,**{'b':4,'c':5})
(2,) 4 {'c': 5}
特殊参数的传递:
在python里,函数也是对象,函数名也是变量名,因此函数本身也可以传递。
计算最大、最小值的函数时,一般用法:
#这是一个求最小值的函数
>>> def min1(*a):
reg=a[0]
for i in a[1:]:
if i <reg:
reg=i
print(reg)
>>> min1(2,3,5,1,6,8)
1
#这里将最大和最小值的函数作为参数传入到求最大和最小值的函数里
>>> def lessthan(x,y):
return x<y
>>> def morethan(x,y):
return x>y
>>> def minmax(test,*args):
res=args[0]
for i in args[1:]:
if test(i,res):
res=i
print(res)
>>> minmax(lessthan,2,3,5,1,6)
1
>>> minmax(morethan,2,3,5,1,6)
6
>>> def mysum(s):
if not s:
return 0
else:
return s[0]+mysum(s[1:])
#或
>>> def mysum(s):
return 0 if not s else s[0]+mysum(s[1:])
>>> mysum([1,2,3,4])
10
嵌套列表里面的值相加
>>> li=[1,2,[3,4,5],6,[7,[8,9],10]]
>>> def sumlist(a):
sum=0
for i in a:
if not isinstance(i,list): #判断遍历的i是否是列表
sum += i
else:
sum += sumlist(i)
return sum
>>> sumlist(li)
55
在python里函数也是以对象的形态出现。函数名也是以变量名形式存放。因此函数也可以跨模块,以参数传递等形式。函数对象也能调用根本无关的操作:属性存储与注释。
间接函数调用:
>>> def func(x):
print(x)
>>> func2=func
>>> func2(2)
2
把函数放进列表或元组里:
>>> def myfunc(func_name,arg1):
func_name(arg1)
>>> def func_name(arg1):
print (arg1)
>>> li=[(func_name,1),(func_name,2),(func_name,3)]
>>> for i in li:
myfunc(i[0],i[1])
1
2
3
lambda会生成函数对象,但不赋值给任何变量。
lambda表达式:
lambda [<arg1>
][,<arg2>
][,<arg3>
]....:expression using args
参数不是必须的,但没有参数就没有相对意义。
lambda简单说明:
lambda是一个表达式,而不是一个语句,也不是一个的代码块。——生成一个对象。
>>> myfunc=lambda a:a*2
>>> myfunc(4)
8
>>> (lambda a,b:a*b)(5,4)
20
当我们把函数对象放进列表里等操作的时候,使用def感觉很臃肿,这时可以使用lambda来简化过程。
>>> funclist=[lambda x: x**2,
lambda x: x**3,
lambda x: x**4]
>>> funclist[0](2)
4
>>> funclist[1](3)
27
使列表中的每个值都加10
>>> l=[1,2,3,4]
>>> list(map(lambda x: x+10,l))
[11, 12, 13, 14]
filter与map相似,但是针对返回的bool结果判断,结果为真,保留元素;结果为假,弃用元素。结果也是保存在可迭代对象里:
>>> list(filter(lambda x: x>1,[-1,0,1,2,3,4,5]))
[2, 3, 4, 5]
reduce函数是在functools模块里的,因此我们需要导入这个函数。
这个方法是第一次从可迭代对象里提取两个元素当作函数的参数传入,按前面的函数进行运算,保存返回值,当可迭代对象里还有元素的时候,之前的返回值为第一个参数,可迭代对象里取下一个继续运算,知道可迭代对象空。最后返回函数的返回值。
>>> from functools import reduce
>>> reduce(lambda x,y: x+y,[1,2,3,4])
10
>>> reduce(lambda x,y:x if x>y else y,[3,5,2,6,7,4,1,9])
9
欢迎各×××陈师傅”
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。