文章目錄前言目前Python已經(jīng)更新到了3.7版本,不必多說,,Python 3比Python 2更是多出了許多新的功能,。Python是一門友好的語言,,其區(qū)別于以往C++,Java的特點不僅是代碼易于閱讀,,同時代碼也更加優(yōu)雅簡潔,,實現(xiàn)同樣的功能相對于Python只需要短短幾行代碼,這給予了開發(fā)人員更大的便利,,同時也易于初學(xué)者學(xué)習(xí),。本文將介紹Python中一些有趣實用的(代碼)功能,希望這些代碼能夠幫助大家更加輕松優(yōu)雅地解決一些問題,。 Python之禪The Zen of Python, by Tim Peters
Python之禪 by Tim Peters
Python:優(yōu)雅高效的寫法多變量賦值當(dāng)你想要初始化多個變量的時候:
x = []y = []z = []
這樣做的話代碼更加簡潔,,同時可讀性更高 變量交換
# edchange x and yt = xx = yy = t
這樣做的話不止代碼簡潔,讓人一眼就能看出是要交換變量,,同時也能免去考慮中間變量賦值的先后順序,,并且后者的效率更是高于前者。 格式化字符串如果你想要格式化輸出一串字符串,,你會怎么做,?
name = 'James'country = 'USA'string = 'My name is %s, from %s, I love %s' % (name, country, country)>>> string'My name is James, from USA, I love USA'
name = 'James'country = 'USA'string = 'My name is {name}, from {country}, I love {country}'.format(name=name, country=country)'My name is James, from USA, I love USA'# or you can simplipy it by using f-stringsname = 'James'country = 'USA'string = f'My name is {name}, from {country}, I love {country}'>>> string'My name is James, from USA, I love USA'
使用 序列并包(pack)當(dāng)你想同時訪問兩個列表的時候,,你的做法是?
names = ['James', 'Tim', 'Katty']ages = [18, 19, 20]for name, age in zip(names,ages): print('name:', name,'age:', age)name: James age: 18name: Tim age: 19name: Katty age: 20
后者的方法不僅一目了然,,同時遍歷元素的行為比遍歷下標(biāo)的行為更加高效,! 序列解包(unpack)當(dāng)你需要將一個二元組序列拆成兩列,你會怎么做,?
Data = [('James', 18), ('Tim', 19), ('Katty', 20)]names = [data[0] for data in Data]ages = [data[1] for data in Data]
條件表達式
if x<y: small=xelse: small=y
后者不僅表達意思更加明了,同時代碼量也少了好幾行,。 if結(jié)構(gòu)簡化如果你需要檢查幾個數(shù)值時:
if x==1 or x==2 or x==3 or x==4: print('x =1 or 2 or 3 or 4')
if鏈?zhǔn)綏l件表達式
if x>0 and x<10: print('0<x<10')
前者是其他語言的判斷方法,,而后者顯然更加簡潔明了。 any & all當(dāng)存在多個條件判斷語句時:
if a>0 or b>0 or c>0: print('one of them greater than 0')if a>0 and b>0 and c>0: print('all of them greater than 0')
eval
>>> eval('[1,2,3,4]')[1,2,3,4]>>> eval('(1,2,3,4)')(1,2,3,4)>>> eval('1+1')2
那么 >>> ast.literal_eval('__import__('os').system('dir')')ValueError Traceback (most recent call last)<ipython-input-95-788ef7e6407f> in <module>()----> 1 ast.literal_eval('__import__('os').system('dir')')~\Anaconda3\lib\ast.py in literal_eval(node_or_string) 83 return left - right 84 raise ValueError('malformed node or string: ' + repr(node))---> 85 return _convert(node_or_string) 86 87 ~\Anaconda3\lib\ast.py in _convert(node) 82 else: 83 return left - right---> 84 raise ValueError('malformed node or string: ' + repr(node)) 85 return _convert(node_or_string) 86 ValueError: malformed node or string: <_ast.Call object at 0x000001C9DBA145F8>
當(dāng)你試圖轉(zhuǎn)化一些'危險'的表達式時,,它會阻止你執(zhí)行并報錯。出于安全考慮,,對字符串進行類型轉(zhuǎn)換的時候最好使用 遍歷元素與下標(biāo)當(dāng)你需要遍歷元素得同時,,獲取元素的位置下標(biāo):
names = ['James', 'Tim', 'Katty']for i,name in enumerate(names): print('Id:{},name:{}'.format(i,names[i]))Id:0,name:JamesId:1,name:TimId:2,name:Katty
前者的代碼不僅難看,同時通過下標(biāo)訪問元素比遍歷元素效率更低,,而后者使用 for/else如果讓你判斷某個列表是否存在偶數(shù),存在則輸出該偶數(shù),,若不存在任何偶數(shù),,則輸出'There are no even Numbers'
for i in [1,3,5,7,9]: if i%2 == 0: print('{} is even number'.format(i))else: print('There are no even Numbers')
前者多了一個 dict映射代替多條件查找
condition = {1:100, 2:200, 3:300}y = condition[x]
訪問字典元素訪問字典元素的方法想必大家都清楚,,但是如果字典中不存在該鍵值對呢?
>>> phone_number = {'James':123456,'Tim':678910,'Katty':111213 }>>> phone_number['James'] if 'james' in phone_number else 'Not Found'123456>>> phone_number['james'] if 'james' in phone_number else 'Not Found''Not Found'
defaultdict當(dāng)你的字典中,,每一個鍵值對應(yīng)的是一個列表時,,如何使用
my_dict = {}names = ['James', 'Tim', 'Katty', 'James']numbers = [123456, 678910, 111213, 456789]for name, number in zip(names, numbers): if name in my_dict: my_dict[name].append(number) else: my_dict[name] = [] my_dict[name].append(number)>>> my_dict{'James': [123456, 456789], 'Tim': [678910], 'Katty': [111213]}
后者使用 my_dict = {}names = ['James', 'Tim', 'Katty', 'James']numbers = [123456, 678910, 111213, 456789]for name, number in zip(names, numbers): if name in my_dict: my_dict[name].append(number) else: my_dict[name] = []
列表/字典解析式當(dāng)你想要生成一個列表或者字典的時候:
生成列表
生成字典 my_dict = {}for i in range(10): my_dict[i]=i*i>>> my_dict{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
生成列表
生成字典 >>> {i:i*i for i in range(10)}{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
列表/字典推導(dǎo)式是Python獨具特色的功能之一,使用可以使得你的代碼更加簡潔高效,。類似地,,你也可以使用元組推導(dǎo)式。 字符串連接當(dāng)你需要創(chuàng)建一串字符串類似
string = []for i in range(10): string .append(str(i))>>> ''.join(string)'0123456789'# or like thisstring = [str(i) for i in range(10)]>>> ''.join(string)'0123456789'
'_'的妙用在Python中,, for _ in range(5): print('Hello')
當(dāng)你只需要一個循環(huán)多次重復(fù)做某件事,但是并不需要循環(huán)體的變量,,就可以使用
在這里 L = [1,2,3,4,5]first, *_, last = L>>> fitst1>>> last5
map函數(shù)如果我們有一個函數(shù),,希望將其作用在一個list[0,1,2,3,4]上,,如何實現(xiàn)?
>>> list(map(lambda i:i*i, range(5)))[0, 1, 4, 9, 16]
后者的代碼顯然一目了然,。
最后很重要的一點是,, reduce函數(shù)如果我們需要將[1,2,3,4]轉(zhuǎn)化成1234,如何做,?
sum = 0for i in [1,2,3,4]: sum= sum*10 + i>>> sum1234
在Python 3中,, filter函數(shù)當(dāng)你需要過濾一個列表的元素,,例如,,將列表中的奇數(shù)刪除,只留下偶數(shù): L = list(range(10))for i in L: if i%2==0: L.remove(i)>>> L[0, 2, 4, 6, 8]
這里 生成器(generator)前面介紹過,我們可以直接使用列表推導(dǎo)式創(chuàng)建一個完整的列表,,當(dāng)列表元素劇增的時候,,如果只需要訪問某幾個元素,那將是十分浪費存儲空間的,。而生成器正是為了解決這一問題,,一邊循環(huán)一邊計算,列表元素按照某種算法推算出來,從而節(jié)省大量空間,。
>>> [x * x for x in range(10)][0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
二者的區(qū)別只是一個用了 yield寫一個簡單的斐波那契數(shù)列吧
def fib(n): x, y = 0, 1 L = [] for i in range(n): L.append(y) x, y = y, x+y return L>>> fib(5)[1, 1, 2, 3, 5]
后者使用了 partial函數(shù)函數(shù)在執(zhí)行時,如果不是默認參數(shù),,就必須在調(diào)用前傳入,。但是,有些參數(shù)是可以在函數(shù)被調(diào)用之前提前獲知的,,這種情況下,,一個函數(shù)有一個或多個參數(shù)預(yù)先就能知道,以便函數(shù)能用更少的參數(shù)進行調(diào)用,。 # partial is not built-in function from python 3from functools import partialdef mul(a, b): return a*bmul_partial = partial(mul,b=10)for i in range(10): print(mul_partial(i),end=' ')# 0 10 20 30 40 50 60 70 80 90
也許你會說,這不就和默認參數(shù)一樣嗎,,那我只要在定義函數(shù)
但是,,如果你要傳入的 lru_cache仍然是一個計算斐波那契數(shù)列的例子,,這次我們使用遞歸實現(xiàn)(雖然遞歸效率遠低于循環(huán),,但這里只是作為一個例子演示,,實際中最好少用遞歸)
import timedef fib(n): if n == 0: return 0 if n == 1: return 1 return fib(n-1) + fib(n-2)start = time.time()>>> fib(40)102334155>>> f'Duration: {time.time() - start}s'Duration: 40.126065492630005s
可以看到,使用了LRU緩存后,,二者的運行時間簡直天差地別,。 枚舉from enum import Enum, autoclass Animal(Enum): bird = auto() dog = auto() cat = auto()>>> print(Animal.cat)Animal.cat
Python 3 中的 Reference
|
|