Python学习之函数(一)
python中函数定义:函数是逻辑结构化和过程化的一种编程方法。
python中函数定义方法:
def test(x):
"The function definitions"
x+=1
return x
def:定义函数的关键字
test:函数名
():内可定义形参
"":文档描述(非必要,但是强烈建议为你的函数添加描述信息)
x+=1:泛指代码块或程序处理逻辑
return:定义返回值
调用运行:可以带参数也可以不带
函数名()
def test(x): y=2*x+1 return y print(test) ==》<function test at 0x000000BC4F803E18> 函数文件,暂忽略 a=test(3) print(a) ==》7 #注意此处打印a而不是y
补充:
1.编程语言中的函数与数学意义的函数是截然不同的俩个概念,编程语言中的函数是通过一个函数名封装好一串用来完成某一特定功能的逻辑,数学定义的函数就是一个等式,等式在传入因变量值x不同会得到一个结果y,这一点与编程语言中类似(也是传入一个参数,得到一个返回值),不同的是数学意义的函数,传入值相同,得到的结果必然相同且没有任何变量的修改(不修改状态),而编程语言中的函数传入的参数相同返回值可不一定相同且可以修改其他的全局变量值(因为一个函数a的执行可能依赖于另外一个函数b的结果,b可能得到不同结果,那即便是你给a传入相同的参数,那么a得到的结果也肯定不同)
2.函数式编程就是:先定义一个数学函数(数学建模),然后按照这个数学模型用编程语言去实现它。
使用函数的好处:
1.代码重用
2.保持一致性,易维护
3.可扩展性
函数过程:
过程就是简单特殊没有返回值的函数
过程的本质也是一个函数
def test01():
msg = 'hello '
print(msg) ==》hello
def test02():
msg = 'hello GD'
print(msg) ==》hello GD
return msg
t1 = test01()
t2 = test02()
print(t1) ==》None #没有返回值返回None
print(t2) ==》hello GD
总结:当一个函数/过程没有使用return显示的定义返回值时,python解释器会隐式的返回None,
所以在python中即便是过程也可以算作函数。
def test01():
pass
def test02():
return 0
def test03():
return 0, 10, 'hello', ['alex', 'lb'], {'W': 'lb'}
t1 = test01()
t2 = test02()
t3 = test03()
print(t1)
print(t2)
print(t3)
None
0
(0, 10, 'hello', ['alex', 'lb'], {'W': 'lb'})
总结:
返回值数=0:返回None
返回值数=1:返回object
返回值数>1:返回tuple
函数参数:
1.形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量
2.实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值

3.位置参数
def test(x,y,z):
print(x)
print(y)
print(z)
test(1,2,3) #1,2,3就是位置参数,须一一对应,缺一不行多一也不行
test(y=1,x=3,z=4) #关键字参数,无须一一对应,缺一不行多一也不行
#若位置参数与关键字参数混合使用,位置参数必须在关键字参数左边
如:
test(1,y=2,3)#报错
test(1,3,y=2)#报错 (不能同时赋值两次)
test(1,3,z=2)
test(1,3,z=2,y=4)#报错 (多一个参数,须一一对应)
test(z=2,1,3)#报错 (位置参数必须在关键字左边)
4.默认参数:
def handle(x,type='mysql'): #默认参数:type='mysql'
print(x)
print(type)
handle('hello') ==>hello
mysql
handle('hello',type='sqlite') ==>hello
sqlite
handle('hello','sqlite') ==>hello
sqlite
5.参数组 (**字典 *列表 )
def test(x,*args): #处理位置参数可用列表(*args)
print(x,args)
test(1)
test(1,2,3,4,5)
test(1,{'name':'alex'})
test(1,['x','y','z'])
test(1,*['x','y','z'])
test(1,*('x','y','z'))
#结果
1 ()
1 (2, 3, 4, 5)
1 ({'name': 'alex'},) #输出元组形式
1 (['x', 'y', 'z'],)
1 ('x', 'y', 'z')
1 ('x', 'y', 'z')
def test(x,**kwargs): #处理关键字参数可用字典(**kwargs)
print(x,kwargs)
test(1,**{'name':'alex'}) ==》1 {'name': 'alex'}
test(1,1,2,2,2,2,2,y=2,z=3) #报错(Test.()取1个位置参数,但给出7个)
test(1,y=2,z=3,z=3) #会报错 :一个参数不能传两个值
#列表,字典混合使用
def test(x,*args,**kwargs):
print(x)
print(args,args[-1])
print(kwargs,kwargs.get('y'))
test(1,1,2,1,1,11,1,x=1,y=2,z=3) #报错
test(1,1,2,1,1,11,1,y=2,z=3) ==》1
(1, 2, 1, 1, 11, 1) 1
{'y': 2, 'z': 3} 2
test(1,*[1,2,3],**{'y':1}) ==》1
(1, 2, 3) 3
{'y': 1} 1
6,局部变量和全局变量
在子程序中定义的变量称为局部变量,在程序的一开始定义的变量(无缩进的变量)称为全局变量。
全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序。
注:当全局变量与局部变量同名时:在定义局部变量的子程序内,局部变量起作用;在其它地方全局变量起作用。
name='rxj' #定义全局变量
def change_name():
print('我的名字',name)
change_name() ==》我的名字 rxj
name='rxj' #全局变量
def change_name():
name='hello' #局部变量(此时局部变量只作用于内部代码块)
print('我的名字',name)
change_name() ==》我的名字 hello
print(name) ==》rxj
def change_name():
global name #global name代表定义全局变量
name='rxj'
print('我的名字',name)
change_name() ==》我的名字 rxj
print(name) ==》rxj
补充:
如果函数的内容无global关键字,优先读取局部变量;能读取全局变量,无法对全局变量重新赋值,但是对于可变类型,可以对内部元素进行操作
如果函数的内容有global关键字,变量本质上就是全局的那个变量,可读取可赋值 NAME=“fff”
代码规范: 全局变量变量名大写
————- 局部变量变量名小写
NAME = "哎呀"
def test():
global NAME # 已经声明,NAME就是全局的那个变量
print('啦啦啦', NAME)
NAME = "嘻嘻" # 修改 全局的变量
print('哈哈哈',NAME)
test() ==》啦啦啦 哎呀
哈哈哈 哎呀
# 1.如果函数的内容无global关键字
# -1) 有声明局部变量
NAME = ["嘻嘻","哈哈"]
def test():
NAME = "嗯哼"
print('是不是', NAME)
test() ==》是不是 嗯哼
# -2) 无声明局部变量
NAME = ["嘻嘻","哈哈"]
def test():
NAME.append('asdf')
print('是不是', NAME)
test() ==>是不是 ['嘻嘻', '哈哈', 'asdf']
# 2.如果函数的内容有global关键字
# - 1)有声明局部变量
NAME = ["嘻嘻", "哈哈"]
def test():
global NAME
NAME = "嘻嘻"
print('是不是', NAME)
test() ==>是不是 嘻嘻
# - 2)无声明局部变量
NAME = ["嘻嘻", "哈哈"]
def test():
global NAME
NAME = ["呵呵"]
NAME.append('asdf')
print('是不是', NAME)
test() ==>是不是 ['呵呵', 'asdf']
*函数可以嵌套多层
#函数可以嵌套多层
NAME = '海风' 1
def huangwei():
name = "黄伟" 3
print(name) 4
def liuyang():
name = "刘洋" 6
print(name) 7
def nulige():
name = '沪指花' 10
print(name) 11
print(name) 8
nulige() 9
liuyang() 5
print(name) 12
huangwei() 2
输出结果:
黄伟
刘洋
刘洋
沪指花
黄伟
#nonlocal,可指定上一级变量
name = "嘻哈"
def test():
name = "good"
def test():
nonlocal name # nonlocal,指定上一级变量,如果没有就继续往上直到找到为止
name = "nice"
test()
print(name)
print(name)
test()
输出结果:
嘻哈
nice
7.前向引用
#风湿理论之函数即变量
1.def foo():
print('from foo')
bar()
foo() #报错,NameError: name 'bar' is not defined
2.def bar():
print('from bar')
def foo():
print('from foo')
bar()
foo() ==》from foo
from bar
3.def foo():
print('from foo')
bar()
def bar():
print('from bar')
foo() ==》from foo
from bar
4.def foo():
print('from foo')
bar()
foo() #报错,NameError: name 'bar' is not defined
8.递归函数
定义:在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。
def calc(n):
print(n)
if int(n/2) ==0:
return n
return calc(int(n/2))
calc(10)
输出:
10
5
2
1
递归特性:
1. 必须有一个明确的结束条件
2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)

浙公网安备 33010602011771号