python3 編碼默認爲unicode,unicode和utf-8都是默認支持中文的。python
若是要python3的編碼改成utf-8,則或者在一開始就聲明全局使用utf-8算法
#_*_coding:utf-8_*_編程
或者將字符串單獨聲明:app
a = "中文".encode("utf-8")ssh
函數式編程函數式編程
函數式編程中的函數指代的是數學中的函數。函數
函數式編程輸入若是肯定,則輸出必定是肯定的。函數中並無不少邏輯運算工具
python是一個面向對象的語言,只是一部分支持函數式編程。編碼
裝飾器:spa
定義:本質是一個函數,裝飾其餘函數,爲其餘函數增長附加功能
原則:
一、不能修改被裝飾的函數的源代碼
二、不能修改被裝飾的函數的調用方式
實現裝飾器的知識準備:
一、函數即"變量"
定義函數的過程實際是將函數體以字符串的形式保存進內存的過程,當函數()時纔是調用執行函數。
所以函數的定義:
def 函數名():
函數體
實際等價於
函數名= 「函數體」
所以函數名就是一個變量名。
能夠做爲一個參數傳遞給另外一個函數
二、高階函數
a:把一個函數名當作實際參數傳遞給另外一個函數
能夠在不修改函數的源代碼的狀況下實現新功能
def bar():
print("in the bar")
def new_func(func):
print("new_func")
func()
print("after")
原來調用:bar()
新功能調用爲:new_func(bar) ,就增長新功能了,可是改變了原函數的調用方法
b:返回值中包含函數名
不修改原函數的調用方式狀況下實現新功能
def bar():
print("in the bar")
def new_func(func):
print("new_func")
func()
print("after")
return func
bar = new_func(bar)
bar() # 爲改變原函數的調用方式
返回結果
new_func # new_func功能
in the bar # new_func功能
after # new_func功能
in the bar # bar功能
三、嵌套函數
在一個函數的函數體內用def去定義一個新函數
高階函數+嵌套函數 => 裝飾器
裝飾器的寫法:
一、普通裝飾器
def bar():
print("in the bar")
def test(func):
def new_func():
print("new_func")
func()
print("after")
return new_func
@test
bar()
二、裝飾器傳遞參數:
def bar():
print("in the bar")
def test(func)
def new_func(*args,**kwargs):
print("new_func")
func(*args,**kwargs)
print("after")
return new_func
@test
bar("liubo",30)
三、裝飾器帶參數,便可以在裝飾器內作一些判斷:
import time
def decorator(type):
def outer(func):
if type=="1":
definner(*args,**kwargs):
start_time=time.time()
ret=func(*args,**kwargs)
stop_time=time.time()
print("func running time is %s" % (stop_time-start_time))
return ret
return inner
else:
def inner(*args,**kwargs):
print("your input is wrong")
return inner
return outer
print("請輸入type:")
type=input(">>>")
@decorator(type)
def f1(name,age):
time.sleep(3)
print("your name is{},age is{}".format(name,age))
f1("liubo",30)
列表生成式
a = [i*2 for i in range(10)]
生成的a爲
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
改列表生成器等價於
a = []
for i in range(10):
a.append(i*2)
print(a)
列表生成器可使代碼很簡潔,任何針對i的for循環均可以寫爲[i的處理 for循環]的格式
當連續調用2次列表生成器對同一個列表時,結果並不會疊加2次的數據,而是第二次的數據會覆蓋第一次的數據
a = [i*2 for i in range(10)]
a = [i*3 for i in range(10)]
print(a)
結果
[0, 3, 6, 9, 12, 15, 18, 21, 24, 27]
生成器:
若是執行一個循環的結果很是巨大,而咱們只用其中一部份內容,那麼多餘的數據就是無用的。所以咱們須要一種工具在執行循環時,每次循環生成一個數據,而以前的數據會釋放,然後面的數據並無生成,不會佔地方。這種工具就是生成器。
上面提到的列表生成式,實際就是在生成時就將列表裏的元素所有加載進內存的。
若是:(i*2 for i in range(10)),這樣就變成了一個生成器,當輸入這個命令時,內存中並無生成任何元素,只是增長了一個生成器
所以獲取生成器中的元素就不能用相似列表的切片的方式獲取。
生成器只有在調用時纔會生成相應的數據,調用可使用for循環來生成,也可使用__next__()方法獲取下一個元素。而生成器只有調用時保留當前值,所以生成器沒法取上一個值。實際for循環就是在for內部反覆的調用next方法
如何生成一個生成器?
一個裴波那契數列的生成器:
def fib(max):
n,a,b = 0,0,1
while n < max:
yield b
a,b = b,a+b
n+=1
return "---done----"
f = fib(10) # 建立生成器
此時f就是一個生成器,那麼我要應用這個函數中元素就須要使用next的方式調用。
print(f.__next__())
print(f.__next__())
print(f.__next__())
從上面的例子咱們能夠看到,生成器就是在函數中出現了yield關鍵字的函數,當函數運行時,遇到yield函數會暫停,而且返回yield後面的值,這樣每次咱們調用__next__()方法時,程序都會返回當前運行的結果。而return的內容就是異常時產生的消息
生成器的好處
一、節約內存外
二、能夠中斷數據的生成去作其餘的事,而後再返回到生成器中
print(f.__next__())
print("....") # 中斷生成器
print(f.__next__()) # 再次進入生成器
print("xxx") #再次中斷生成器
print(f.__next__())
經過__next__()方法,當超過了生成器的元素數量時,就會以異常結束,異常的提示就是程序最後返回的值
StopIteration: ----done---- # 異常
那麼若是須要避免這個異常,則須要將異常抓出
g = fib(6)
while True:
try: # 若是正常,則嘗試循環
x = next(g)
print("g:",x)
except StopIteration as e: # 若是出現了StopIteration ,則按下面執行
print("Generator retrun value:",e.value) # e.value就是出錯的返回值,此處爲"---done----"
break
調用一個生成器
def f1():
x = 0
while x < 10:
yield x # 第一次調用next會生成0
x += 1 # 第二次next會先加1 而後輸出1
f2 = f1() # 首先定義f2,調用f1函數。此時至關於從f2進入了f1函數
print(f2.__next__()) # 以後的每次調用都是從f2 = f1()這裏進入的,所以會依次輸出0-4
print(f2.__next__())
print(f2.__next__())
print(f2.__next__())
print(f2.__next__())
若是以下
print(f1().__next__()) # 這樣至關於每次都是從f1重新進入,所以每次輸出都是0。由於每次都是從新調用函數
print(f1().__next__())
print(f1().__next__())
print(f1().__next__())
print(f1().__next__())
在調用生成器的函數中,除了next方法,還有一個send方法。
next方法僅僅是喚醒生成器的yield,讓他開始生成元素,可是若是yield沒有返回值,則返回值爲None。
send方法喚醒yield,同時給yield傳遞值。
例如
在生成器函數中
baozi = yield
上面這個函數,取一個變量等於yield,程序 運行到此會暫停,可是yield爲空,所以若是我用next方法下面調用baozi這個變量,值爲空。
可是若是我在調用send方法,則這個值就會被send發送進來。
def cus(name)
print("%s 開始吃包子" % name)
baozi = yield # 包子賦值給yield,可是並無返回值,這裏的做用是停下來同時接收send的值給baozi
print("%s 的包子已經被我吃了" % baozi) # 此處卻須要調用baozi這個變量。
那麼若是我須要baozi這個變量有值,就須要這樣調用:
c = cus("liubo") # 建立生成器並命名爲c
c.__next__() # 首先要讓生成器運行到yield。
c.send("韭菜餡") # 調用send方法,將"韭菜餡"這個字符串傳遞給yield,並向下執行
生成器單線程的並行效果 執行案例
import time
def cus(name):
print("%s 開始吃包子" % name)
while True:
baozi = yield # 包子賦值給yield,可是並無返回值
print("{}:{} 個包子已經被我吃了".format(name,baozi)) # 此處卻須要調用baozi這個變量。
def producer(name):
c1 = cus("c1") # 建立生成器
c2 = cus("c2")
c1.__next__() # 讓生成器執行到yield,同時也打印cus函數的第一句話,表明c1已準備好
c2.__next__()
for i in range(1,4):
time.sleep(1)
print("{}:我作了2個包子".format(name))
time.sleep(1)
c1.send(i) # 將i傳遞給c1,i將會被傳遞給baozi變量以便打印
time.sleep(1)
c2.send(i)
producer("liubo")
上述程序,將使一個廚師和兩個食客三個程序同時運行(但實際是串行的)
迭代器
可直接做用於for循環的數據類型:
一、集合數據類型,例如list,tuple,dict,set,str等
二、生成器,包括帶yield的生成器
能夠直接做用於for循環的對象統稱爲可迭代對象,Iterable
能夠被__next__()函數調用並不斷返回下一個值的對象統稱爲迭代器 Iterator
可使用isinstance(),判斷一個對象是否爲Iterable對象
form collections import Iterator
isinstance((x for x in range(10)),Iterator) # isinstance(對象,類型) 判斷對象是否爲特定類型
可迭代對象不必定是迭代器(list,tuple,dict),可是可使用iter()函數將其變爲迭代器
a = [11,22,33] # 可迭代對象 不是迭代器
b = iter(a) # 就是一個迭代器了,能夠用b.__next__()調用下一個元素
迭代器在python表明一個數據流,是一個惰性運算,即只有當用到這個值時才生成這個值,所以迭代器能夠表明一個無窮大的序列。
可迭代對象在建立之初即須要建立全部的元素,迭代器的長度是未知的,可是可迭代對象的長度倒是已知的。所以可迭代對象不能是迭代器,只能經過iter()函數轉換。
內置方法
內置方法 |
功能 |
案例 |
|
abs(x) |
取一個數的絕對值 |
|
|
all(iterable) |
若是可迭代對象中的全部元素都是True,則返回鎮;不然返回False |
print(all([0,1,-3])) |
|
any(iterable) |
若是可迭代對象中有一個元素爲真,則返回真。與all相對 |
|
|
ascii(object) |
將一個對象在acsii中的對應打印出來 |
|
不經常使用 |
bin(x) |
將一個十進制轉換爲二進制 |
bin(255) 輸出0b11111111 |
|
bool(x) |
返回一個值的真假,空和0都爲假 |
|
|
bytearray(str,encoding) |
默認狀況下,字符串和二進制類型都是不容許修改的,可是bytearray是能夠修改的 |
b = bytearray("abcde",encoding ="utf-8") print(b) 輸出:a2cde,在這裏第二個元素b就被替換爲acsii表中第50個元素了。在這種狀況下我使用b[1]的方式獲取的並不是b,而是b在ascii中對應的序號。
可是若是直接用b = byte("abcde",encoding ="utf-8"),則針對某個元素的修改實際都是新建這個列表或字符串,而不是在原來的基礎上修改 |
不經常使用 |
callable() |
判斷一個對象是否能夠調用,即對象是否能夠在最後加() |
def test:pass print(callable(test))
輸出 True |
|
chr(i) |
輸入一個數字,返回acsii表中對應的元素 |
char(97) 輸出"a" |
|
ord() |
輸入一個元素,返回ascii表中對應的序號 |
ord("a") 輸出97 |
|
classmethod(func) |
|
|
|
compile (code,"文件名",執行方式) |
將一個字符串編譯爲能夠被python執行的語句(此時仍未執行)。 其中code是被編譯的字符串,文件名是當出錯時日誌輸出的位置,執行方式是但願被那個命令執行 |
code = "for i in range(10)" c = complie(code,"","exec") exec(c) 輸出,執行code的代碼。此處使用的exec執行命令 |
|
dict() |
生成一個字典 |
|
|
dir() |
能夠查詢對象的內部方法 |
dir([]) 輸出列表的方法 ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__' , '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__' , '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__' , '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_e x__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__s izeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'ex tend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort'] 其中__的是內部方法不可用 |
|
divmod(a,b) |
a和b相除與商和餘數 |
x,y = divmod(5,2) print("x=",x) print("y=",y)
輸出: x=2 y=1
2爲商,1爲餘數 |
|
enumerate(iterable,start=0) |
將一個可迭代對象序列化,開始的序列爲start=中定義的。將可迭代對象中每一個元素與其序號單獨造成一個新的元組。每一個元組就能夠分片獲取。start若是不寫,默認從0開始 |
li = [11,22,33] for i in enumerate(li,start=1): print(i)
輸出: (1, 11) (2, 22) (3, 33)
|
|
eval(表達式,globals=None,locals=None) |
eval()用來將字符串編譯爲表達式,例如 s = "8*8" r = eval(s) , print(r)的時候會返回爲64,eval只能執行表達式,eval有返回值,若是用eval(「7+8+9」),是能返回結果的,這點比exec強,對比exec。 |
x=1 eveal("x+1")
輸出
2 |
|
exec(object) |
exec() 用來執行編譯後的代碼,和complie何用,先用complie編譯,而後用exec執行。exec能夠執行全部的python的命令,exec只是執行沒有返回值,所以用exec運行一個表達式,是拿不到結果的,例如exec(「7+8+9」),只是執行可是結果是拿不到的。在執行代碼的時候exec能夠接受代碼或者字符串。 |
|
|
filter(func,iterable) |
將可迭代對象的每一個函數帶入func中,生成一個迭代器,迭代的元素時func中返回爲真的值 |
def func1(a): if a>22: retrun True b = filter(func1,[11,22,33,44]) for i in b: print(i) 返回 33 44
此處也能夠直接跟lambda函數
for i in filter(lambda x : x>22,[11,22,33,44]): print(i)
返回 33 44
|
|
map(func,iterable) |
和filter對比,filter方法將返回爲真的值生成新的迭代器。 而map方法則將返回值迭代。 |
for i in map(lambda x:x>22,[11,22,33,44]) print(i)
返回
False False True True
固然就是說map會將func的結果直接返回,若是 for i in map(lambda n : n*2,[11,22,33]): print(i)
返回 22 44 66 |
|
import functools |
是一個二元操做函數,他用來將一個數據集合(鏈表,元組等)中的全部數據進行下列操做:用傳給reduce中的函數 func()(必須是一個二元操做函數)先對集合中的第1,2個數據進行操做,獲得的結果再與第三個數據用func()函數運算,最後獲得一個結果。
|
import functools res = functools.reduce(lambda x,y:x*y,range(1,10)) print(res)
上面的函數的結果就是1*2*3*4.....*9。 如描述裏面的func必須是一個二元操做的,那麼這裏的兩個變量就會首先從後面的可迭代對象中取前兩個,而後按照要求返回,以後會將返回值與下一個對象操做,知道可迭代對象中全部的元素都被處理。 |
|
frozenset() |
將一個集合變成不可修改的集合。 |
a = set([]) 此時的a能夠有pop,clear等方法能夠修改這個集合
可是若是用 a = frozenset() a就不在有這些方法了
|
|
globals() |
以字典的形式當前整個代碼中的全部變量 |
|
|
hash() |
將一個特定對象進行哈希算法 |
|
|
hex() |
將數字轉爲十六進制 |
|
|
locals() |
以字典形式打印當前代碼中的所有的局部變量 |
|
|
max() |
返回可迭代對象中的最大值 |
|
|
min() |
返回最小值 |
|
|
next() |
從迭代器中返回下一個item |
|
|
oct() |
將一個數字轉爲八進制 |
|
|
pow(x,y) |
打印x的y次方的結果 |
|
|
round(x,y) |
x是一個浮點數,y則爲保留小數點後多少位,默認y爲0即不顯示小數,結果會四捨五入 |
round(1.2323,2) 輸出 1.23 |
|
sorted(排序內容,key="排序依據8") |
排序,只能排序int類型的數字。若是排序字典則字典的key必須是int類型 |
能夠將字典排序 a = {1:11,2:22,5:55,3:33,4:44} print(sorted(a)) 輸出會將key排序輸出 [1, 2, 3, 4, 5]
print(sorted(a.items()))
字典.items()這個方法自己會將字典轉爲元組 輸出結果爲 按照字典key排序,並將字典的鍵值對變爲元組 [(1, 11), (2, 22), (3, 33), (4, 44), (5, 55)]
若是要按照字典的值排序 print(sort(a.items(),key=lambda x:x[1]))
其中,a.items()會將字典的鍵值對變爲元組,每一個元組的[0]是鍵,[1]是值 lambda x:x[1] 是將這個元組帶入函數,並返回[1]角標即字典的值, key = lambda x : x[1]表明以字典的值爲排序依據
返回結果 [(1, 11), (2, 22), (3, 33), (4, 44), (5, 55)]
以值排序,key能夠不是int類型
a = {"zhangsan":11,"lisi":22,5:55,3:33,4:44} print(sorted(a.items(),key=lambdax:x[1]))
返回結果
[('zhangsan', 11), ('lisi', 22), (3, 33), (4, 44), (5, 55)] |
|
sum() |
輸入列表,將列表求和 |
|
|
zip(列表a,列表b) |
將兩個列表的元素一一對應,取列表中元素最少的拼接 |
|
|
__import__() |
正常的import導入模塊時後面模塊名是一個變量。可是若是模塊名是一個字符串,就不能用import。所以須要__import__() |
__import__("decorator") |
|
匿名函數
函數的目的是爲了重複調用,爲此創建函數在內存中佔用空間,可是若是這個函數僅調用一次這個佔用的空間就被浪費了。所以引出了匿名函數。
lambda函數即匿名函數,由於這個函數並未像其餘函數同樣經過def func()的方式建立了一個func的函數,他並無建立函數名,所以當還行一次後就沒有對應的變量與之關聯,其佔用的內存空間也就會被回收。
def func(n):
print(n)
這個函數的lambda寫法爲
lambda n:print(n)
執行時能夠
(lambda n:print(n))(5)
a = lambda n : print(n)
a(5)
A = lambda n:print(n) # 這裏的A是一個函數
A = (lambda n : print(n))(5) # 這裏的A是匿名函數的結果,傳遞了n = 5給匿名函數後的return
可是lambda只能執行簡單的操做,好比三元運算
a = lambda n : print("n<3") if n<3 else print("n>3") # 至關於return 返回了一個三目運算
a(5)
軟件目錄開發規範
os.path.dirname() |
獲取當前目錄的上級目錄名 |
os.path.abspath(__file__) |
獲取當前文件的絕對路徑 |
sys.path.append() |
追加環境變量的路徑 |
所以若是一個文件的絕對路徑爲:E:\Atm\bin\atm.py,我須要將E:\Atm路徑追加到python模塊調用的環境變量中,那麼須要這樣寫
base = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(base)