1. 程式人生 > >函數部分

函數部分

open ins turn value dir index content 最重要的 返回



1、必須有一個明確的結束條件;
2、每次進入一層遞歸時,問題規模相比上次遞歸都應有所減少;
---------------------------------------------------------------------------------------

匿名函數總結:
lambda x,y:x+y #return x+y
max(iter,key=lambda)
min(iter,key=lambda)
sorted(iter,key=lambda)
map(lambda,iter)
reduce(lambda,iter)
filter(lambda,iter)




----------------------------------------------------------------------------------
import time
print(time)--------<module ‘time‘ (built-in)>

類似:m=__import__(‘time‘)
print(m)
m.sleep(3)




filter函數:過濾是TRUE值的內容:

示例:
dic=[{‘name‘:‘geon‘,‘age‘:20},
{‘name‘:‘geon2‘,‘age‘:9000},
{‘name‘:‘geon3‘,‘age‘:1000}
]
過濾大於100的字典
a=filter(lambda d:d[‘age‘]>100,dic)
for i in a:
print(i)








reduce:示例:

python中的reduce內建函數是一個二元操作函數,他用來將一個數據集合(鏈表,元組等)
中的所有數據進行下列操作:用傳給reduce中的函數 func()(必須是一個二元操作函數)
先對集合中的第1,2個數據進行操作,得到的結果再與第三個數據用func()函數運算,
最後得到一個結果。

from functools import reduce

l=list(range(100))
print(l)
reduce(lambda x,y:x+y,l)




---------------------------------------------------------------------------------------

常用函數:sum lambda zip() map


map:示例:

name_l=[‘a‘,‘b‘,‘c‘]
map(lambda x:name+‘sb‘,name_l) <------------map + lambda
<----------map(lambda x:‘x--‘,可叠代對象)

l=[1,2,3,4,7]

原實現: [i**2 for i in l ]
print(x)

map 實現: m=map(lambda i:i**2,l)
FOR i in m:
print(i)
print(list(m))





lambda 函數:
匿名函數
lambda k: salaries[k] <-----------------------
冒號:後面相當於return 內容。
salaries={‘a‘:10,‘b‘:20,‘c‘:30}
f=lambda k:salaries[k]
print(f)
print(f(‘c‘)) --------------給一個 key 返回 key 對應的 value

改寫 字典取最大值:
print(max(salaries,lambda k:salaries[k]))



示例1: 返回字典內最大值的 KEY ,比較 字典內的VALUE: <------------------


dic={‘a‘:10,‘b‘:20,‘c‘:30}


def get_value(k):
return dic[k]

print(max(dic,key=get_value))



lamba K:return(dic[key])

示例2: zip
print(dic.keys(),dic.values())
z=zip(dic.keys(),dic.values()) <----------------------
print([i for i in z])

>>>>>
dict_keys([‘c‘, ‘a‘, ‘b‘]) dict_values([30, 10, 20])
[(‘c‘, 30), (‘a‘, 10), (‘b‘, 20)]




----------------------------------------------------------------------------------------------

聲明式編程:



示例2: 列表嵌套字典

res=(line.split() for line in f)
dec=[{‘name‘:j[0],‘prince‘:j[1],‘count‘:j[2]} for j in res]

以上可改成:

res=[]
with open(‘b.txt‘) as f:
for line in f:
l=line.split()
d={}
d[‘name‘]=l[0]
d[‘prince‘]=l[1]
d[‘count‘]=l[2]
res.append(d)
print(res)


示例1:

f=open(‘b.txt‘)
ms=(float(line.split()[-1])*float(line.split()[-2]) for line in f)
sum(ms)

以上可以用生命式替代

money=[]
with open(‘b.txt‘) as f:
for line in f:
goods=line.split()
res=int(goods[-1])*int(goods[-2])
money.append(res)
# prin
print(sum(money))




sum() 可以plus 可叠代對象; ------------------------------

如:sum([1,2,3,4])
numJ_g=(i for i in range(3))
print(sum(numj_g))



------------------------------------------------------------------------------------

f=open(‘sp‘)
# l1=[i.strip() for i in f]
l1=(i.strip() for i in f) <------------------ 可叠代對象;
print(next(l1))
a=list(l1) <------------- list() 括號可以包含可叠代對象 ,生成列表;


g=l=(‘egg%s‘%i for i in range(100)) 元組 ---生成器;
print(g)
print(next(g))

>>> i=(‘egg %s‘%i for i in range(100) if i<50)
>>> print(i)
<generator object <genexpr> at 0x7ff0e56b7f10>
>>> print(next(i))
egg 0
>>>

-----------------------------------------------------------------------


列表表達式;



go=os.walk(‘/home/zjf‘)
l1=[‘%s/%s‘%(i[0],j) for i in g for j in i[-1]]
print(l1)


i=[‘egg %s‘%i for i in range(100) if i > 50]

l=[1,2,3,4]
s=‘hello‘
l1=[(num,s1) for num in l for s1 in s]
print(l1)


------------------------------------------------------------------------------------


面向過程函數示例:




import os

def init(func):
def wrapper(*args,**kwargs):
res = func(*args,**kwargs) #!!!!!!!!!!!!!!!!!! 忘記加參數
next(res)
return res
return wrapper #!!!!!!!!!!!!!!!!!!!!!!忘記返回wrapper

@init
def search(target):
while True:
dir_name = yield
g = os.walk(dir_name)
for i in g:
for j in i[-1]:
file_path = ‘%s/%s‘%(i[0],j)
target.send(file_path)

@init
def opener(target):
‘打開文件獲取文件句柄‘
while True:
file_path=yield
with open(file_path) as f:
target.send((file_path,f)) #!!!!!!!!!!!!!! 傳2個參數
@init
def cat(target):
‘讀取文件內容‘
while True:
file_path,f=yield #!!!!!!!!!!!!!!!!!!!!!接收2個參數
for line in f:
target.send((file_path,line))
@init
def grep(pattern,target): #!!!!!!!!!!!!!!! 先參數,後函數target
‘過濾行內容有無python‘
while True:
file_path,line=yield
if pattern in line:
target.send(file_path)
@init
def printer():
‘打印文件路徑‘
while True:
file_path=yield
print(file_path)

g=search(opener(cat(grep(‘python‘,printer()))))
g.send(‘/home/zjf/geon‘)








協程函數:
----------------------------------------------------------------------------------

示例:作業: 連續輸入網址打印結果;

from urllib.request import urlopen
def get():
while True:
url=yield
res=urlopen(url).read()
print(res)
e=get()
next(e)
print(e.send(‘http://www.baidu.com‘))
print(e.send(‘http://www.sina.com‘))




----------------------------------------------------------------------------------
協程函數:(使用yield 表達式的生成器)

yield 表達式:
開始的生成器不能使用send,
必須先netx()之後才能使用send()

#e.send與next(e) 的區別:
1、如果函數內yield是表達式形式,那麽必須先next(e)
2、二者共同之處都是可以讓函數在上次暫停的位置繼續運行;
不一樣:send在觸發下一次代碼的執行時,會順便給yield賦值;



示例1、:剛蛋吃包子


def eater(name):
print(‘%s start to eat‘%name)
while True:
food=yield #類比: 去飯館點菜以後等著。 print(‘%s start to eat‘%name)
while True:
food=yield #類比: 去飯館點菜以後等著。
print(‘%s get %s,to start eat‘%(name,food))
print(‘done‘)

e=eater(‘剛蛋‘)
print(e)
print(next(e))
e.send(‘包子‘)
print(‘%s get %s,to start eat‘%(name,food))
print(‘done‘)

e=eater(‘剛蛋‘)
print(e)
print(next(e))
e.send(‘包子‘) #send(self,value) yield = ‘包子‘ send 相當於next()


示例2:
def eater(name):
print(‘%s start to eat‘%name)
foodlist=[]
while True:
food=yield foodlist
print(‘%s get %s,to start eat‘%(name,food))
foodlist.append(food)
print(‘done‘)

e=eater(‘剛蛋‘)
# print(e)
print(next(e))
print(e.send(‘包子‘))



示例3: 跳過 next(e)


def fst(fun):
def wrapper(*args,**kwargs):
# fun(**args)
res=fun(*args,**kwargs)
next(res)
return res
return wrapper



@fst # ester=fst(eater)
def eater(name):
print(‘%s start to eat‘%name)
foodlist=[‘動骨‘]
while True:
food=yield foodlist
# print(‘get %s,to start eat‘%food)
foodlist.append(food)
print(‘done‘)



e=eater(‘剛蛋‘) #wrapper(‘剛帶‘)
# print(next(e))
print(e.send(‘包子‘))
print(e.send(‘包子2‘))
print(e.send(‘包子3‘))
print(e.send(‘包子4‘))
print(e.send(‘包子5‘))
print(e.send(‘包子6‘))









----------------------------------------------------------------------------------
示例2、:tail管道 程序用python編寫; tail |grep ‘error‘
import time
def tail(file_path):
with open(file_path,‘r‘) as f:
f.seek(0,2)
while True:
line=f.readline()
if not line:
time.sleep(0.3)
continue
else:
yield line

def grep2(pattern,lines):
for line in lines:
if pattern in line:
print(line)

#調用
g=tail(‘/tmp/a.txt‘) #帶參數的函數作為 另一個函數的輸入!!!
grep2(‘error‘,g)



示例1、:tail程序用python編寫;


#/usr/bin
import time
def tail(file_path):
with open(file_path,‘r‘) as f:
f.seek(0,2)
while True:
line=f.readline()
if not line:
time.sleep(0.3)
continue
else:
print(line,end=‘‘)


tail(‘/tmp/a.txt‘)



------------------------------------------------------------------------------------------



生成器





與return區別:
生成器就是一個函數,這個函數內包含yield這個關鍵字; <-------------------------!!!!!
return只能返回一次,函數徹底結束;多個yield能返回多次值;
生成器的本質就是叠代器; <----------------------------------!!!!!!!!!!!

可叠代的數據類型: 可以用for循環的 就是可叠代的; <-----------------------!!!!!!!!!!


yield幹了什麽:
1、把函數變成生成器---> 叠代器 g=test() g.__iter() g.__next()
#用RETURN 返回值只能返回一次,而YIELD返回多次
#函數在暫停以及下一次繼續喜下一次運行的狀態是有YIELD保存;
yield功能總結;
1、相當於把__iter__和__next__方法封裝到函數內部
2、與RETURN比,RETUN只能返回一次,而YIELD返回多次;
3、函數暫停已繼續運行的狀態通過yield保存



for i in g:
print(i)

示例:


def a(n):
print(‘cut down:‘)
while n > 0:

yield n
n -=1

g=a(5)

#for i in g:



for i in g:
print(i)

示例:


def a(n):
print(‘cut down:‘)
while n > 0:

yield n
n -=1

g=a(5)

#for i in g:
# print(i)

或者:

while True:
try:
print(next(g))
except StopIteration:
break

--------------------------------------------------------------------------------

def test():
print(‘first‘)
yield 1 #return 1 碰到yield 停止,並返回 1
yield 2
test()
g=gest()
print(isinstance(g,Iterator)) 是否是可叠代對象;
print(next(g)) 觸發對象是函數;


示例:

def scq():
print(‘a‘)
yield 1,2,3,4
print(‘b‘)
yield 2
print(‘c‘)
yield 3

res_sc=scq()
res=next(res_sc)
print(res)
res=next(res_sc)
print(res)
res=next(res_sc)


----------------------------------------------------------------------------------
isinstance(‘ssssss‘,str)
type(‘ssss‘) is str >>>>>>>>> True
可叠代的數據類型: 可以用for循環的 就是可叠代的;
數據類型是叠代器: 只有文件本身是叠代器;

叠代器 (優缺點)


1、 提供了一種不依賴索引取值的方式;這樣就可以遍歷沒有索引的可叠代對象:

如: 字典,集合,文件
2、 叠代器與列表比較,叠代器更省內存;(惰性計算;)
3、 缺點:無法獲取叠代器長度;使用不如列表索引取值靈活;
叠代器一次性取值;

d={‘a‘:1,‘b‘:2,‘c‘:3}
i=iter(d)
while True:
try:

print(next(i))
except StopIteration: # 類似if StopIteration:
break



#可叠代的: 只要對象本身有__iter__()方法,那它就是可叠代的;

d={‘a‘:1,‘b‘:2,‘c‘:3}

i=d.__iter__()
print(i.__next__())

______________________________________________________________________________
把裝飾器內的參數包到函數裏面; @timmer(auth_type=file) 有參裝飾器!


示例:


裝飾器: 最重要的是定義wrapper不能少了return值;!!!!!!!!!!!!!!!!!!



def auth2(auth_type):
def auth(fun):
print(auth_type)
def wrapper(*args,**kwargs):
if auth_type==‘file‘:
name=input(‘username:‘)
password=input(‘password:‘)
if name==‘zhejiangf4‘ and password==‘sb‘:
print(‘auth successful‘)
res=fun(*args,**kwargs)
return res
else:
print(‘auth error‘)
return wrapper
return auth


@auth2(auth_type=‘file‘)
def index():
print(‘welcome to index page !‘)

index()


補充:
@ccchttps://www.baidu.com/
@bbb
@aaa
def fun():
print(‘aaa‘)

fun=ccc(bbb(aaa(fun)))

示例3:
@ccc(‘c‘)
@bbb(‘b‘)
@aaa(‘a‘)
def func():
pass

func=ccc(‘c‘)(bbb(‘b‘)(aaa(‘a‘)(func)))

______________________________________________________________________________
#裝飾器

import time
def timmer(fun):
def wrapper():
start_time=time.time()
func() -------------->index()
stop_time=time.time()
s_time=stop_time-start_time
print(‘pro runs time is %s‘%s_time)
return wrapper

@裝飾器語法 timmer名稱
@timmer #--------> index=timmer(inex)=wrapper !!!!!!!!!!!!註意:是index名字!
def index():
time.sleep(3)
print(‘welcme to old boy‘)

index() index=wrapper -------------------wrapper()

執行過程:----------1、先找到index ---index地址,2、執行 ()


______________________________________________________________________________





閉包:首先必須是內部定義的函數,包含對外部作用域,而非全局作用域名字的引用;

x=1
def f1():
x=2
def f2():
print(x)
return f2 # f2!

f=f1() # --->內部f2
f()
print(f.__closure__) # 閉包有__closure__
print(f.__clousure__[0].cell_contents)

例子2:
x=1
def f1(x):
# x=2
def f2():
print(x)
return f2

f=f1(1000000000)
f()
print(f.__closure__)
print(f.__closure__[0].cell_contents)


[email protected]:~/test$ python3 a.py
1000000000
(<cell at 0x7f9158116468: int object at 0x7f915811e710>,)
1000000000

例子3:
from urllib.request import urlopen

def get(url):
def index():
return urlopen(url).read()
return inex


f=get(‘http://www.baidu.com‘)
print(f.__closure__[0].cell_contents)

# 下載www.baidu頁面




______________________________________________________________________________

功能(def),主邏輯(if ....);---------
函數可以看成變量:函數可以被賦值;可以被當作參數傳遞;


def foo():
print(‘foo‘)

def bar(func):
print(func) #打印 foo 內存地址;
fun() #執行 foo 函數;

bar(foo)




_______________________________________________________________________________

x=1
def foo():
x=1
print(x)

foo()

作用域: 函數內部---->函數外部-----> 內置名稱






_______________________________________________________________________________

參數位置順序: (x,*args,**kwargs)

**kwargs 字典方式; 除位置參數意外剩下的。
eg:
def foo(x,*args,**kwargs):
print(x)
print(args)
print(kwargs)
foo(1,y=1,z=2) y=1,z=2 傳給kwargs


>>> foo(3,‘a‘=2)
File "<stdin>", line 1
SyntaxError: keyword can‘t be an expression



def foo(x,**kwargs):
print(x)
print(kwargs)

foo(1,y=2,a=3,b=4) # **kwagrs實參索引不能加 ‘‘ !!!!!!!!!!!!!!

>>>>>>1
>>>>>>{‘y‘:2,‘a‘:3,‘b‘:4}



__________________________________________________________________________________
*args #args 位置參數;

示例1:
def foo(x,*args):
print(x)
print(args)
foo(1,2,3,4,5,6,‘a‘,‘b‘) *args 實參元組格式必須加 ‘‘
示例2:
def bar(x,y,z): #需要一一對應;(與*(值))
print(x)
print(y)
print(z)
bar(*(1,2,3)) # *(1,2,3) 類似1,2,3 = bar(1,2,3)
多出的以元組的形式給args

sum([1,2,3,4])


tips:
1、位置參數特點: 必須傳值的參數!
2、默認參數必須放在位置參數後面!
3、是參是可變類型 結果會受函數的影響 (編程可控性變差): 不可變類型不會;

def bar(x):
x.append(4)

x=[1,2,3,]
bar(x) # x傳遞的是內存地址;
print(x)
>>>>>[1,2,3,4]



__________________________________________________________________________________
head,*_=[1,2,3,4,5]
>>>head
>>>1 對於元組,序列類型都可以這麽玩;

a,b,c,d,e=[1,2,3,4,5]
a,_,_,_,e=[1,2,3,4,5]
>>>a
>>>1
>>>e
>>>5

x=‘hello‘
x,y,z,x1,x2=‘hello‘
x=‘h‘
y=‘e‘
z=‘l‘
x1=‘l‘
x2=‘9‘

例子1:
def bar(x,y):
return 1,2,3 # 多值return

a,b,c=bar(1,2)

print(a)
print(b)
print(c)

例子2:

def foo(x,y):
print(x)
print(y)

a=100
b=200
foo(a,b) #是參必須是明確的值

例子3:

x=[] #每次改全局的值;
def register(name,name_list=x):
name_list.append(name)

register(‘ASB‘)
register(‘ysb‘)
__________________________________________________________________________________

def bar(x,y):return 1,2,3,4,[1,2],{‘a‘,1}
多值返回,格式為元組;
>>>>(1, 2, 3, 4, [1, 2], {1, ‘a‘})

_______________________________________________
def bar(x,y):
res=x+y
return res

res1=bar(1,2)
res=bar(1,2)*10
bar(bar(1,2),3)



def 函數名(arg1,arg2,arg3):
‘描述信息‘
函數體
return 1 (可以是任意數據類型;)

無參函數一般不需要返回值;



____________________________________________________________________________________

硬盤保存數據--------->(完全讀到內存;) 其實就是覆蓋原來的數據;

with open(‘a.txt‘) as f, open(‘b.txt‘) as f2:
pass

f.seek(0) 光標到開頭,truncate(3) 從開頭截斷到第3個位置;其他丟棄;
truncate(3)

with open(‘a.txt‘,‘w‘) as f:
f.writelines([‘111111111\n‘,‘22222222222\n‘)
f.seek(0)
f.truncate(3)


with open(‘a.txt‘,‘w‘) as f:
f.writelines([‘111111111\n‘,‘22222222222\n‘)
eval() 字符串轉字典,列表;

函數部分