定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可
特性:
1.减少重复代码
2.使程序变的可扩展
3.使程序变得易维护
函数参数
形参变量
只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量
实参
可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值
def calc(x,y): # x,y 是形参,用来接受参数 res = x*y return res t = calc(2,3) # 2,3 是实参,实际传入的参数, print(t)
默认参数
def staff(name,age,skill,year=2018): #默认参数一般放到实参后面 print('staff info'.center(20,'-')) print("name:",name) print("age:",age) print("skill:",skill) print("year:",year) staff("lemi",22,"python_devops")
关键参数
正常情况下,给函数传参数要按顺序,不想按顺序就可以用关键参数,只需指定参数名即可(指定了参数名的参数就叫关键参数),但记住一个要求就是,关键参数必须放在位置参数(以位置顺序确定对应关系的参数)之后
def staff(name,age,skill,year=2018): print('staff info'.center(20,'-')) print("name:",name) print("age:",age) print("skill:",skill) print("year:",year) staff("lemi",skill="python_devops",22) # 不可以 staff("kevin",skill="linux",age=22) #可以这样 staff("walk",25,"linux",age=22) #不可以,相当于两次赋值 # 总结:不想按位置参数,一一对应的去传值, # 就使用关键参数(参数名=值),但得只能在位置参数后面, # 相当于,你不想排队一个个进,想按名进去, # 那你就只能等到前面排队的进完再进,不然混乱(报错)
非固定参数
若你的函数在定义时不确定用户想传入多少个参数,就可以使用非固定参数
# *args 会把多传入的参数变成一个元组形式(args也可以其他形式命名,相当于形参)
# args,如果没传值,就为空 ()
def staff(name,age,*args): print(name,age,args) staff('lemi',22,'python','CQ') # 输出 # lemi 22 ('python', 'CQ')
当*args在其他形参前面时会截胡,传递参数时,他后面的参数用关键参数可以解决
def staff(name,*args,age):
pass
staff(‘lemi’,’python’,’linux’,age=22)
staff(‘lemi’,*[‘python’,’linux’],age=22)
解包,传给形参args
# *kwargs 会把多传入的参数(key-value型)变成一个dict形式{}
# kwargs,如果没传值,就为空 {}
def staff(name,age,*args,**kwargs): print(name,age,args,kwargs) staff('lemi',22,'linux','web',skill='python',place='CQ') # 输出 #lemi 22 ('linux', 'web') {'skill': 'python', 'place': 'CQ'} staff('lemi',22,'linux','web',**{’skill’:'python',’place’:'CQ'}) 效果跟上面一样
返回值
函数外部的代码要想获取函数的执行结果,就可以在函数里用return语句把结果返回
def staff(name,age,skill,year=2018): print('staff info'.center(20,'-')) print("name:",name) print("age:",age) print("skill:",skill) print("year:",year) if age>22: return False else: return True interview = staff("lemi",22,"python_devops") if interview: print(interview) print('面试成功') else: print('have to improve') output: -----staff info----- name: lemi age: 22 skill: python_devops year: 2018 面试成功 True
注意
函数在执行过程中只要遇到return语句,就会停止执行并返回结果,也可以理解为 return 语句代表着函数的结束
如果未在函数中指定return,那这个函数的返回值为None
函数,只能返回一个值
全局与局部变量
status = 'poor man' def work(status): print('before learn python:',status) status = 'Charming male' print('after change:',status) work(status) print('看看外面status改变了吗?',status) output: before learn python: poor man after change: Charming male 看看status改变了吗? poor man 不用传name 值到函数里,也可以在函数里调用外面的变量 # 局部函数可以调用全局变量,但是不能修改 status = 'poor man' def work(): status = 'Charming male' print('after change:',status) work() print('看看外面status改变了吗?',status) output: after change: Charming male 看看外面status改变了吗? poor man
1.在函数中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。
2.全局变量作用域是整个程序,局部变量作用域是定义该变量的函数。
3.当全局变量与局部变量同名时,在定义局部变量的函数内,局部变量起作用;在其它地方全局变量起作用。
修改全局变量
status = 'poor man' def work(): global status status = 'Charming male' print('after change:',status) work() print('看看外面status改变了吗?',status) output after change: Charming male 看看外面status改变了吗? Charming male
global status的作用就是要在函数里声明status是全局变量,最上面的status='poor man'即使不写,程序最后面的print也可以打印status
变量是列表时, 当修改的是列表时,可以删除元素,修改元素 skill = ['linux','python','html'] def change_skill(): skill = ['linux','python'] print(skill) #此处不能修改 change_skill() print(skill) ['linux', 'python'] ['linux', 'python', 'html'] ------------------ skill = ['linux','python','html'] def change_skill(): skill[2] = 'hadoop' skill.remove('linux') print('inside',skill) #这里可以该,改的是元素,并不是列表对象 #因为在内存里,列表对象整体是一个地址,元素又是另一个地址 change_skill() print('outside',skill) inside ['python', 'hadoop'] outside ['python', 'hadoop']
作用域
作用域(scope),程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
python中函数就是一个作用域,局部变量放置在其作用域中。
代码定义完,作用域已经生成,无论在任何地方调用,作用域链向上查找
age = 21 def func1(): age = 22 def func2(): print(age) return func2 val = func1() print(val) val() output <function func1.<locals>.func2 at 0x000002AB58965BF8> 22
嵌套函数
name = 'bird kevin' def work(): name = 'common staff' def work_1(): name = 'outstanding staff' print('level 3',name) work_1() print('level 2',name) work() print('level now',name) OUTPUT level 3 outstanding staff level 2 common staff level now bird kevin # 最外层不能调用work_1()里层函数 #小游戏 age = 19 def func1(): global age def func2(): print(age) age = 73 func2() func1() print(age) #output>>> 73 73 age = 19 def func1(): def func2(): print(age) func2() age = 73 func1() print(age) #会报错,不知道找哪一个
匿名函数
匿名函数就是不需要显式的指定函数名
#a = lambda x,y:x*y print(a(1,2)) lambda 不能有复杂的逻辑。可以三元运算 res = map(lambda x:x**2,[1,5,7,4,8]) for i in res: print(i) 输出 1 25 49 16 64 节省代码
高阶函数
变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
def add(x,y,f): return f(x) + f(y) res = add(3,-6,abs) print(res)
只需满足以下任意一个条件,即是高阶函数
1.接受一个或多个函数作为输入
2.return 返回另外一个函数
递归
在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数
def fac(n): if n == 1: return 1 else: return n *fac(n-1) print(fac(3)) def calc(n): v = int(n/2) print(v) if v > 0: calc(v) print(n) calc(10) output 5 2 1 0 1 2 5 10 先一层层进去,再往外走
递归特性:
1.必须有一个明确的结束条件
2.每次进入更深一层递归时,问题规模相比上次递归都应有所减少
3.递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)
尾递归,调用下一层的时候就退出了 def cal(n): print(n) return cal(n+1) cal(1) 在python并没有优化
内置函数
>>> min([2,3,4]) #返回数字序列最小值 2 >>> max([2,3,4]) # 返回数字序列最大值 4 >>> help(all) Help on built-in function all in module builtins: all(iterable, /) Return True if bool(x) is True for all values x in the iterable. If the iterable is empty, return True. >>> a = [1,2,3] >>> all(a) True >>> a.append(0) >>> all(a) False >>> a.append([]) >>> all(a) False >>> all([]) True >>>help(any) Help on built-in function any in module builtins: any(iterable, /) Return True if bool(x) is True for any x in the iterable. If the iterable is empty, return False. dir 打印当前下变量 >>> help(hex) Help on built-in function hex in module builtins: hex(number, /) Return the hexadecimal representation of an integer. >>> hex(12648430) '0xc0ffee' >>> 10//3 3 >>> divmod(10,3) (3, 1) >>> sorted([22,31,13,3,14,1,34,3]) [1, 3, 3, 13, 14, 22, 31, 34] >>> d = {} >>> for i in range(20): d[i] = i-2 >>> d {0: -2, 1: -1, 2: 0, 3: 1, 4: 2, 5: 3, 6: 4, 7: 5, 8: 6, 9: 7, 10: 8, 11: 9, 12: 10, 13: 11, 14: 12, 15: 13, 16: 14, 17: 15, 18: 16, 19: 17} >>> sorted(d) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] >>> d.items <built-in method items of dict object at 0x0000023C083AF5E8> >>> d.items() dict_items([(0, -2), (1, -1), (2, 0), (3, 1), (4, 2), (5, 3), (6, 4), (7, 5), (8, 6), (9, 7), (10, 8), (11, 9), (12, 10), (13, 11), (14, 12), (15, 13), (16, 14), (17, 15), (18, 16), (19, 17)]) >>> sorted(d.items(),key) Traceback (most recent call last): File "<pyshell#11>", line 1, in <module> sorted(d.items(),key) NameError: name 'key' is not defined >>> sorted(d.items(),key=lambda x:x[1]) [(0, -2), (1, -1), (2, 0), (3, 1), (4, 2), (5, 3), (6, 4), (7, 5), (8, 6), (9, 7), (10, 8), (11, 9), (12, 10), (13, 11), (14, 12), (15, 13), (16, 14), (17, 15), (18, 16), (19, 17)] >>> sorted(d.items(),key=lambda x:x[1],reverse = True) [(19, 17), (18, 16), (17, 15), (16, 14), (15, 13), (14, 12), (13, 11), (12, 10), (11, 9), (10, 8), (9, 7), (8, 6), (7, 5), (6, 4), (5, 3), (4, 2), (3, 1), (2, 0), (1, -1), (0, -2)] >>> ascii('n') "'n'" >>> ascii('你') "'\u4f60'" >>> oct(10) '0o12' >>> bin(10) '0b1010' >>> help(eval) Help on built-in function eval in module builtins: eval(source, globals=None, locals=None, /) Evaluate the given source in the context of globals and locals. The source may be a string representing a Python expression or a code object as returned by compile(). The globals must be a dictionary and locals can be any mapping, defaulting to the current globals and locals. If only globals is given, locals defaults to it. >>> eval('1+7') 8 >>> eval('print('hello world')') SyntaxError: invalid syntax >>> eval('print("hello world")') hello world >>> code = ''' if 5 > 4: print('ok') else: print('fail')''' >>> eval(code) Traceback (most recent call last): File "<pyshell#27>", line 1, in <module> eval(code) File "<string>", line 2 if 5 > 4: ^ SyntaxError: invalid syntax >>> 只能处理简单单行代码 Traceback (most recent call last): File "<pyshell#28>", line 1, in <module> 只能处理简单单行代码 NameError: name '只能处理简单单行代码' is not defined >>> exec(code) ok >>> help(exec) Help on built-in function exec in module builtins: exec(source, globals=None, locals=None, /) Execute the given source in the context of globals and locals. The source may be a string representing one or more Python statements or a code object as returned by compile(). The globals must be a dictionary and locals can be any mapping, defaulting to the current globals and locals. If only globals is given, locals defaults to it. >>> res = eval('1+3+4') >>> res1 = exec('1+3+4') >>> print('res',res,res1) res 8 None >>> exec可以执行多行但拿不到返回值 KeyboardInterrupt >>> eval执行单行可以拿到返回值 KeyboardInterrupt >>> ord('a') 97 >>> chr('98') Traceback (most recent call last): File "<pyshell#35>", line 1, in <module> chr('98') TypeError: an integer is required (got type str) >>> chr(98) 'b' >>> s = '元贞' >>> s[0] '元' >>> s.encode('utf-8') b'xe5x85x83xe8xb4x9e' >>> s1 = bytearray(s) Traceback (most recent call last): File "<pyshell#40>", line 1, in <module> s1 = bytearray(s) TypeError: string argument without an encoding >>> s1 = bytearray(s.encode (utf-8)) Traceback (most recent call last): File "<pyshell#41>", line 1, in <module> s1 = bytearray(s.encode (utf-8)) NameError: name 'utf' is not defined >>> s1 = bytearray(s.encode ('utf-8')) >>> s1[0] = 'a' Traceback (most recent call last): File "<pyshell#43>", line 1, in <module> s1[0] = 'a' TypeError: an integer is required >>> s1[0] = 65 >>> s '元贞' >>> s1 bytearray(b'Ax85x83xe8xb4x9e') >>> s1[4] 180 >>> id(s[0]) 2456860022384 >>> 源地址修改 KeyboardInterrupt >>> map(lambda x:x*x,[1,2,3]) <map object at 0x0000023C0842C908> >>> list(map(lambda x:x*x,[1,2,3])) [1, 4, 9] >>> list(map(lambda x:x<3,[1,2,3])) [True, True, False] >>> list(filter(lambda x:x<3,[1,2,3])) [1, 2] >>> import functools >>> functools.reduce <built-in function reduce> >>> bytes('34') Traceback (most recent call last): File "<pyshell#55>", line 1, in <module> bytes('34') TypeError: string argument without an encoding >>> bytes('34) SyntaxError: EOL while scanning string literal >>> bytes(34) b'x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00' >>> bytes('你好') Traceback (most recent call last): File "<pyshell#58>", line 1, in <module> bytes('你好') TypeError: string argument without an encoding >>> bytes(你好) Traceback (most recent call last): File "<pyshell#59>", line 1, in <module> bytes(你好) NameError: name '你好' is not defined >>> print('python','linux',sep='->') python->linux >>> print('python','linux',end='->') python linux-> >>> print('python','linux') python linux >>> print('python','linux',end='') python linux >>> msg = 'linux is lady ' f = open('skill.txt','w') print(msg,'python is yong woman',sep='|',end="",file=f) print(msg,'python is yong woman',sep='|',end="",file=f) >>> def f(): pass >>> a = [1,2,3] >>> callable(f) True >>> callable(a) False >>> s = {1,2,3,4} >>> s.discard(2) >>> s {1, 3, 4} >>> s = frozenset(s) >>> s frozenset({1, 3, 4}) >>> >>> >>> s.discard(3) Traceback (most recent call last): File "<pyshell#77>", line 1, in <module> s.discard(3) AttributeError: 'frozenset' object has no attribute 'discard' >>> s.remove(2) Traceback (most recent call last): File "<pyshell#78>", line 1, in <module> s.remove(2) AttributeError: 'frozenset' object has no attribute 'remove' 打印变量名和对应的值 >>> vars() {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'd': {0: -2, 1: -1, 2: 0, 3: 1, 4: 2, 5: 3, 6: 4, 7: 5, 8: 6, 9: 7, 10: 8, 11: 9, 12: 10, 13: 11, 14: 12, 15: 13, 16: 14, 17: 15, 18: 16, 19: 17}, 'i': 19, 'code': " if 5 > 4: print('ok') else: print('fail')", 'res': 8, 'res1': None, 's': frozenset({1, 3, 4}), 's1': bytearray(b'Ax85x83xe8xb4x9e'), 'functools': <module 'functools' from 'C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\functools.py'>, 'f': <function f at 0x0000023C08464400>, 'a': [1, 2, 3]} >>> def f(): n = 3 print(locals()) >>> f() {'n': 3} >>> globals() {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'd': {0: -2, 1: -1, 2: 0, 3: 1, 4: 2, 5: 3, 6: 4, 7: 5, 8: 6, 9: 7, 10: 8, 11: 9, 12: 10, 13: 11, 14: 12, 15: 13, 16: 14, 17: 15, 18: 16, 19: 17}, 'i': 19, 'code': " if 5 > 4: print('ok') else: print('fail')", 'res': 8, 'res1': None, 's': frozenset({1, 3, 4}), 's1': bytearray(b'Ax85x83xe8xb4x9e'), 'functools': <module 'functools' from 'C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\functools.py'>, 'f': <function f at 0x0000023C084646A8>, 'a': [1, 2, 3]} >>> >>> a [1, 2, 3] >>> repr(a) '[1, 2, 3]' >>> a [1, 2, 3] >>> b = [6,7,8] >>> zip(a,b)() Traceback (most recent call last): File "<pyshell#96>", line 1, in <module> zip(a,b)() TypeError: 'zip' object is not callable >>> list(zip(a,b)) [(1, 6), (2, 7), (3, 8)] >>>