0
点赞
收藏
分享

微信扫一扫

Python程序设计基础第五章笔记

RJ_Hwang 2022-04-14 阅读 79
python

Python程序色设计基础第五章

文章目录


5.1 函数定义与使用

5.1.1 基本语法

基本语法:
-----def 函数名([参数列表]):
-----‘’‘ 注释 ’‘’
----------函数体

一定要严格保持缩进。
可以使用内置函数 help() 来查看注释。
函数的返回值和 return 的值数据类型相同。
无论 return 语句出现在函数的什么位置,一旦得到执行,直接结束函数的执行。若果函数没有 return 语句,或者又 return 语句但是没有得到执行,或者执行了不返回任何值的 return 语句,解释器都会认为该函数以 return None 结束。

5.1.2 函数嵌套定义、可调用对象与修饰器

函数嵌套定义

在函数 A 的函数体内定义函数 B,函数 A 返回函数 B。

可调用对象

函数属于 python 的可调用对象之一,调用方法为:
调用:变量 = 函数名[(实参)]
使用:变量([实参])

def test1(a,b):
	def func(x):
		return a+b+x
	retrun func      #这里 return func 而没有用 return func([形参])

def test2(a,b):
	def func(x):
		return a+b+x
	retrun func(a)   #func(a) 中的 a 就是 test(a,b) 中的 a
	
a = test1(1,2)
b = test2(1,2)

a(3)  ==>6   
b   ==>4  

test1(2,2)(3)  ==>7
test2(2,2)  ==>6

修饰器

修饰器本质上是一个一函数为参数,返回函数的函数。

5.1.3 函数递归调用

返回本函数(不止是返回函数名,还包括参数,即整个函数的运行),只不过每次返回对参数进行修改,知道参数满足一定的要求,不再返回函数,而是一个确定的值。

5.2 函数参数

5.2.1 位置参数

是一种常用的参数形式,调用函数的实参和形参顺序必须严格一致,数量必须相同。

5.2.2 默认值参数

在函数定义时,为参数设置默认值,在调用函数时是否为此种参数传递实参时可选的,若为默认值参数传递其他实参,位置和数量必须符合。
在函数定义时,一个默认值参数的后面都不能再出现位置参数。
可以用 函数名.–defaule-- 来查看函数当前所有的默认值,返回一个元组。
要尽量避免用可变序列作为函数的默认值参数。

def test(new,old=[]):
    old.append(new)
    return old

test('5',[1,2,3,4])  ==>[1, 2, 3, 4, '5']

test('c',['a','b'])  ==>['a', 'b', 'c']

test('a')  ==>['a']   #第一次使用默认列表参数

test('b')  ==>['a', 'b']   #默认列表变为 ['a']

5.2.3 关键参数

在实参列表中,为形参赋值

def test(a,b,c):
    print(a,b,c)

test(b=1,a=2,c=3)  ==>2 1 3    #如果所有参数都是关键参数,名称对应好即可

test(a=1,2,3)   ==>SyntaxError: positional argument follows keyword argument

test(c=1,2,3)   ==>SyntaxError: positional argument follows keyword argument

test(1,c=3,b=2)  ==>1 2 3   #如果只有部分是关键参数,默认值参数要在前面,后面的关键参数名称对应好

5.2.4 可变长度参数

第一种可变长度参数,将参数保存在元组中,实参形式为位置参数:

def test(*p):
	print(p)

test(1,2,3)  ==>(1,2,3)

第二种可变参数,将参数保存在字典中,实参形式为关键参数:

def test(**p):
	print(p)

test(x=1,y=2,z=3)  ==>{'x': 1, 'y': 2, 'z': 3}
#注意,字典里,键为 str([形参]),例如 1 所对应的键为 'x',即字符串化,在实参列表里是 x

5.2.5 传递参数时的序列解包

可变长度参数是形参长度不确定,由实参长度确定;而传递参数的序列解包是形参长度确定,用这个长度的一个或多个序列来作为实参。
第一种,实参非字典序列:

def test(a,b,c,d):
    print(a,b,c,d)

x=[1,2]
y=['third':3,'forth':4]

test(*x,*y.values())  ==>1 2 3 4

第二种,实参为字典序列:

def test(a,b,c):
    print(a,b,c)

dict1 = {'b':1,'a':2,'c':3}

test(**dict1)  ==>2 1 3   #其中,字典的键一定要和形参名分别相同

当可变长度参数遇到序列解包:

def test(*p):
	print(p)

lst1 = [1,2,3]

test(*lst1)  ==>1 2 3    

def test(**p):
	for i in p.items():
		print(i,end='')  

dict1 = {'x':1,'y':2,'z':3}

test(**dict1)  ==>('x',1) ('y',2) ('z',3)

多种形式的参数的混合使用

在定义函数时,形参列表应以如下形式排列:
位置参数,默认值参数,可变长度参数*,可变长度参数**

再调用函数时,实参列表应以如下形式排列:
位置参数和可变长度参数*,默认值参数,关键参数,可变长度参数*,可变长度参数**
(可变长度参数* 在实参列表中会按位置参数对待,可变长度参数** 在实参列表中按关键参数对待)


def test(a,b,c):
    print(a,b,c)

test(c=2,b=3,1)  ==>SyntaxError: positional argument follows keyword argument
#位置参数不能在关键参数之后

test(**{'b':1,'c':2},*(3,))  ==>SyntaxError: iterable argument unpacking follows keyword argument unpacking     
#序列解包不能在关键参数解包之后

test(c=2,b=3,*(1,))  ==>1 3 2   #序列解包可以在关键参数之后,但在实参中会按位置参数处理

test(*(1,),**{'c':1,'b':2})  ==>1 2 1

5.3 变量作用域

不同作用域的变量名是互不影响的。
若在函数内部定义了一个与函数外变量同名的局部变量,后面的代码都以局部变量的值为准。
若没有定义同名的局部变量,以全局变量的值为准。
可以用 global 变量 在函数内定义一个全局变量,但定义一个全局变量时,只能有定义操作,不能有赋值 global a = 1 是错误的。global a \n a = 1 是正确的。

x=1

def print_x():
    print(x,end = ' ')
    y=x
    print(y)    
print_x()  ==>1 1

def change_x(): 
    x=3
    print(x)     
change_x()  ==>3

def change_x():
	print(x)
	x=3
change_x()  ==>UnboundLocalError: local variable 'x' referenced before assignment
#当在函数内确实要引入局部变量时,要在定义变量之后再使用,即使在函数外面有同名的全局变量

def demo():
    print(x)
    x=x+1
    print(x)
demo(x)  ==>UnboundLocalError: local variable 'x' referenced before assignment
#原理同上,x = x +1 这个表达式中,先计算右边,右边是全局变量,为 1,左边是局部变量,在定义之前
#的 print(x) 的 x 是局部变量 x ,在定义前使用,报错
    
def local_x():
    x=3
print(x)  ==>1  #局部变量不改变外面的值

5.4 lambda 表达式

语法格式:
lambda [形参] : 表达式
相当于函数体只有 return 语句的函数:
def f([形参]):return 表达式

def test(n):
	return n**2
lst1 = [1,2,3]
list(map(lambda x:test(x), lst1))  ==>[1,4,9]  #lambda 中函数的嵌套

r = []
for i in range(3):
	r.append(lambda :i**2)
	
r  ==>[<function __main__.<lambda>()>,
 	   <function __main__.<lambda>()>,
 	   <function __main__.<lambda>()>]  #封装了三个 lambda 函数,返回值为 i**2
 	   
func1 = r[1]
func2 = r[2]
func3 = r[3]
print(func1(),func2(),func3())  ==>4 4 4   
#是因为,r 中的 lambda 表达式是无参函数,返回值是 i**2 ,此时 i 已经在 range(3) 中迭代完成,
#i == 2 ,func1(), func2() ,func3() 的值都是 2**2 == 4

r = []
for i in range(3):
	r.append(lambda n=i:n**2)  #相当于使用了默认值参数
	
r[0]()  ==>0    
r[1]()  ==>1
r[2]()  ==>4
r[0](5)  ==>25

5.5 生成器函数设计要点 略

举报

相关推荐

第五章笔记整理

0 条评论