Python学习笔记(三)
主题:函数
关键字:
- 函数、形参与实参、
def
、函数文档- 关键字参数、默认参数、收集(可变)参数
- 返回值、函数与过程
- 作用域
- 内嵌函数、闭包、匿名函数(
lambda
表达式)BIF
:filter()
过滤器、map
映射
1、定义函数: def
函数格式:
>>> def MyFirstFunction():
print("语句")
2、调用函数
直接用函数名+括号
调用机制是往上去寻找。
>>> MyFirstFunction()
语句
3、含有参数的函数调用
>>> def add(num1,num2):
result = num1 + num2
print(result)
>>> add(1,2)
3
4、函数返回值
>>> def add(num1,num2):
return (num1 + num2)
>>> print(add(1,2))
3
5、形式参数和实际参数
- 形参:函数定义过程中出现的参数
def add(num1,num2):
- 实参:函数调用时使用的参数
add(1,2)
6、函数文档
>>> def MyFirstFunction(name):
'函数文档'
# 函数注释
print('传递进来的' + name +'叫实参,因为Ta是具体的参数值')
>>> MyFirstFunction('小甲鱼')
传递进来的小甲鱼叫实参,因为Ta是具体的参数值
- 打印函数文档
>>> MyFirstFunction.__doc__
'函数文档'
#或
>>> help(MyFirstFunction)
Help on function MyFirstFunction in module __main__:
MyFirstFunction(name)
函数文档
doc
前后的下划线分别有两条。
- 一般系统的特殊属性都是用双下划线开始和结尾的。
>>> print.__doc__ "print(value, ..., sep=' ', end='\\n', file=sys.stdout, flush=False)\n\nPrints the values to a stream, or to sys.stdout by default.\nOptional keyword arguments:\nfile: a file-like object (stream); defaults to the current sys.stdout.\nsep: string inserted between values, default a space.\nend: string appended after the last value, default a newline.\nflush: whether to forcibly flush the stream."
>>> help(print) 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.
7、关键字参数
>>> def SaySome(name,words):
print(name + '->' +words)
>>> SaySome('小甲鱼','让编程改变世界!')
小甲鱼->让编程改变世界!
>>> SaySome(words = '让编程改变世界!',name = '小甲鱼')
小甲鱼->让编程改变世界!
- 默认参数
>>> def SaySome(name = '小甲鱼',words = '让编程改变世界!'):
print(name + '->' + words)
>>> SaySome()
小甲鱼->让编程改变世界!
>>> SaySome('Sandy','How are you?')
Sandy->How are you?
默认参数为‘小甲鱼’和‘让编程改变世界!’
在调用时无实参输入则默认输出定义里边的参数,否则按照输入参数输出。
8、收集参数(可变参数)
>>> def test(*params):
print('参数的长度是:',len(params))
print('第二个参数是:',params[1])
>>> test(1,'小甲鱼',3,14,6,7,8)
参数的长度是: 7
第二个参数是: 小甲鱼
若在输入参数中还需要其它类型的参数,需要把它设置为默认参数(exp=8
)
>>> def test(*params,exp): # 也可以在此定义exp=8
print('参数的长度是:',len(params),exp)
print('第二个参数是:',params[1])
>>> test(1,'小甲鱼',3,14,6,7,exp = 8)# 此处'exp=8'改为8
参数的长度是: 6 8 # 结果输出 7 8
第二个参数是: 小甲鱼
9、函数与过程
函数(
function
):有返回值过程(
procedure
):简单、特殊并且没有返回值
- python只有函数,没有过程
>>> def hello(): print("hello fishc!") >>> temp = hello() hello fishc! >>> temp >>> print(temp) None
10、返回值
>>> def back():
return [1,'d','小甲鱼',3.14] # 可以返回多个参数
>>> back()
[1, 'd', '小甲鱼', 3.14] # 返回列表
>>> def back():
return 1,'d','小甲鱼',3.14 # 没有括号
>>> back()
(1, 'd', '小甲鱼', 3.14) # 默认返回元组
11、变量的作用域(可见性)
- 局部变量(
Local Variable
)- 全局变量(
Global Variable
)
例子:
def discount(price,rate):
final_price = price * rate
## old_price = 88 # 这里试图修改全局变量
## print('修改后old_price的值是:',old_price)
return final_price
old_price = float(input('请输入原价:'))
rate = float(input('请输入折扣率:'))
new_price = discount(old_price,rate)
##print('修改后old_price的值是:',old_price)
print('打折后价格:',new_price)
print('打印局部变量final_price的值:',final_price)
运行结果:
============ RESTART: E:/Python/入门练习/5.py ===========
请输入原价:100
请输入折扣率:0.8
打折后价格: 80.0
Traceback (most recent call last):
File "E:/Python/入门练习/5.py", line 12, in <module>
print('打印局部变量final_price的值:',final_price)
NameError: name 'final_price' is not defined
报错的原因是final_price
只是在discount()
函数里边定义了,外边的只有old_price
、rate
和new_price
而全局变量old_price
等可以在discount()
函数里调用:
def discount(price,rate):
final_price = price * rate
print('这里试图打印全局变量old_price的值:',old_price) ####
## print('修改后old_price的值是:',old_price)
return final_price
old_price = float(input('请输入原价:'))
rate = float(input('请输入折扣率:'))
new_price = discount(old_price,rate)
##print('修改后old_price的值是:',old_price)
print('打折后价格:',new_price)
结果:
请输入原价:100
请输入折扣率:0.8
这里试图修改全局变量old_price的值: 100.0
打折后价格: 80.0
且在discount()
函数里对全局变量的修改实质上是创建一个在discount()
里边的局部变量(屏蔽shadowing),只是名字和全局变量一样,但是和全局变量不一样,他们的存储空间不同,全局变量存储于栈里,局部变量存储于其它空间里。
因此,不要在函数内部修改全局变量的值,一般是访问它的值。
简洁例子:
>>> count = 5
>>> def MyFun():
count = 10 # 修改全局变量
print(count)
>>> MyFun()
10
>>> print(count) # 全局变量未发生改变
5
12、内嵌函数和闭包
global
关键字
可以在函数中修改全局变量的值。
例如:
>>> def MyFun():
global count
count = 10
print(count)
>>> MyFun()
10
>>> print(count)
10
- 内嵌函数
在函数内部创建另一个函数
>>> def fun1():
print('fun1正在被调用...')
def fun2():
print('fun2正在被调用...')
fun2() # 调用并打印fun2()函数
>>> fun1()
fun1正在被调用...
fun2正在被调用...
- 注意:内部函数
fun2()
的整个作用域、定义和调用都在fun1()
内
- 闭包
函数式编程,编程范式。
如果在一个内部函数里对外部作用域(但不是在全局作用域)的变量进行引用,内部函数就被称作闭包。(调用的函数和引用的参数都和全局变量无关)
>>> def FunX(x):
def FunY(y):
return x * y
return FunY
>>> i = FunX(8) # x 取 8
>>> i
<function FunX.<locals>.FunY at 0x0436B148>
>>> type(i)
<class 'function'>
其中,FunY(y)
的外部作用域为FunX(x)
整个作用域,return x * y
对FunX(x)
的变量x
进行了引用,所以FunY(y)
为闭包。
>>> i(5) # y 取 5
40
>>> FunX(8)(5)
40
同样,它们也有全局变量和局部变量的关系:
>>> def Fun1():
x= 5
def Fun2():
x *= x
return x
return Fun2() # 试图调用Fun2()修改Fun1()里的x值
>>> Fun1()
UnboundLocalError: local variable 'x' referenced before assignment
修改方法:
>>> def Fun1():
x= [5]
def Fun2():
x[0] *= x[0]
return x[0]
return Fun2()
>>> Fun1()
25
- 因为列表不是存放在栈里,这里的解决方法是把
x
变为列表,使其不在栈中,可以进行修改。
另一种方法:
>>> def Fun1():
x= 5
def Fun2():
nonlocal x
x *= x
return x
return Fun2()
>>> Fun1()
25
- 使用
nolocal
把局部变量改为全局变量
13、lambda
表达式
用于创建匿名函数()
一般获取返回值时,需要定义函数:
>>> def ds(x):
return 2 * x + 1
>>> ds(5)
11
但是较为麻烦,可以创建一个没有名字的函数:
>>> lambda x : 2 * x +1
<function <lambda> at 0x0436B388>
>>> g = lambda x : 2 * x +1
>>> g(5)
11
也可以有多个参数:
>>> g = lambda x,y : x+y
>>> g(3,4)
7
优点:
- 写一些执行脚本时,可以省下定义函数过程,使代码更精简。
- 可以替代一些调用次数少的函数。
- 更易于阅读函数,不需跳转到
def
处的函数定义去查看函数内容与用法。
14、较实用的两个BIF
filter()
过滤器
函数原型:
filter(function or None, iterable);
每一个可迭代数 iterable
作为function
的参数,返回为True
的值筛选出来,组成为一个列表。
>>> list(filter(None,[1,0,True,False]))
[1, True] # True值被返回并形成一个列表,0和False被筛选掉了。
应用:
# 筛选出奇数
>>> def odd(x):
return x % 2 # 偶数无返回值
>>> temp = range(10)
>>> show = filter(odd,temp)
>>> list(show)
[1, 3, 5, 7, 9] # 奇数被筛选出来
一行实现:
>>> list(filter(lambda x : x % 2, range(10)))
[1, 3, 5, 7, 9]
map
映射
函数原型:
map(func, *iterables);
返回所有iterables
在func
里面的值组成的列表。
>>> list(map(lambda x : x * 2,range(10)))
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]