本篇内容
-
函数基本语法及特性
-
嵌套函数
-
递归函数
-
匿名函数
- 高阶函数
-
内置函数
1.函数的基本语法及特性
1.1 函数概念
函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数。
定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可
特性:
-
减少重复代码
-
使程序变的可扩展
-
使程序变得易维护
1.2 函数的定义
你可以定义一个由自己想要功能的函数,以下是简单的规则:
- 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()。
- 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
- 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
- 函数内容以冒号起始,并且缩进。
- return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。
语法:
Python 定义函数使用 def 关键字,一般格式如下:
def 函数名(参数列表): 函数体
例1:
通过调用函数名,执行函数:
def sayHi(): print("hello word!")sayHi() # 输出 hello word!
例2:
输出前n个数的偶数和,需要用户给函数传递一个参数。
def sum(num): a=0 for i in range(num): a += i+1 if (i+1)%2 == 0 else 0 return aprint(sum(100)) # 输出 # 2550
函数调用:
定义一个函数:给了函数一个名称,指定了函数里包含的参数,和代码块结构。
这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从 Python 命令提示符执行。
如下实例调用了 prinmsg() 函数:
#!/usr/bin/env python# -*- coding:utf-8 -*-# 定义函数def printmsg(msg): ''' 打印传入的字符串 ''' print(msg) return# 调用函数printmsg("hello world!")printmsg("hello,40kuai!")
# 输出 hello world!hello,40kuai!
1.3 参数
1.3.1 实参和形参
形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量。
实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值
1.3.2 参数类型
以下是调用函数时可使用的正式参数类型:
- 必需参数
- 关键字参数
- 默认参数
- 不定长参数
必需参数
必需参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。
调用printmsg()函数,你必须传入一个参数,不然会出现语法错误:
#!/usr/bin/env python# -*- coding:utf-8 -*-def printmsg(msg): ''' 打印传入的字符串 ''' print(msg) returnprintmsg()
# 输出 Traceback (most recent call last): File "C:/Users/helei/PycharmProjects/S16/day3/test.py", line 10, inprintmsg()TypeError: printmsg() missing 1 required positional argument: 'msg'
关键参数
关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。
使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。
以下实例在函数 printmsg() 调用时使用参数名
正常情况下,给函数传参数要按顺序,不想按顺序就可以用关键参数,只需指定参数名即可
def printmsg(msg,num): ''' 打印传入的字符串 ''' print(msg) print(num) return printmsg(num=12,msg="hello world")
# 输出hello world!12 # 不按顺序传入关键参数不影响输出结果。
但记住一个要求就是,关键参数必须放在位置参数之后。
# 如果关键参数在位置参数之前 def printmsg(msg,num): ''' 打印传入的字符串 ''' print(msg) print(num) returnstring="hello world!"printmsg(num=12,string)
#输出如下报错信息 File "C:/Users/helei/PycharmProjects/S16/day3/test.py", line 12 printmsg(num=12,string) ^SyntaxError: positional argument follows keyword argument
正确的应该为:
def printmsg(msg,num): ''' 打印传入的字符串 ''' print(msg) print(num) returnstring="hello world!"printmsg(string,num=12)# 输出hello world!12
默认参数
在定义函数时,可以把函数的参数定义为默认参数,如下
def msg(name,age=22): print('name:',name) print('age:',age)
在调用带有默认参数的函数时,用户可以不给默认参数赋值,当不赋值时,变量使用默认的参数。
msg('40kuai')msg('40kuai',40)# 输出# name: 40kuai# age: 22# name: 40kuai# age: 40
不定长参数
若函数在定义时不确定用户想传入多少个参数,就可以使用非固定参数,先来看下*args的效果
def msg(msg,*args): """ 打印输入的所有字符串 """ print(msg) for i in args: print(i)msg('name',11,22,33,44) # 输出 # name # 11 # 22 # 33 # 44
好像不太直观,那就让你看看args中是什么数据:
def msg(msg,*args): """ 打印输入的所有字符串 """ print(msg) print('args:',args) for i in args: print(i)msg('name',11,22,33,44)# 输出# name# args: (11, 22, 33, 44)# 11# 22# 33# 44
再来看看还有一个**kwargs:
def msg(msg,*args,**kwargs): """ 打印输入的所有字符串 """ print(msg) print('args:',args) print(kwargs) # for i in args: # print(i)msg('name',11,22,33,44,name='40kuai',age=18)# 输出# name# args: (11, 22, 33, 44)# {'name': '40kuai', 'age': 18}
看了这么多总结一下
默认参数放到位置参数的后面
关键字参数放到必需参数的后面
关于*args和**kwargs
*args的作用就是把用户多余输入的(位置)参数,放到args中,以元组的形式。
**kwargs的作用是把用户多余输入的(关键)参数,放到kwargs中 ,以字典的形式保存
1.4 函数的返回值
return [表达式] 的作用有两方面:
1.用于退出函数
2.选择性地向调用方返回一个表达式。
不带参数值的return语句返回None。(0,None,空的返回值为False)
可以返回多个值,以元组形式返回
1.5 变量作用域
Pyhton 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的。
变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。两种最基本的变量作用域如下:
- 全局变量
- 局部变量
定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。
局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。
name = '40kuai'def put(name): print("美男子:",name) name = '还是我' print("美男子:", name)print("美男子:", name)put(name)print("美男子:", name)
输出结果:
美男子: 40kuai美男子: 40kuai美男子: 还是我美男子: 40kuai
2.嵌套函数
哎,我也忘了,先来个代码想想。
string = 'hello world!'def msg(): print("msg") def msg1(st): print(st)msg()# 输出# msg
函数里边套个函数,就是嵌套函数。哈哈哈哈
但是为什么没有输出第二次函数的结果呢,恩~,没调用。再试试
string = 'hello world!'def msg(): print("msg") def msg1(st): print(st)msg()msg1()# 输出# msg# NameError: name 'msg1' is not defined
报错了,想起来了,函数就是相当于变量,定义到函数内部就是局部变量,在全局当然找不到,我真聪明。
string = 'hello world!'def msg(): print("msg") def msg1(st): print(st) msg1("string")msg()# 没毛病
但是就想在外边调用内部函数怎么办。再想想~~
string = 'hello world!'def msg(): print("msg") def msg1(st): print(st) return msg1msg1 = msg()msg1("string")# 就要变身为装饰器了,后面讲
3.递归函数
在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。
date = range(4200000000)count = 0def search(find_num, date, count): mit = int(len(date)/2) num = date[mit] if find_num > num: print('右',count,num) search(find_num, date[mit:],count+1) elif find_num < num: print('左',count,num) search(find_num,date[:mit],count+1) else: print(count,num)search(123456,date,count)
递归特性:
1. 必须有一个明确的结束条件
2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
3. 递归效率不高,递归层次过多会导致栈溢出(最大的递归层数为999层)
4.匿名函数
匿名函数就是不需要显式的指定函数
# 作者 alex#这段代码def calc(n): return n**nprint(calc(10)) #换成匿名函数calc = lambda n:n**nprint(calc(10))
copy:你也许会说,用上这个东西没感觉有毛方便呀, 。。。。呵呵,如果是这么用,确实没毛线改进,不过匿名函数主要是和其它函数搭配使用的呢,如下
res = map(lambda x:x**2,[1,5,7,4,8])for i in res: print(i)
5.高阶函数
变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
def add(x,y,f): return f(x) + f(y) res = add(3,-6,abs)print(res)
6.内置函数
内置函数使用方法,后续补上。。。。有人提醒我吗?