色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

讓你的 Python 代碼優雅又地道

馬哥Linux運維 ? 來源:未知 ? 作者:鄧佳佳 ? 2018-03-06 10:35 ? 次閱讀

前言

Python社區文化的澆灌下,演化出了一種獨特的代碼風格,去指導如何正確地使用Python,這就是常說的pythonic。一般說地道(idiomatic)的python代碼,就是指這份代碼很pythonic。Python的語法和標準庫設計,處處契合著pythonic的思想。而且Python社區十分注重編碼風格一的一致性,他們極力推行和處處實踐著pythonic。所以經常能看到基于某份代碼P vs NP (pythonic vs non-pythonic)的討論。pythonic的代碼簡練,明確,優雅,絕大部分時候執行效率高。閱讀pythonic的代碼能體會到“代碼是寫給人看的,只是順便讓機器能運行”暢快。

然而什么是pythonic,就像什么是地道的漢語一樣,切實存在但標準模糊。import this可以看到Tim Peters提出的Python之禪,它提供了指導思想。許多初學者都看過它,深深贊同它的理念,但是實踐起來又無從下手。PEP 8給出的不過是編碼規范,對于實踐pythonic還遠遠不夠。如果你正被如何寫出pythonic的代碼而困擾,或許這份筆記能給你幫助。

Raymond Hettinger是Python核心開發者,本文提到的許多特性都是他開發的。同時他也是Python社區熱忱的布道師,不遺余力地傳授pythonic之道。這篇文章是網友Jeff Paine整理的他在2013年美國的PyCon的演講的筆記。

術語澄清:本文所說的集合全都指collection,而不是set。

以下是正文。

本文是Raymond Hettinger在2013年美國PyCon演講的筆記(視頻, 幻燈片)。

示例代碼和引用的語錄都來自Raymond的演講。這是我按我的理解整理出來的,希望你們理解起來跟我一樣順暢!

遍歷一個范圍內的數字

foriin[0,1,2,3,4,5]:

printi **2

foriinrange(6):

printi **2

更好的方法

foriinxrange(6):

printi **2

xrange會返回一個迭代器,用來一次一個值地遍歷一個范圍。這種方式會比range更省內存。xrange在Python 3中已經改名為range。

遍歷一個集合

colors=['red','green','blue','yellow']

foriinrange(len(colors)):

printcolors[i]

更好的方法

forcolorincolors:

printcolor

反向遍歷

colors=['red','green','blue','yellow']

foriinrange(len(colors)-1,-1,-1):

printcolors[i]

更好的方法

forcolorinreversed(colors):

printcolor

遍歷一個集合及其下標

colors=['red','green','blue','yellow']

foriinrange(len(colors)):

printi,'--->',colors[i]

更好的方法

fori,colorinenumerate(colors):

printi,'--->',color

這種寫法效率高,優雅,而且幫你省去親自創建和自增下標。

當你發現你在操作集合的下標時,你很有可能在做錯事。

遍歷兩個集合

names=['raymond','rachel','matthew']

colors=['red','green','blue','yellow']

n=min(len(names),len(colors))

foriinrange(n):

printnames[i],'--->',colors[i]

forname,colorinzip(names,colors):

printname,'--->',color

更好的方法

forname,colorinizip(names,colors):

printname,'--->',color

zip在內存中生成一個新的列表,需要更多的內存。izip比zip效率更高。

注意:在Python 3中,izip改名為zip,并替換了原來的zip成為內置函數。

有序地遍歷

colors=['red','green','blue','yellow']

# 正序

forcolorinsorted(colors):

printcolors

# 倒序

forcolorinsorted(colors,reverse=True):

printcolors

自定義排序順序

colors=['red','green','blue','yellow']

def compare_length(c1,c2):

iflen(c1)

iflen(c1)>len(c2):return1

return0

print sorted(colors,cmp=compare_length)

更好的方法

print sorted(colors, key=len)

第一種方法效率低而且寫起來很不爽。另外,Python 3已經不支持比較函數了。

調用一個函數直到遇到標記值

blocks=[]

whileTrue:

block=f.read(32)

ifblock=='':

break

blocks.append(block)

更好的方法

blocks=[]

forblockiniter(partial(f.read,32),''):

blocks.append(block)

iter接受兩個參數。第一個是你反復調用的函數,第二個是標記值。

譯注:這個例子里不太能看出來方法二的優勢,甚至覺得partial讓代碼可讀性更差了。方法二的優勢在于iter的返回值是個迭代器,迭代器能用在各種地方,set,sorted,min,max,heapq,sum……

在循環內識別多個退出點

def find(seq,target):

found=False

fori,valueinenumerate(seq):

ifvalue==target:

found=True

break

ifnotfound:

return-1

returni

更好的方法

def find(seq,target):

fori,valueinenumerate(seq):

ifvalue==target:

break

else:

return-1

returni

for執行完所有的循環后就會執行else。

譯注:剛了解for-else語法時會困惑,什么情況下會執行到else里。有兩種方法去理解else。傳統的方法是把for看作if,當for后面的條件為False時執行else。其實條件為False時,就是for循環沒被break出去,把所有循環都跑完的時候。所以另一種方法就是把else記成nobreak,當for沒有被break,那么循環結束時會進入到else。

遍歷字典的key

d={'matthew':'blue','rachel':'green','raymond':'red'}

forkind:

printk

forkind.keys():

ifk.startswith('r'):

deld[k]

什么時候應該使用第二種而不是第一種方法?當你需要修改字典的時候。

如果你在迭代一個東西的時候修改它,那就是在冒天下之大不韙,接下來發生什么都活該。

d.keys()把字典里所有的key都復制到一個列表里。然后你就可以修改字典了。

注意:如果在Python 3里迭代一個字典你得顯示地寫:list(d.keys()),因為d.keys()返回的是一個“字典視圖”(一個提供字典key的動態視圖的迭代器)。詳情請看文檔。

遍歷一個字典的key和value

# 并不快,每次必須要重新哈希并做一次查找

forkind:

printk,'--->',d[k]

# 產生一個很大的列表

fork,vind.items():

printk,'--->',v

更好的方法

fork,vind.iteritems():

printk,'--->',v

iteritems()更好是因為它返回了一個迭代器。

注意:Python 3已經沒有iteritems()了,items()的行為和iteritems()很接近。詳情請看文檔。

用key-value對構建字典

names=['raymond','rachel','matthew']

colors=['red','green','blue']

d=dict(izip(names,colors))

# {'matthew': 'blue', 'rachel': 'green', 'raymond': 'red'}

Python 3: d = dict(zip(names, colors))

用字典計數

colors=['red','green','red','blue','green','red']

# 簡單,基本的計數方法。適合初學者起步時學習。

d={}

forcolorincolors:

ifcolornotind:

d[color]=0

d[color]+=1

# {'blue': 1, 'green': 2, 'red': 3}

更好的方法

d={}

forcolorincolors:

d[color]=d.get(color,0)+1

# 稍微潮點的方法,但有些坑需要注意,適合熟練的老手。

d=defaultdict(int)

forcolorincolors:

d[color]+=1

用字典分組 — 第I部分和第II部分

names=['raymond','rachel','matthew','roger',

'betty','melissa','judith','charlie']

# 在這個例子,我們按name的長度分組

d={}

fornameinnames:

key=len(name)

ifkeynotind:

d[key]=[]

d[key].append(name)

# {5: ['roger', 'betty'], 6: ['rachel', 'judith'], 7: ['raymond', 'matthew', 'melissa', 'charlie']}

d={}

fornameinnames:

key=len(name)

d.setdefault(key,[]).append(name)

更好的方法

d=defaultdict(list)

fornameinnames:

key=len(name)

d[key].append(name)

字典的popitem()是原子的嗎?

d={'matthew':'blue','rachel':'green','raymond':'red'}

whiled:

key,value=d.popitem()

printkey,'-->',value

popitem是原子的,所以多線程的時候沒必要用鎖包著它。

連接字典

defaults={'color':'red','user':'guest'}

parser=argparse.ArgumentParser()

parser.add_argument('-u','--user')

parser.add_argument('-c','--color')

namespace=parser.parse_args([])

command_line_args={k:vfork,vinvars(namespace).items()ifv}

# 下面是通常的作法,默認使用第一個字典,接著用環境變量覆蓋它,最后用命令行參數覆蓋它。

# 然而不幸的是,這種方法拷貝數據太瘋狂。

d=defaults.copy()

d.update(os.environ)

d.update(command_line_args)

更好的方法

d = ChainMap(command_line_args, os.environ, defaults)

ChainMap在Python 3中加入。高效而優雅。

提高可讀性

位置參數和下標很漂亮

但關鍵字和名稱更好

第一種方法對計算機來說很便利

第二種方法和人類思考方式一致

用關鍵字參數提高函數調用的可讀性

twitter_search('@obama', False, 20, True)

更好的方法

twitter_search('@obama', retweets=False, numtweets=20, popular=True)

第二種方法稍微(微秒級)慢一點,但為了代碼的可讀性和開發時間,值得。

用namedtuple提高多個返回值的可讀性

# 老的testmod返回值

doctest.testmod()

# (0, 4)

# 測試結果是好是壞?你看不出來,因為返回值不清晰。

更好的方法

# 新的testmod返回值, 一個namedtuple

doctest.testmod()

# TestResults(failed=0, attempted=4)

namedtuple是tuple的子類,所以仍適用正常的元組操作,但它更友好。

創建一個nametuple

TestResults = namedTuple('TestResults', ['failed', 'attempted'])

unpack序列

p='Raymond','Hettinger',0x30,'python@example.com'

# 其它語言的常用方法/習慣

fname=p[0]

lname=p[1]

age=p[2]

email=p[3]

更好的方法

fname, lname, age, email = p

第二種方法用了unpack元組,更快,可讀性更好。

更新多個變量的狀態

def fibonacci(n):

x=0

y=1

foriinrange(n):

printx

t=y

y=x+y

x=t

更好的方法

def fibonacci(n):

x,y=0,1

foriinrange(n):

printx

x,y=y,x+y

第一種方法的問題

x和y是狀態,狀態應該在一次操作中更新,分幾行的話狀態會互相對不上,這經常是bug的源頭。

操作有順序要求

太底層太細節

第二種方法抽象層級更高,沒有操作順序出錯的風險而且更效率更高。

同時狀態更新

tmp_x=x+dx *t

tmp_y=y+dy *t

tmp_dx=influence(m,x,y,dx,dy,partial='x')

tmp_dy=influence(m,x,y,dx,dy,partial='y')

x=tmp_x

y=tmp_y

dx=tmp_dx

dy=tmp_dy

更好的方法

x,y,dx,dy=(x+dx *t,

y+dy *t,

influence(m,x,y,dx,dy,partial='x'),

influence(m,x,y,dx,dy,partial='y'))

效率

優化的基本原則

除非必要,別無故移動數據

稍微注意一下用線性的操作取代O(n**2)的操作

總的來說,不要無故移動數據

連接字符串

names=['raymond','rachel','matthew','roger',

'betty','melissa','judith','charlie']

s=names[0]

fornameinnames[1:]:

s+=', '+name

prints

更好的方法

print ', '.join(names)

更新序列

names=['raymond','rachel','matthew','roger',

'betty','melissa','judith','charlie']

delnames[0]

# 下面的代碼標志著你用錯了數據結構

names.pop(0)

names.insert(0,'mark')

更好的方法

names=deque(['raymond','rachel','matthew','roger',

'betty','melissa','judith','charlie'])

# 用deque更有效率

delnames[0]

names.popleft()

names.appendleft('mark')

裝飾器和上下文管理

用于把業務和管理的邏輯分開

分解代碼和提高代碼重用性的干凈優雅的好工具

起個好名字很關鍵

記住蜘蛛俠的格言:能力越大,責任越大

使用裝飾器分離出管理邏輯

# 混著業務和管理邏輯,無法重用

def web_lookup(url,saved={}):

ifurlinsaved:

returnsaved[url]

page=urllib.urlopen(url).read()

saved[url]=page

returnpage

更好的方法

@cache

def web_lookup(url):

returnurllib.urlopen(url).read()

注意:Python 3.2開始加入了functools.lru_cache解決這個問題。

分離臨時上下文

# 保存舊的,創建新的

old_context=getcontext().copy()

getcontext().prec=50

print Decimal(355)/Decimal(113)

setcontext(old_context)

更好的方法

with localcontext(Context(prec=50)):

print Decimal(355)/Decimal(113)

譯注:示例代碼在使用標準庫decimal,這個庫已經實現好了localcontext。

如何打開關閉文件

f=open('data.txt')

try:

data=f.read()

finally:

f.close()

更好的方法

with open('data.txt')asf:

data=f.read()

如何使用鎖

# 創建鎖

lock=threading.Lock()

# 使用鎖的老方法

lock.acquire()

try:

print'Critical section 1'

print'Critical section 2'

finally:

lock.release()

更好的方法

# 使用鎖的新方法

withlock:

print'Critical section 1'

print'Critical section 2'

分離出臨時的上下文

try:

os.remove('somefile.tmp')

exceptOSError:

pass

更好的方法

with ignored(OSError):

os.remove('somefile.tmp')

ignored是Python 3.4加入的, 文檔。

注意:ignored 實際上在標準庫叫suppress(譯注:contextlib.supress).

試試創建你自己的ignored上下文管理器。

@contextmanager

def ignored(*exceptions):

try:

yield

exceptexceptions:

pass

把它放在你的工具目錄,你也可以忽略異常

譯注:contextmanager在標準庫contextlib中,通過裝飾生成器函數,省去用__enter__和__exit__寫上下文管理器。詳情請看文檔。

分離臨時上下文

# 臨時把標準輸出重定向到一個文件,然后再恢復正常

with open('help.txt','w')asf:

oldstdout=sys.stdout

sys.stdout=f

try:

help(pow)

finally:

sys.stdout=oldstdout

更好的寫法

with open('help.txt','w')asf:

with redirect_stdout(f):

help(pow)

redirect_stdout在Python 3.4加入(譯注:contextlib.redirect_stdout), bug反饋。

實現你自己的redirect_stdout上下文管理器。

@contextmanager

def redirect_stdout(fileobj):

oldstdout=sys.stdout

sys.stdout=fileobj

try:

yield fieldobj

finally:

sys.stdout=oldstdout

簡潔的單句表達

兩個沖突的原則:

一行不要有太多邏輯

不要把單一的想法拆分成多個部分

Raymond的原則:

一行代碼的邏輯等價于一句自然語言

列表解析和生成器

result=[]

foriinrange(10):

s=i **2

result.append(s)

print sum(result)

更好的方法

print sum(i**2 for i in xrange(10))

第一種方法說的是你在做什么,第二種方法說的是你想要什么。

編譯:0xFEE1C001

www.lightxue.com/transforming-code-into-beautiful-idiomatic-python

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • python
    +關注

    關注

    56

    文章

    4792

    瀏覽量

    84628

原文標題:讓你的 Python 代碼優雅又地道

文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    使用Python進行串口通信的案例

    當然!以下是一個使用Python進行串口通信的簡單示例。這個示例展示了如何配置串口、發送數據以及接收數據。我們將使用 pyserial 庫,這是一個非常流行的用于串口通信的Python庫。 首先,
    的頭像 發表于 11-22 09:11 ?180次閱讀

    對比Python與Java編程語言

    Python與Java都是目前非常流行的編程語言,它們各有其獨特的優勢和適用場景。以下是對這兩種編程語言的對比: 一、語法和易用性 Python 語法簡潔,代碼更易讀,非常適合初學者。 動態類型系統
    的頭像 發表于 11-15 09:31 ?289次閱讀

    使用Python進行圖像處理

    下面是一個關于使用Python在幾行代碼中分析城市輪廓線的快速教程。
    的頭像 發表于 11-07 10:14 ?210次閱讀
    使用<b class='flag-5'>Python</b>進行圖像處理

    Python常用函數大全

    Python 世界里,有一些寶藏函數和模塊,它們可以編程更輕松、代碼更高效。這篇文章將帶你一一認識這些神器,
    的頭像 發表于 10-27 17:20 ?236次閱讀

    【每天學點AI】一個例子帶你了解Python裝飾器到底在干嘛!

    今天我們來聊聊一種能給你的代碼變得“加料”的神器——Python裝飾器。就像一杯咖啡,原本它是苦的,為了它符合我的口味,我給它添加了糖,添加之后就完美的符合了我的口味。那么,裝飾器又是如何給
    的頭像 發表于 09-20 16:54 ?551次閱讀
    【每天學點AI】一個例子帶你了解<b class='flag-5'>Python</b>裝飾器到底在干嘛!

    如何幫助孩子高效學習Python:開源硬件實踐是最優選擇

    顯著提升孩子的學習興趣和對Python原理的理解。本文將探討為何使用Raspberry Pi(樹莓派)或Unihiker(行空板)等開源硬件是孩子們掌握Python的最佳途徑。 孩子們在Py
    的頭像 發表于 09-06 09:49 ?307次閱讀

    揭秘能耗管理系統:如何的建筑綠色省錢?

    揭秘能耗管理系統:如何的建筑綠色省錢? 在當今這個環保意識日益增強的時代,建筑行業的綠色轉型已成為不可逆轉的趨勢。而在這場轉型中,能耗管理系統(Energy Management System
    的頭像 發表于 08-14 10:38 ?250次閱讀

    pytorch和python的關系是什么

    ,PyTorch已經成為了一個非常受歡迎的框架。本文將介紹PyTorch和Python之間的關系,以及它們在深度學習領域的應用。 Python簡介 Python是一種高級、解釋型、通用的編程語言,由Guido van Rossu
    的頭像 發表于 08-01 15:27 ?1889次閱讀

    怎么導出python邊緣計算中的APP?

    怎么導出python邊緣計算中的APP,想進行修改找不到源碼
    發表于 07-25 06:13

    用pycharm進行python爬蟲的步驟

    提供了許多有用的功能,如代碼自動完成、調試和版本控制等。您可以從JetBrains的官方網站下載PyCharm,并根據您的需求選擇免費社區版或付費專業版。 創建一個新的Python項目 打開
    的頭像 發表于 07-11 10:11 ?824次閱讀

    華為云開發者桌面全新發布 CodeArts IDE for Python,極致優雅云原生開發體驗

    Python 編碼體驗。 Python 是一種編程語言,廣泛用于 Web 應用程序、軟件開發、數據科學和機器學習 (ML)。Python 以其優雅的語法、動態解釋性、豐富的標準庫、極
    的頭像 發表于 05-10 00:27 ?1235次閱讀
    華為云開發者桌面全新發布 CodeArts IDE for <b class='flag-5'>Python</b>,極致<b class='flag-5'>優雅</b>云原生開發體驗

    谷歌升級Bard AI聊天機器人為Gemini,新增Python代碼編輯功能

     此外,谷歌表示,接下來數個月內,Gemini Advanced 計劃會加入更多新功能,如支持更為詳盡的上下文信息、增強多模態交互性以及完善編程功能。據谷歌公開更新,付費用戶可用 Gemini 界面直接編輯和執行 Python 代碼,有助于快速驗證試驗
    的頭像 發表于 02-20 15:47 ?577次閱讀

    優雅停機是什么?SpringBoot+Nacos+k8s實現優雅停機

    優雅停機是什么?網上說的優雅下線、無損下線,都是一個意思。
    的頭像 發表于 02-20 10:00 ?2027次閱讀
    <b class='flag-5'>優雅</b>停機是什么?SpringBoot+Nacos+k8s實現<b class='flag-5'>優雅</b>停機

    Python智能家居系統代碼介紹

    Python智能家居系統是一種基于Python編程語言開發的智能家居控制系統,在現代家庭中得到了越來越廣泛的應用。本文將詳細介紹Python智能家居系統的代碼實現,包括系統的結構與功能
    的頭像 發表于 01-25 09:46 ?1352次閱讀

    Burn-In測試明白多少呢?

    Burn-In測試明白多少呢? burn-in測試,中文名老化測試,指的就是在產品出廠之前先進行高負荷的使用其渡過故障高發頻率,其到達客戶手中能夠穩定運行。 可能有人不懂為什么
    的頭像 發表于 01-12 15:41 ?6771次閱讀
    Burn-In測試<b class='flag-5'>你</b><b class='flag-5'>又</b>明白多少呢?
    主站蜘蛛池模板: 小小水蜜桃3视频在线观看| 东京热影院| 久久青青热| 亚洲国产综合另类视频| 国产 有码 无码 电影| 女朋友的妈妈在线观看| 中文字幕成人免费高清在线| 狠狠人妻久久久久久综合九色| 晚夜免费禁用十大亏亏| 妇少水多18P蜜泬17P亚洲乱| 亲嘴扒胸摸屁股视频免费网站| 99久久久国产精品免费调教| 快穿之H啪肉| 最近的2019中文字幕国语完整版| 久草精品视频| 艳照门在线播放| 精品国产乱码久久久久久夜深人妻| 亚洲xxxx动漫| 国内精品久久久久久西瓜色吧| 亚洲成人99| 国产在线精品一区二区网站免费| 性色欲情网站IWWW九文堂| 国产午夜不卡| 亚洲电影成人 成人影院| 国产又黄又硬又粗| 亚洲人女同志video| 精品爽爽久久久久久蜜臀| 一本道色综合手机久久| 久久久大香菇| 538久久视频在线| 內射XXX韩国在线观看| ewp系列虐杀在线视频| 日本久久黄色| 国产成人免费视频| 午夜性爽视频男人的天堂在线| 国产亚洲精品久久久999无毒| 亚洲精品一卡二卡三卡四卡2021| 狠狠射首页| 在线精彩视频在线观看免费| 麻豆精品传媒卡一卡二传媒短视频 | FREEXXX性乌克兰XXX|