Python函数
函数
函数是一个特定功能的结构,属于代码组的一种
函数的特征
- 函数的定义必须使用def关键字
- 函数的命名规则
- 不允许使用中文,尽量使用英文
- 可以包含数字,但是不能以数字开头
- 不可以使用特殊符号,_除外
- 函数名严格区分大小写
- 函数名不要与关键字冲突
- 函数名要见其名知其意
- 函数不被调用不被执行
函数的定义
定义函数的规则
- def关键字开头 ,后跟一个空格
- 函数名后接括号,括号内可有参数可无参数,括号后接冒号
- 函数内所有代码缩进
- 编写函数文档,可以不写,但是作为一个合格的程序猿,强烈推荐编写
- 编写函数体
- 使用return返回,这个可以不写,Python默认会返回
如下函数
def printName() :
print('定义了一个函数')
print('王小儿')
这需要调用才会执行
函数的参数
参数的分类
- 位置参数
- 定义的时候直接定义变量名,也就是形参名
- 调用的时候直接把变量名与值按位置一一对应放入即可,不传参数是不合法的
- 默认参数
- 形参带有默认值
- 调用的时候如果没有传入值,则使用默认值
- 关键字参数
- 收集参数
位置参数
这种参数也是最普遍的,需要几个参数就定义几个,只定义形参名称,然后调用的时候按对应的形参位置传入值就行了
def hello(name) :
print('{0},你怎么了'.format(name))
def hello2(name,name2):
print(name,name2)
def hello3(name,name2,name3):
print(name,name2,name3)
hello('ya')
hello2('ya','wa')
hello3('ya','wa','aa')
这里切记传参一定要与形参位置对应,且必须传,不能少
默认参数
这里就是形参有默认值
def helloMan(name='王二'):
print('{0},早上好啊'.format(name))
def helloM(n1='w',n2='q'):
print(n1,n2)
helloMan('xiao')
helloM()
这种参数就是参数可传可不传
如果位置参数与默认参数都有的话,切记所有位置参数必须出现在默认参数前,包括函数定义和调用
def print_hello(n1,n2,n3='op'):
print(n1,n2,n3)
print_hello('1','2')
print_hello('1','2','oo')
关键字参数
这种参数在定义方法定义确定形参阶段跟默认参数和位置参数是一样的,只是在调用阶段不一样
调用的时候,以键值对的形式指定参数名和参数值,这样做虽然麻烦,但是不容易出现位置混淆
def helloM(n1,n2='2'):
print(n1,n2)
def helloMe(n1='1',n2='2'):
print(n1,n2)
def print_hello(n1,n2,n3='op'):
print(n1,n2,n3)
helloM('1',n2='2')
helloMe(n1='3')
helloMe(n1='3',n2='2')
print_hello(1,2,n3='4')
//这种就是错误的调用
print_hello(1,n3='4',2)
但是调用的时候一定要注意,有位置参数,位置参数一定要在关键字参数前面;关键字参数之间不存在先后顺序
收集参数
定义函数时,有时候我们不确定调用的时候到底会传递几个参数(不传也可以),此时,可用包裹(packing)位置参数,或者包裹关键字参数,来进行参数传递,会显得非常方便
包裹位置参数
def hello_p(*arg):
print(arg)
print(arg[0])
hello_p(1,2,3)
打印结果
(1, 2, 3)
1
我们传进的所有参数都会被arg变量收集,它会根据传进参数的位置合并为一个元组(tuple),args是元组类型,这就是包裹位置传递
注意:形参名之前添加*
包裹关键字参数
def func(**arg):
print(arg)
func(a=1,b=2)
打印结果
{‘a’: 1, ‘b’: 2}
arg是一个字典(dict),收集所有关键字参数
注意:形参名之前添加**
参数混合使用
基本原则是:先位置参数,默认参数,包裹位置参数,关键字参数,包裹关键字参数(定义和调用都应遵循)
def func(name, age, sex=1, *args, wife='ya',**kargs):
print(name,age,sex,args,wife,kargs)
func('ming',22,0,11,2,1,3,wife='ai',h=175,w=70)
打印结果
ming 22 0 (11, 2, 1, 3) ai {‘h’: 175, ‘w’: 70}
函数的返回值
Python中也是使用return这个关键字作为函数的返回的,但是这里的函数不像Java或者其它语言,需要在定义函数的时候在方法名前面定义好返回值类型;Python中直接像上面那样定义方法,然后需要返回就直接return就行了
def helloMen(persion):
return '{0},你怎么不理我啊{1}'.format(persion,persion)
注意:这里如果我们没有return,那这里的result是None,也就是说函数中没有return的话,也会返回一个值,只不过是None
变量作用域
在函数中声明变量的有效使用范围就是函数的变量作用域
分类
- 全局变量:在函数外声明的变量就是全局变量,作用域是整个程序
- 局部变量:在函数内部声明的变量就是局部变量,作用域是函数内
注意:如果全局变量和局部变量同名时,在定义局部变量的函数内,局部变量有效,其余地方全局变量有效
name = 'xiao wamg' # 全局变量
def funcname():
value = 'this' # 局部变量
name = 'lao er' # 局部变量
print('name:',name)
我们来调用下
funcname()
看看结果
name: lao er
global关键字
这个关键字干嘛的呢,其实看这个单词的意思应该知道了,它是将局部变量变成全局变量
def pri():
print(na)
def name():
global na # 升级成全局变量
na = 'wang er'
print('我定义了一个全局变量')
可以看到在第二个方法中定义了一个变量,但是前面加了一个global修饰,注意,python中有关键字修饰的变量一定要先定义,再赋值,千万别global na = ‘wang er’ 这种写法
接下来调用
name()
pri()
打印结果
我定义了一个全局变量
wang er
这里可以看到第一个方法也能用到这个变量了
注意:虽然这样做可以,但是要记住方法只有调用了才会执行,也就是说第一个方法要能用这个变量,前提是第二个方法要先调用,让这个变量生效
查看函数文档
比我我们想查看print函数的官方解释,也就是函数文档了,怎么办呢,如下
help(print)
就是使用help函数,然后把函数名作为参数传进去
看看打印出来的结果
Help on built-in function print in module builtins:
print(...)
print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file: a file-like object (stream); defaults to the current sys.stdout.
sep: string inserted between values, default a space.
end: string appended after the last value, default a newline.
flush: whether to forcibly flush the stream.
我们重点看第三局
print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
第一个value也就是我们传的参数,
后面的…就是表示可以传多个参数,
再后面的sep=’ ‘,看下面的解释,说处于两个参数之前的string,也就是以这个分割多个参数,默认是空格
再后面的end=’\n’,也就是以什么结束,默认是\n,这个转义字符,意思就是换行;多个参数并不会在同一行打印出来
我们接下来用一个九九乘法表举例
for row in range(1,10):
for col in range(1,row+1):
if col == 1 :
print('第{0}行'.format(row),col * row,sep=' ',end=' ')
else :
print(col * row,end=' ')
print('----')
看看执行结果
自定义函数文档
假如我们要对自己定义的函数写函数文档怎么办呢?
方法:在函数内部开始的第一行使用字符串定义文字内容即可或者使用… …将内容包括起来
内部函数
这个其实就是在函数内部声明的函数就是内部函数,这也是函数嵌套
- 内部函数在函数内部可以访问
- 内部函数的调用必须在定义内部函数之后
- 内部函数不可以在函数外部调用
- 本质上内部函数等同于内部变量
nonlocal关键字
nonlocal的作用是声明当前变量不是当前内部函数中的变量,他有可能是当前函数的外部变量(不是全局变量)
def foo():
name='lhf'
def bar():
nonlocal age #声明当前变量不是内部函数中的变量
print(name)
递归函数
如果一个函数在内部调用自己,那这个函数就是递归函数
- 递归函数必须要有一个明确的结束条件,不能无限递归
- Python中对递归层次有限制,超过限制会报错
- 递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)
在Python中进行递归不像Java或者其它语言,没做限制,能无限递归,顶多把机器搞崩;但是在Python中不行,有递归次数有限制
具体递归什么样呢,看代码
def calc(num):
print(num)
if int(num/2) == 0 :
return num
else :
calc(int(num/2))
接下来调用下
result = calc(8)
看结果
8
4
2
1