目錄python
def foo(x,y,z):#位置形參:必須被傳值的參數 print(x,y,z) # foo(1,2,3) foo(1,2,3) #位置實參數:與形參一一對應
def register(name,age,sex='male'): #形參:默認參數 print(name,age,sex) register('asb',age=40) register('a1sb',39) register('a2sb',30) register('a3sb',29) register('鋼蛋',20,'female') register('鋼蛋',sex='female',age=19)
(1):默認參數必須跟在非默認參數後閉包
def register(sex='male',name,age): #在定義階段就會報錯 print(name,age,sex)
(2):默認參數在定義階段就已經賦值了,並且只在定義階段賦值一次app
a=100000000 def foo(x,y=a): print(x,y) a=0 foo(1)
(3):默認參數的值一般定義成不可變類型函數
def foo(x,y,*args): #*會把溢出的按位置定義的實參都接收,以元組的形式賦值給args print(x,y) print(args) foo(1,2,3,4,5) def add(*args): res=0 for i in args: res+=i return res print(add(1,2,3,4)) print(add(1,2)) def foo(x, y, **kwargs): # **會把溢出的按關鍵字定義的實參都接收,以字典的形式賦值給kwargs print(x, y) print(kwargs) foo(1,2,a=1,name='egon',age=18) def foo(name,age,**kwargs): print(name,age) if 'sex' in kwargs: print(kwargs['sex']) if 'height' in kwargs: print(kwargs['height']) foo('egon',18,sex='male',height='185') foo('egon',18,sex='male') def calc(*numbers): sum = 0 for n in numbers: sum = sum + n * n print(sum) num = [1,2,3] #num位置能夠是list或tuple calc(*num) *nums表示把nums這個list的全部元素做爲可變參數傳進去。這種寫法至關有用,並且很常見。
def foo(x,y,z): print(x,y,z) foo(z=3,x=1,y=2)
關鍵字參數須要注意的問題:工具
1:關鍵字實參必須在位置實參後面 2: 不能重複對一個形參數傳值 foo(1,z=3,y=2) #正確 foo(x=1,2,z=3) #錯誤 foo(1,x=1,y=2,z=3) #錯誤
def foo(name,age,*,sex='male',height): print(name,age) print(sex) print(height) #*後定義的參數爲命名關鍵字參數,這類參數,必須被傳值,並且必須以關鍵字實參的形式去傳值 foo('egon',17,height='185') def per(name,age,*,city): print(name,age,city) per('make',24,city='beijing') def per(name,age,*,city='beijing',job): print(name,age,city,job) per('make',24,job='it')
*args是可變參數,args接收的是一個tuple; **kw是關鍵字參數,kw接收的是一個dict
def foo(): print('from foo') def bar(func): #print(func) return func f = bar(foo) #取到返回值foo內存地址 print(f) f() #調用
def foo(): print('from foo') def bar(func): print(func) func() bar(foo) # foo函數內存地址被看成參數傳遞到bar函數中,並調用 ''' 結果: <function foo at 0x00000049CC9A3E18> from foo '''
函數嵌套是閉包函數基礎測試
函數的嵌套定義: 顧名思義就是函數裏面, 套函數。應用如閉包、裝飾器
def f1(): def f2(): print('from f2') def f3(): print('from f3') f3() f2() f1()
函數的嵌套調用:屬於面向過程(分子原子級操做),細分問題
def max2(x,y): """判斷兩個數的大小""" return x if x>y else y def max4(a,b,c,d): """判斷4個數的大小""" res1 = max2(a,b) res2 = max2(res1,c) res3 = max2(res2,d) return res3 print(max4(12,34,11,35))
#倒入模塊 import time #變量賦值 name = 'engon' #函數定義 def func(): pass #類定義 class Foo: pass
print(max) print(min) #全部的內置空間 #dir 對象的內建名稱空間 import builtins for i in dir(builtins): print(i)
文件的執行會產生全局名稱空間,指的是文件級別定義的名字都會放入改空間
調用函數時會產生局部名稱空間,只在函數調用時臨時綁定,調用結束解綁定
爲名稱空間的具體應用。他們之間的關係,以下對應: 1.全局做用域:內置名稱空間,全局名層空間 2.局部做用:局部名稱空間
做用於的優先級順序:局部名稱空間---》全局名層空間---》內置名稱空間ui
查看全局做用域內的名字:gloabls()url
查看局部做用域內的名字:locals()code
若是在一個內部函數裏,對在外部做用域(但不是在全局做用域)的變量進行引用,那麼內部函數就被認爲是閉包(closure)。一個閉包就是你調用了一個函數A,這個函數A返回了一個函數B給你。這個返回的函數B就叫作閉包。你在調用函數A的時候傳遞的參數就是自由變量對象
函數嵌套的一種方式,必須遵照如下規則: a. 定義在內部函數 b. 包含對外部做用域而非全局做用域的引用,該內部函數就成爲閉包函數
# 定義實例,對象隱藏,全局不可見 def f1(): # x內部隱藏,全局不可見 x = 1 def f2(): print(x) return f2 f=f1() #print(f) # x由於隱藏,因此全局做用域無效 x=100000000000000000000000000 f() #下面也是個閉包 #!/usr/bin/python # -*- coding:utf-8 -*- def f1(): x = 1 y = 2 def f2(): print(x,y) return f2 a = f1() print(a) print(a.__closure__[0].cell_contents)
閉包應用:惰性計算
from urllib.request import urlopen #res = urlopen('http://crm.oldboyedu.com').read() #print(res.decode('utf-8')) def index(url): def get(): return urlopen(url).read() return get # 存在內存裏 oldboy = index('http://crm.oldboyedu.com') #print(oldboy().decode('utf-8')) # 閉包函數相對與普通函數會多出一個__closure__的屬性,裏面定義了一個元組用於存放全部的cell對象, # 每一個cell對象一一保存了這個閉包中全部的外部變量 print(oldboy.__closure__[0].cell_contents)
abs(-5) # 取絕對值,也就是5 round(2.623423,5) # 不帶第二個參數(四捨五入取整,也就是3.0, 4爲精準到四位四捨五入),不然第二個參數爲小數點後面的位數 pow(2, 4) # 至關於2**3,若是是pow(2, 3, 5),至關於2**3 % 5 divmod(9, 2) # 返回除法結果和餘數 max([1, 5, 2, 9]) # 求最大值 min([9, 2, -4, 2]) # 求最小值 sum([2, -1, 9, 12]) # 求和
int("5") # 轉換爲整數 integer float(2) # 轉換爲浮點數 float str(2.3) # 轉換爲字符串 string bool(0) # 轉換爲相應的真假值,在Python中,0至關於False在Python中,下列對象都至關於False:[], (), {}, 0, None, 0.0, '' slice(5, 2, -1) # 構建下標對象 slice,切片函數 list((1, 2, 3)) # 轉換爲表 list tuple([2, 3, 4]) # 轉換爲定值表 tuple dict(a=1, b="hello", c=[1, 2, 3]) # 構建詞典 dictionary set() #建立集合函數 frozenset() #建立一個不可修改的集合 如:s=frozenset({1,2}) # 定義不可變集合
ord('A') # "A"字符對應的數值 chr(65) # 數值65對應的字符 bin(56) # 返回一個字符串,表示56的二進制數 hex(56) # 返回一個字符串,表示56的十六進制數 oct(56) # 返回一個字符串,表示56的八進制數 complex(3,9) # 返回複數 3 + 9j
all([True,1,"hello!"]) # 是否全部的元素都至關於True值 any(["",0,False,[],None]) # 是否有任意一個元素至關於True值 sorted([1,5,3]) # 返回正序的序列,也就是[1,3,5] reversed([1,5,3]) # 返回反序的序列,也就是[3,5,1]
''' 參數mode是用來指明那種表示的源碼類型; 若是是exec類型,表示這是一個序列語句,能夠進行運行; 若是是eval類型,表示這是一個單一的表達式語句,能夠用來計算相應的值出來; 若是是single類型,表示這是一個單一語句,採用交互模式執行,在這種狀況下,若是是一個表達式,通常會輸出結果,而不是打印爲None輸出。 ''' a = repr('me') # 返回一個對象的字符串表示。有時可使用這個函數來訪問操做。 print(a) b = compile("print('Hello')",'','exec') # 編譯字符串成爲code對象 exec(b) d = "1+2+3+4*4" e = compile(d,'','eval') # 解釋字符串表達式。參數也能夠是compile()返回的code對象 print(eval(e)) b = compile("print('Hello')",'','eval') eval(b)
''' dir() 不帶參數時返回當前範圍內的變量,方法和定義的類型列表,帶參數時返回參數的屬性,方法列表 help() 返回對象的幫助文檔 id() 返回對象的內存地址 len() 返回對象長度,參數能夠是序列類型(字符串,元組或列表)或映射類型(如字典) challable() 判斷對象是否能夠被調用,能被調用的對象就是一個callables對象,好比函數和帶有__call__()的實例 ''' l = [] print(dir(l)) print(help(l)) x = 1 y = 2 print(id(x),id(y)) print(y is x) #判斷的是身份 def func(): pass print(callable(func))
globals() 返回一個描述當前全局變量的字典 locals() 打印當前可用的局部變量的字典 vars() 1. 當函數不接收參數時,其功能和locals函數同樣,返回當前做用域內的局部變量。 2. 當函數接收一個參數時,參數能夠是模塊、類、類實例,或者定義了__dict__屬性的對象。
裝飾器:修飾別人的工具,修飾添加功能,工具指的是函數 裝飾器自己能夠是任何可調用對象,被裝飾的對象也能夠是任意可調用對象
爲何要用裝飾器?
a. 開放封閉原則:對修改是封閉的,對擴展是開放的 b. 裝飾器就是爲了在不修改被裝飾對象的源代碼以及調用方式的前提下,爲其添加新功能
import time def timmer(func): def wrapper(*args): # 在運行函數前執行,time.time()爲當前時間(格林威治時間1970到如今的秒數) start_time = time.time() # 被裝飾函數執行,沒有返回值,默認爲 res = func(*args) # 在函數運行後執行 stop_time = time.time() print('run time is %s' % (stop_time - start_time)) return wrapper @timmer def ff(args): time.sleep(1) print('welecome to %s'% args) ff('china')
import time def timmer(func): def wrapper(*args,**kwargs): # 在運行函數前執行,time.time()爲當前時間(格林威治時間1970到如今的秒數) start_time = time.time() # 被裝飾函數執行,沒有返回值,默認爲 res = func(*args,**kwargs) # 在函數運行後執行 stop_time = time.time() print('run time is %s' % (stop_time - start_time)) return wrapper @timmer def foo(ar,kw): time.sleep(1) print('name:%s \nage:%s'% (ar,kw)) @timmer def ff(job): print('job %s' % job) res = foo('mk','18') res1 = ff('it')
import time def timmer(func): def wrapper(*args): # 在運行函數前執行,time.time()爲當前時間(格林威治時間1970到如今的秒數) start_time = time.time() # 被裝飾函數執行,沒有返回值,默認爲 res = func(*args) # 在函數運行後執行 stop_time = time.time() print('run time is %s' % (stop_time - start_time)) return wrapper login_user = {'user':None,'status':False} def auth(func): def wrapper(*args,**kwargs): if login_user['user'] and login_user['status']: res = func(*args,**kwargs) return res else: name = input('name:') passwd = input('passwd') if name == 'mk' and passwd == '123': login_user['user']='mk' login_user['status']='123' print('\033[45mlogin successful\033[0m') res = func(*args,**kwargs) return res else: print('\033[43mlogin err\033[0m') return wrapper @auth @timmer def index(): time.sleep(1) print('namenage') index()
login_user = {'user':None,'status':False} def auth(db_type): def auth2(func): def wrapper(*args,**kwargs): if db_type == 'file': if login_user['user'] and login_user['status']: res = func(*args,**kwargs) return res else: name = input('name:') passwd = input('passwd') if name == 'mk' and passwd == '123': login_user['user']='mk' login_user['status']='123' print('\033[45mlogin successful\033[0m') res = func(*args,**kwargs) return res else: print('\033[43mlogin err\033[0m') elif db_type == 'ldap': print('db_type-->ldap') return wrapper return auth2 @auth('file') #傳參 def index(): print('namenage') index() # @auth('ldap') # # def index(): # print('namenage') # index()
a.官網裝飾器定義: 裝飾器是一個函數,其主要用途是包裝另外一個函數或類。這種包裝的首要目的是透明地修改或加強被包 裝對象的行爲。 b.@functools.wraps做用: 由於裝飾器是一個閉包函數,怎樣能獲取被修飾函數的詳細信息,如:__name__。 此類實際調用函數的屬性。@functools.wraps就提供了該功能。 它是如何實現的,下面的例子是經過反射的原理把func的一些屬性更新給了callf函數。原func的屬性 不變。可是callf的屬性仍是跟原func不徹底同樣,so,若有相似的問題,還須要本身寫。 具體,請看將來的類章節。
functool.wrpaps 保持了wrapper.__name__ = func.__name__
#!/usr/bin/python # -*- coding:utf-8 -*- import functools def log(text): #定義裝飾器 if isinstance(text,str): def decorator(func): @functools.wraps(func) def wrapper(*args,**kwargs): print('%s %s' % (text,func.__name__)) return func(*args,**kwargs) return wrapper return decorator else: @functools.wraps(text) def wrapper(a,b): print('call %s' % text.__name__) return text(a,b) return wrapper #情景一:裝飾器自己不用傳入參數,只接收函數func @log #調用裝飾器(將函數now當參數傳入log裝飾器) def now(a,b): #能夠傳值 print('20159',a,b) #now() a = now('c','d') #情景二:裝飾器自己須要傳入參數,再接收函數func @log('ii.py') def now(): print('2015') #now() #print(now.__name__)
迭代器只不過是一個實現迭代器協議的容器對象。
可迭代的對象:內置__iter__方法的,都是可迭代的對象
一、訪問者不須要關心迭代器內部的結構,僅需經過next()方法不斷去取下一個內容 二、不能隨機訪問集合中的某個值 ,只能從頭至尾依次訪問 三、訪問到一半時不能往回退 四、便於循環比較大的數據集合,節省內存
可迭代對象經過__iter__轉成迭代器對象
a = iter([1,2,3,4,5]) print(a) print(a.__next__()) print(a.__next__()) print(a.__next__()) print(a.__next__()) print(a.__next__())
結果:
<list_iterator object at 0x1028d95c0> 1 2 3 4 5
經過collections模塊的Iterable類型判斷: from collections import Iterable print isinstance('abc', Iterable) # str是否可迭代 True print isinstance('1,2,3', Iterable) # list是否可迭代 True print isinstance(123, Iterable) # 整數是否可迭代 False
1.提供了一種不依賴下標的迭代方式
l = [122,343,55,6,7] i = iter(l) print(i) print(next(i)) print(next(i))
'''結果 <list_iterator object at 0x1007d9518> 122 343 '''
2.就迭代器自己來講,更節省內存。迭代一個值,原來迭代的值丟棄
l = [122,343,55,6,7] i = iter(l) for item in i: print(item) print('='*10)
'''結果 122 343 55 6 7 ========== '''
for item in i: print(item) f = open('a.txt','r',encoding='utf-8') #print(next(f),end='') for ii in f: #print(ii) print(ii.strip())
'''結果 222333 sdf '''
一個函數調用時返回一個迭代器,那這個函數就叫作生成器(generator);若是函數中包含yield語法,那這個函數就會變成生成器。
def xran(): print('one') yield 1 print('two') yield 2 print('three') yield 3 a = xran() print(a.__next__()) print(a.__next__()) print(a.__next__()) #a.__next__() #循環完畢拋出StopIteration a.close #關閉生成器
a = [7,8,9] b = (i**2 for i in a) print(b) print(next(b)) print(next(b)) print(next(b))
a. 至關於爲函數封裝好__iter__和__next__ b. return只能返回一次值,函數就終止了,而yield能返回屢次值,每次返回都會將函數暫停,下一次next會從上一次暫停的位置繼續執行
import time def tail(ttt): with open(ttt,encoding='utf-8') as f: f.seek(0,2) #print(f.tell()) while True: line = f.readline().strip() if line: return line yield line else: time.sleep(0.2) # 測試tail功能是否有效(用echo ‘python’>> a.txt,不能在pc中) # t = tail('a.txt') #print(next(t)) # for line in t: # print(line) def grep(patten,lines): for line in lines: if patten in line: yield line g = grep('python',tail('a.txt')) print(g) for i in g: print(i)
#篩選出僅偶數的平方 a = [x*x for x in range(1,11) if x % 2 ==0] print(a) #[4, 16, 36, 64, 100] b = [m+n for m in 'ABC' for n in 'abc'] print(b) #['Aa', 'Ab', 'Ac', 'Ba', 'Bb', 'Bc', 'Ca', 'Cb', 'Cc'] import os c = [d for d in os.listdir('.')] #遍歷當前路徑下的文件 print(c) #print([d for d in os.listdir('.')]) d = {'x': 'A', 'y': 'B', 'z': 'C' } for k,v in d.items(): print(k,'=',v) print([k + '=' + v for k,v in d.items()]) L = ['Hello', 'World', 'IBM', 'Apple'] e = [s.lower() for s in L] print(e) #內建的isinstance函數能夠判斷一個變量是否是字符串: x='abc' y=123 print(isinstance(x, str)) print(isinstance(y, str))
請修改列表生成式,經過添加if語句保證列表生成式能正確地執行 # L1 = ['Hello', 'World', 18, 'Apple', None] # 期待輸出: ['hello', 'world', 'apple'] print(L2) 方法一: L1 = ['Hello', 'World', 18, 'Apple', None] L2 = [] for i in L1: if isinstance(i,str): L2.append(i.lower()) print(L2) 方法二: L2 = [s.lower() for s in L1 if isinstance(s,str)] print(L2)