上学期看视频记得,也没学到多少,目前打算一边通过《Python学习手册 第四版》提高核心语法(太厚了 噗),一边学习Python Web开发
然后这里的多任务编程和网络编程是暑假学的
5. 函数
5.1 函数的参数
### 可变对象按引用传递,不可变对象按引用传递
# 避免对可变参数的修改:
L = [1,2]
change(L[:]) #
# 或
def change(l):
l = l[:]
###【默认参数】【必须是不可变对象】
def power(x,n=2):
return x**n
power(2) #=>4
power(2,3) #=>8
###【可变参数】(元祖)
def sum(*nums): #可以传入0到N个参数,函数内部接收到的是tuple
s=0
for x in nums:
s+=x
return s
###【关键字参数】(字典)
def preson(name,age,**kw): #可以传入0个或多个参数
print('name:',name,'age:',age,'other',kw)
person('bin',19,city='zz',job='stu') #=> name:bin age:19 other:{'city':'zz','job':'stu'}
###【元祖字典的】【拆包】
a=(1,2,3)
def func(*args):
print(args)
func(a) # => ((1,2,3),) 没有*当作一个值,有*拆成N个值传入
func(*a) # => (1,2,3) 【拆包,拆成一个一个的值】 字典 传入 **a
5.2 函数式编程
5.2.1 匿名函数
>>> func = lambda x : x*2 #分号前是参数,分号后是表达式,不用return,自动返回后面的值
>>> func(2) #=> 4
###【简单应用,字典排序,匿名函数作实参】
info = [{'name':'bin','age':19},{'name':'jin','age':19},{'son':'sname','age':1}]
info.sort(key=lambda x:x['name'])
print(info)
5.2.2 高阶函数
就是函数名可以作为参数使用
### map(func,seq) 将函数func作用于序列seq的每个元素,并返回一个迭代器
>>> list(map(lambda x:x*2,[1,2,3])) # => [2,4,6]
### reduce(func,seq) 把一个函数作用在一个序列[x1, x2, x3, ...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:
###reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
>>> from functools import reduce
>>> def fn(x, y):
... return x * 10 + y
...
>>> reduce(fn, [1, 3, 5, 7, 9])
13579
###filter(func,seq) filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。
def not_empty(s): #把列表的空字符串去掉
return s and s.strip()
list(filter(not_empty, ['A', '', 'B', None, 'C', ' ']))
# 结果: ['A', 'B', 'C']
###sorted(seq,key=None,reverse=False)
>>> sorted([36, 5, -12, 9, -21])
[-21, -12, 5, 9, 36]
#还可以接收一个key函数来实现自定义的排序,key作用于每一个元素,并按作用后的seq排序
>>> sorted([36, 5, -12, 9, -21], key=abs)
[5, 9, -12, -21, 36]
5.3 作用域
a=1
def aa():
global a #如果没有global a的话,想要在函数中对a这个全局变量修改,仅仅a=0还不够,因为a是个与全局
a=0 #变量相同的局部变量,需要用 global a将他声明为全局变量,然后修改
aa()
print(a) # => 0
##如果列表和字典当作全局变量时,可以不用global,直接在函数内部修改。因为列表字典是可变类型可以直接修改
l=[1,2,3]
def a():
l.append(4)
a()
print(l) #=> [1,2,3,4]
###---------
a=100
def test(a):
a+=a
print(a) #=>200 没用global,函数外a不变
#-----------
a=[100]
def test(b): #b引用a指向的对象,如果对象是可变类型,下面可以修改全局变量,否则的话,重新指向复制的新的对象
b+=b #=> 函数外:a => [100,100],
b=b+b #=> [100]+[100]==>[100,100] 函数外:a => [100]。因为这里右侧新建了一个对象,b作为局部变量重新引用了一个新的对象。
#----对象名搜寻顺序----
#locals -> enclosing function -> globals -> builtins
#局部 闭包的外函数的局部变量 全局 内建
5.4 闭包
闭包就是内部函数引用了外部函数的临时变量,并且外部函数返回了内部函数的引用
def outer(x):
def wrapper(y):
print(x+y)
return wrapper
a = outer(1)#a现在是wrapper指向函数的引用
a(1)#2
a(2)#3
###【闭包无法修改外部函数的局部变量】
def outer():
n = 1
def wrapper():
n -= 1 #error,
n = 2 #相当于新定义了一个局部变量 n = 2
return wrapper
##通过nonlocal修改外部函数局部变量
def outer():
n = 1 #将n定义为列表也可以,解决这个问题
def wrapper():
nonlocal n
n -= 1
print(n)
return wrapper
a = outer()
a()#输出0
###闭包执行完成后,仍然能保持住当前的执行环境
a()#输出-1
a()#输出-2
###【注意事项】
# 当闭包内引用了一个后期会发生变化变量时
# 1.
def outer():
a = 1
def inner():
print(a)
a = 2
return inner
a = outer()
a()#输出了2,因为inner后又修改了
## 2.
def outer():
l = []
for i in range(1,4):
def inner():
return i*i
l.apend(inner)
return l
f1,f2,f3 = outer()
print(f1(),f2(),f3())#9,9,9
#原因就在于返回的函数引用了变量i,但返回的函数并非立刻执行。等到3个函数都返回时,它们所引用的变量i已经变成了3,因此最终结果为9
#[解决:]
def outer():
def f(j):
def inner():
return j*j
return inner
fs = []
for i in range(1, 4):
fs.append(f(i)) # f(i)立刻被执行(是一个数值,而不是函数),因此i的当前值被传入f()
return fs
5.5 装饰器
就是不修改原函数的情况下,添加新的功能
###【装饰器原理】
def w1(func):
def wrapper():
print('这是新加功能')
func()
return wrapper
def f1():
print('---f1---')
f1 = w1(f1)
f1() # 将会添加一个print
### 【使用@】