日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

如何写出更具有Python风格的代码

發布時間:2024/1/8 python 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何写出更具有Python风格的代码 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

我們都喜歡 Python,因為它讓編程和理解變的更為簡單。但是一不小心,我們就會忽略規則,以非 Pythonic 方式編寫一堆垃圾代碼,從而浪費 Python 這個出色的語言賦予我們的優雅。Python 的代碼風格是非常優雅、明確和簡單,在 Python 解釋器中執行 import this 你可以看到 Tim Peters 編寫的 Python 之禪:

>>>?import?this The?Zen?of?Python,?by?Tim?PetersBeautiful?is?better?than?ugly. Explicit?is?better?than?implicit. Simple?is?better?than?complex. Complex?is?better?than?complicated. Flat?is?better?than?nested. Sparse?is?better?than?dense. Readability?counts. Special?cases?aren't?special?enough?to?break?the?rules. Although?practicality?beats?purity. Errors?should?never?pass?silently. Unless?explicitly?silenced. In?the?face?of?ambiguity,?refuse?the?temptation?to?guess. There?should?be?one--?and?preferably?only?one?--obvious?way?to?do?it. Although?that?way?may?not?be?obvious?at?first?unless?you're?Dutch. Now?is?better?than?never. Although?never?is?often?better?than?*right*?now. If?the?implementation?is?hard?to?explain,?it's?a?bad?idea. If?the?implementation?is?easy?to?explain,?it?may?be?a?good?idea. Namespaces?are?one?honking?great?idea?--?let's?do?more?of?those!

這里我找了目前最好的中文版本:

美 優于 丑

明確 優于 隱晦

簡單 優于 復雜

復雜 也好過 繁復

扁平 優于 嵌套

稀疏 優于 擁擠

可讀性很重要

固然代碼實用與否 比潔癖更重要,

我們以為的特例也往往沒有特殊到必須打破上述規則的程度

除非刻意地靜默,否則不要無故忽視異常

如果遇到模棱兩可的邏輯,請不要自作聰明地瞎猜。

應該提供一種,且最好只提供一種,一目了然的解決方案

當然這是沒法一蹴而就的,除非你是荷蘭人[1]

固然,立刻著手 好過 永遠不做。

然而,永遠不做 也好過 不審慎思考一擼袖子就莽著干

如果你的實現很難解釋,它就一定不是個好主意

即使你的實現簡單到爆,它也有可能是個好辦法

命名空間大法好,不搞不是地球人!

[1]:本文作者 Tim peters 解釋說這里的荷蘭人指的是 Python 的作者 Guido van Rossum.

以下是用 Python 編寫更好的代碼的 8 種方法:

一、忘掉類 C 語言風格

如果需要打印列表中的所有元素及其索引,你想到的第一件事是:

for?i?in?range(len(arr)):print(i,?arr[i])

那么你仍然在編寫 C 代碼。擺脫這一點,請牢記 Python 關鍵字 enumerate 。它索引列表/字符串中的所有元素,并且支持設置索引的起始編號

>>>?for?index,?item?in?enumerate(['a','b','c']):? ...?????print(index,?item) ...? 0?a 1?b 2?c >>>?for?index,?item?in?enumerate(['a','b','c'],1):?#這里第二個參數可以設置起始編號 ...?????print(index,item) ...? 1?a 2?b 3?c

現在看起來更好了,而且更加 Pythonic。將列表轉換成字符串呢?如果你這樣寫:

#?The?C?way string?=?'' for?i?in?arr:string?+=?i

就是 C 風格,如果使用 Python 的關鍵字 join,不僅效率更高,而且更優雅:

#?The?Python?way string?=?''.join(arr)

就像 join 一樣 ?,Python 有很多神奇的關鍵字,因此請不要為語言工作,而是使用該語言為你工作。

二、牢記 PEP8

我不是要求你完全遵循 PEP8,而是要求遵循其中的大多數規則,何況現在有很多自動格式化的工具,足以讓你的代碼更加美觀,我們的 Python 之父也說過:閱讀代碼的頻率遠遠高于寫代碼的頻率,他是如此的正確!因此代碼的可讀性非常重要。

你是否對自己曾經寫過的代碼感到好奇?為什么這么寫,這句話為什么在這?好吧,PEP8 是大多數這類問題的答案。盡管代碼注釋是個好方法,但是代碼的風格也需要加以調整,比如變量 i , j , count 等即使第一次出現時寫了注釋,也不能保證后面你仍然記得住,這樣來看就浪費了寶貴的時間。

任何普通的程序員都可以編寫計算機可以理解的代碼。只有好的程序員可以編寫人類可以理解的代碼。

首選 CamelCase 作為類, UPPER_WITH_UNDERSCORES 作為常量,而 lower_with_underscores 作為變量,方法和模塊名稱。即使使用,也要避免使用單一名稱功能 lambda 。

三、善用推導式

常用的推導式有:列表推導式,集合推導式,字典推導式。先說下列表推導式。

列表推導式就是當我們需要基于一個已有的列表創建新的列表時,所使用的語法格式,列表推導式包含以下四個部分:

1、一個輸入序列(Input Sequence) 2、一個變量,代表著輸入序列的一個成員(Variable) 3、一個可選的判定表達式,表達這個變量滿足的條件(Optional Predicate ) 4、一個輸出序列,根據 2 和 3 生成一個輸出序列(Output Expression)

比如有個列表既有數字,又有字符,現在需要計算數字的平方,并將結果放在新的列表中,如果不用列表推導式,寫出的代碼就是這樣的:

#?bad?code a_list?=?[1,?‘4’,?9,?‘a’,?0,?4]squared_ints?=?[] for?item?in?a_list:if?type(item)?==?types.IntType:squared_ints.append(item**2)

如果使用列表推導式,只需要兩行代碼,非常的優雅:

a_list?=?[1,?‘4’,?9,?‘a’,?0,?4] squared_ints?=?[?e**2?for?e?in?a_list?if?type(e)?==?types.IntType?]

當然,如果你喜歡 map 和 filter,你還可以這樣做,當時這是不推薦的,因為可讀性不好:

map(lambda?e:?e**2,?filter(lambda?e:?type(e)?==?types.IntType,?a_list))

比如集合推導式的使用:

給定輸入

names?=?[?'Bob',?'JOHN',?'alice',?'bob',?'ALICE',?'J',?'Bob'?]

希望得到:

{?'Bob',?'John',?'Alice'?}

那么集合推導式就是:

{?name[0].upper()?+?name[1:].lower()?for?name?in?names?if?len(name)?>?1?}

再比如字典推導式:

mcase?=?{'a':10,?'b':?34,?'A':?7,?'Z':3}mcase_frequency?=?{?k.lower()?:?mcase.get(k.lower(),?0)?+?mcase.get(k.upper(),?0)?for?k?in?mcase.keys()?}#?mcase_frequency?==?{'a':?17,?'z':?3,?'b':?34}

從上面可以看出。推導式風格的代碼是優雅的,人類易讀的。

四、你還在顯式的關閉文件嗎?

如果你在寫代碼時仍然在顯式的關閉文件,就像上圖中的 programmer,你在為編程語言工作,如果你學會了使用 with 上下文管理器,那么你就是一個 Python programmer,讓編程語言為你工作:

with?open('filename.txt',?'w')?as?filename:filename.write('Hello')

當程序退出 with 塊時,文件會自動關閉。with 語句的語法格式:

with?VAR?as?EXPR:BLOCK

相當于:

mgr?=?(EXPR) exit?=?type(mgr).__exit__??#?Not?calling?it?yet value?=?type(mgr).__enter__(mgr) exc?=?True try:try:VAR?=?value??#?Only?if?"as?VAR"?is?presentBLOCKexcept:#?The?exceptional?case?is?handled?hereexc?=?Falseif?not?exit(mgr,?*sys.exc_info()):raise#?The?exception?is?swallowed?if?exit()?returns?true finally:#?The?normal?and?non-local-goto?cases?are?handled?hereif?exc:exit(mgr,?None,?None,?None)

有很多網絡連接、數據庫連接庫都會提供 with 功能。甚至熟悉了 with 的實現機制后,可以自行實現 with 功能:

class?File(object):def?__init__(self,?file_name,?method):self.file_obj?=?open(file_name,?method)def?__enter__(self):return?self.file_objdef?__exit__(self,?type,?value,?traceback):self.file_obj.close()

只要定義了 __enter__,__exit__方法,就可以使用 with 語句:

with?File('demo.txt',?'w')?as?opened_file:opened_file.write('Hola!')

五、使用迭代器和生成器

迭代器:iterator 生成器:generator

迭代器和生成器都是 Python 中功能強大的工具,值得精通。迭代器是一個更籠統的概念:任何一個對象只要它所屬的類具有__next__方法(Python 2是next)和具有返回 self 的__iter__方法都是迭代器。

每個生成器都是一個迭代器,但反之不然。生成器是通過調用具有一個或多個 yield 表達式的函數而構建的,并且該函數是滿足上一段對iterator 的定義的對象。

使用區別:

網絡上很多技術博主都說生成器是懶人版的迭代器,比迭代器更節省內存,其實是錯誤的,他們都很節省內存(我會舉例子)。

他們真正的區別是:當你需要一個具有某些復雜的狀態維護行為的類,或者想要公開除__next__(和__iter__和__init__)之外的其他方法時,你就需要自定義迭代器,而不是生成器。

通常,一個生成器(有時,對于足夠簡單的需求,一個生成器表達式)就足夠了,并且它更容易編寫代碼。

比如說計算正整數 a 到 b (b 遠遠大于 a)直接的平方,生成器的話就是:

def?squares(start,?stop):for?i?in?range(start,?stop):yield?i?*?igenerator?=?squares(a,?b)

或者:

generator?=?(i*i?for?i?in?range(a,?b))

如果是迭代器,則是這樣:

class?Squares(object):def?__init__(self,?start,?stop):self.start?=?startself.stop?=?stopdef?__iter__(self):?return?selfdef?__next__(self):?#?next?in?Python?2if?self.start?>=?self.stop:raise?StopIterationcurrent?=?self.start?*?self.startself.start?+=?1return?currentiterator?=?Squares(a,?b)

可以看出,迭代器寫起來稍麻煩,當也更為靈活,比如你想提供一個 current 方法時,可以直接添加到 Squares 類中:

????def?current(self):return?self.start

從上述可以看出,迭代器并沒有保存 a 到 b 之間的所有值,所有并不消耗過多的內存,這一點也可以自行測試,代碼如下:

>>>?from?collections.abc?import?Iterator >>>?from?sys?import?getsizeof >>>?a?=?[i?for?i?in?range(1001)] >>>?print(type(a)) <class?'list'> >>>?print(getsizeof(a)) 9016 >>> >>>?b?=?iter(a) >>>?print(type(b)) <class?'list_iterator'> >>>?print(isinstance(b,Iterator)) True >>>?print(getsizeof(b)) 48 >>>?c?=?(i?for?i?in?range(1001)) >>>?print(getsizeof(b)) 48 >>>?type(c) <class?'generator'> >>>?type(b) <class?'list_iterator'>

可以看出 b 是 iterator,c 是 generator,它們占用的內存大小是一樣的。

六、善用 itertools

itertools 模塊標準化了一個快速、高效利用內存的核心工具集,這些工具本身或組合都很有用。它們一起形成了“迭代器代數”,這使得在純 Python 中有可以創建簡潔又高效的專用工具。比如,如果你想要字符串中所有字符的組合或列表中數字的所有組合,則只需編寫

from?itertools?import?combinations names?=?'ABC' for?combination?in?combinations(names,?2):print(combination) '''?Output?-('A',?'B')('A',?'C')('B',?'C') '''

這是一個值得經常使用的標準庫,更多詳細功能請參考官方文檔:https://docs.python.org/zh-cn/3/library/itertools.html[1]

七、善用 collections

這又是一個值得使用的標準庫 collections,它提供替代內置的數據類型的多個容器,如 defaultdict、OrderedDict、namedtuple、Counter、deque 等,非常使用,而且比自己實現要安全穩定的多。比如:

#?frequency?of?all?characters?in?a?string?in?sorted?order from?collections?import?(OrderedDict,?Counter) string?=?'abcbcaaba' freq?=?Counter(string) freq_sorted?=?OrderedDict(freq.most_common()) for?key,?val?in?freq_sorted.items():print(key,?val) '''?Output?-('a',?4)('b',?3)('c',?2) '''

不多說了,看官方文檔:https://docs.python.org/3/library/collections.html[2]

八、不要過度使用類

不要過度使用類。堅持用 Java 和 C ++ 的程序員會經常使用類,但是在使用 Python 時,可以在函數和模塊的幫助下復用代碼。除非絕對需要,否則不必創建類。

本文講述類 8 個讓你寫出更好 Python 代碼的方法,希望對你有所幫助。

推薦閱讀:

10個技巧讓你的代碼更優雅

6 個值得玩味的 Python 代碼

參考資料

[1]

https://docs.python.org/zh-cn/3/library/itertools.html: https://docs.python.org/zh-cn/3/library/itertools.html

[2]

https://docs.python.org/3/library/collections.html: https://docs.python.org/3/library/collections.html

總結

以上是生活随笔為你收集整理的如何写出更具有Python风格的代码的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。