python3 函數 二
1、函數嵌套
1、1函數嵌套定義 :在一個函數的內部,又定義另外一個函數。
def f1():
x=1
def f2():
print(‘from f2‘)
f2()
f1()
1、2函數的嵌套調用:在調用一個函數的過程中,又調用了其他函數。
def bar():
print(‘from bar‘)
def foo():
print(‘from foo‘)
bar()
foo()
通過函數的嵌套使用,分解成操作減少重復代碼,一次調用。
2、名稱空間與作用域
名稱空間
2、1 名稱空間:存放名字的地方,準確的說名稱空間是存放名字與變量值綁定關系的地方
2、2內置名稱空間:python自帶的名字,在python解釋器啟動時產生,存放一些python內置的名字
2、3全局名稱空間:在執行文件時,存放文件級別定義的名字,Python中頂行寫的。
2、4局部名稱空間:在執行文件的過程中,如果調用了函數,則會產生該函數的名稱空間,用來存放該函數內定義的名字,該名字在函數調用時生效,調用結束後失效
2、5加載順序:內置名稱空間------>全局名稱空間----->局部名稱空間
2、6名字的查找順序:局部名稱空間------>全局名稱空間----->內置名稱空間
作用域,作用的範圍
全局作用域:全局存活,全局有效
局部作用域:局部存活,局部有效
定義在函數內部的變量擁有一個局部作用域,定義在函數外的擁有全局作用域。
局部變量只能在其被聲明的函數內部訪問,而全局變量可以在整個程序範圍內訪問。調用函數時,所有在函數內聲明的變量名稱都將被加入到作用域中。
def f1():
x = 1
y = 2
print(locals())
print(globals())
f1()
print(locals())
print(globals())
print(locals() is globals())
修改全局變量的值
x=1
def f1():
global x
x=2
f1()
print(x)
修改局部變量的值
x = 0
def f1():
x = 1
def f2():
x = 2
def f3():
nonlocal x #改的是函數正上方的值
x = 3
f3()
f2()
f1()
優先掌握:作用域關系,在函數定義時就已經固定 ,於調用位置無關,在調用函數時,必須回到函數原來定義的位置去找作用域關系.
x = 1
def f1():
def f2():
print(x)
return f2 x = 1
def f1():
def f2():
print(x)
return f2
func = f1()
func()
func = f1()
func()
查看作用域:globals(),locals()
global
nonlocal
LEGB 代表名字查找順序: locals -> enclosing function -> globals -> __builtins__
locals 是函數內的名字空間,包括局部變量和形參
enclosing 外部嵌套函數的名字空間(閉包中常見)
globals 全局變量,函數定義所在模塊的名字空間
builtins 內置模塊的名字空間
3、閉包函數
3、1 閉包函數: 定義在函數內部的函數
3、2包含對外部作用域名字的引用,而不是對全局作用域名字的引用,那麽該內部函數就稱為閉包函數
import requests
def deco(url):
def wrapper():
return (requests.get(url).text)
return wrapper
get = deco(‘https://www.baidu.com‘)
print(get())
閉包的意義:返回的函數對象,不僅僅是一個函數對象,在該函數外還包裹了一層作用域,這使得,該函數無論在何處調用,優先使用自己外層包裹的作用域
4、裝飾器
開放封閉原則:對拓展是開放的,對修改是封閉的
裝飾器:裝飾他人的工具,裝飾的目的是為他人添加新功能
裝飾器本身是任意可調用對象,被裝飾的對象本身也可以是任意可調用的對象
裝飾器遵循的原則:1、不修改被裝飾對象的源代碼
2、不修改被調用對象的調用方式
裝飾器的目的:在遵循1和2原則的前提下,為其他函數添加新功能
@裝飾器名:必須寫在被裝飾對象的正上方,且是單獨一行
示例:
import time
def timmer(func):
def wrapper(*args,**kwargs):
start_time=time.time()
res=func(*args,**kwargs)
stop_time=time.time()
print(‘run time is %s‘ %(stop_time-start_time))
return res
return wrapper
@timmer
def foo():
time.sleep(3)
print(‘from foo‘)
foo()
裝飾器語法:
被裝飾函數的正上方,單獨一行
@deco1
@deco2
@deco3
def foo():
pass
foo=deco1(deco2(deco3(foo)))
裝飾器補充:wraps
from functools import wraps
def deco(func):
@wraps(func) #加在最內層函數正上方
def wrapper(*args,**kwargs):
return func(*args,**kwargs)
return wrapper
@deco
def index():
‘‘‘去你妹的‘‘‘
print(‘from index‘)
print(index.__doc__)
5、叠代器
叠代器:是一個重復的過程,每一次重復,都是基於上一次的結果而來。
s=‘hello‘
l=[‘a‘,‘b‘,‘c‘,‘d‘]
t=(‘a‘,‘b‘,‘c‘,‘d‘)
dic={‘name‘:‘egon‘,‘sex‘:‘m‘,"age":18}
set1={1,2,3}
f=open(‘db.txt‘)
叠代器對象本身也是可叠代對象
l=[‘a‘,‘b‘,‘c‘,‘d‘]
dic={‘name‘:‘egon‘,‘sex‘:‘m‘,"age":18}
iter_l=iter(l)
iter_dic=iter(dic)
while True:
try:
k=next(iter_dic)
print(k,dic[k])
except StopIteration:
break
可叠代對象:
1 有__iter__,執行得到仍然是叠代本身
2 有__next__
叠代器對象的優點
1、提供了一種統一的(不依賴於索引的)叠代方式
2、叠代器本身,比起其他數據類型更省內存
叠代器對象的缺點
1、一次性,只能往後走,不能回退,不如索引取值靈活
2、無法預知什麽時候取值結束,即無法預知長度
判斷可叠代對象與叠代器對象
print(isinstance(s,Iterable)) 判斷s數據類型是否是可叠代對象
print(isinstance(s,Iterator)) 只有文件是叠代器對象
6、生成器
生成器:
在函數內部包含yield關鍵字,那麽該函數執行的結果就是生成器(生成器就是叠代器)
def func():
print(‘first‘)
yield 11111111
print(‘second‘)
yield 2222222
print(‘third‘)
yield 33333333
print(‘fourth‘)
g=func()
print(g)
from collections import Iterator
print(isinstance(g,Iterator))
yield的功能:
1 把函數的結果做生叠代器(以一種優雅的方式封裝好__iter__,__next__)
2 函數暫停與再繼續運行的狀態是由yield,保存當前運行狀態。
def func(n):
while True:
yield n
n+=1
g=func(0)
print(next(g))
def my_range(start,stop):
while True:
if start == stop:
raise StopIteration
else:
yield start
start+=1
g=my_range(1,3)
for i in my_range(1,3):
print(i)
yield與return的比較?
相同:都有返回值的功能
不同:return只能返回一次值,而yield可以返回多次值
import time
def tail(filepath):
with open(filepath, ‘r‘) as f:
f.seek(0, 2)
while True:
line = f.readline()
if line:
yield line
else:
time.sleep(0.2)
def grep(pattern,lines):
for line in lines:
if pattern in line:
print(line,end=‘‘)
grep(‘error‘,tail(‘access.log‘))
7、三元表達式,列表推導式,生成器表達式
三元表達式
x=10
res=x if x > 3 else ‘no‘
print(res)
列表解析
l = [‘egg%s‘%i for i in range(10)]
l=[‘egg%s‘ %i for i in range(10) if i >=5]
print(l)
names = [‘alex_sb‘,‘egon‘,‘wupeiqi_sb‘,‘yuanhao_sb‘]
names_new = [name for name in names if name.endswith(‘sb‘)]
print(names_new)
生成器表達式
g = (‘egg%s‘%i for i in range(10)) # 將中括號變成小括號即為生成器表達式
# 叠代器同一時間在內存中只有一個值
print(g)
print(next(g))
print(next(g))
with open(‘a.txt‘,encoding=‘utf-8‘) as f:
g=(len(line) for line in f)
print(max(g))
python3 函數 二