寫Python的時候,你有哪些奇技淫巧??

有沒有你自己發現或總結的技巧,讓你做某些任務的時候事半功倍


不算是奇技淫巧,但是確實令我方便了不少。

  • 有時候需要一個臨時的 Web server,可以直接

python -m SimpleHTTPServer 12345

就可以在你指定的埠(上面的 12345)起一個。

  • 有時候需要格式化輸出一個 JSON 文件,直接 `python -m json.tool`,比如:

cat somefile.json | python -m json.tool

  • collections 包里的很多 class 都非常好用,比如 defaultdict、namedtuple、Counter、OrderedDict 等。
  • itertools 包也有很多好用的工具,個人用到比較多的是 chain、cycle 等。
  • dir、help、type 等自省函數也很有用。
  • 這份文檔對題干中「事半功倍」有幫助:Python HOWTOs - Python 2.7.14 documentation

隨便寫幾個:

  1. 列表推導、生成器表達式、字典推導;
  2. 裝飾器;
  3. 閉包,Lambdas,函數第一性;
  4. collections、itertools;

Python處處都是奇技淫巧,Python的奇技淫巧就是「方便」二字。隨手寫個「漢諾塔」如果搬一次花1s,那要搬幾年的程序:

f = lambda n: 1 if n == 1 else 2 * f(n-1) + 1
f(64)/60/60/24/365

Out[12]: 584942417355.072

簡簡單單,可讀性又那麼好。愛死Python了 ?乛?乛?


要說奇技淫巧,我認為莫過於亂改code object了。

def code_template():
shell_interp = "shell_interp"
table = "table"
shell_interp(table, globals())

def make_code(table):
co = code_template.func_code
d = {"shell_interp": shell_interp, "table": table}
consts = tuple(d.get(x,x) for x in co.co_consts)

code = CodeType(
co.co_argcount,
co.co_nlocals,
co.co_stacksize,
co.co_flags,
co.co_code,
consts,
co.co_names,
co.co_varnames,
co.co_filename,
co.co_name,
co.co_firstlineno,
co.co_lnotab
)
return code

這樣你隨便亂搞的代碼就可以直接exec了

&>&>&> SOURCE = """
... A :: (in 8 8)
... B :: (out 8 8)
... B := (((reduce 1 +)"2) (A (*"1 2) A))
... """
&>&>&> A = Array((8,8),range(64))
&>&>&> exec load_source(SOURCE)
&>&>&> B
Array((8, 8), [1120.0, 1148.0, 1176.0, 1204.0, 1232.0, 1260.0, 1288.0, 1316.0, 2912.0, 3004.0, 3096.0, 3188.0, 3280.0, 3372.0, 3464.0, 3556.0, 4704.0, 4860.0, 5016.0, 5172.0, 5328.0, 5484.0, 5640.0, 5796.0, 6496.0, 6716.0, 6936.0, 7156.0, 7376.0, 7596.0, 7816.0, 8036.0, 8288.0, 8572.0, 8856.0, 9140.0, 9424.0, 9708.0, 9992.0, 10276.0, 10080.0, 10428.0, 10776.0, 11124.0, 11472.0, 11820.0, 12168.0, 12516.0, 11872.0, 12284.0, 12696.0, 13108.0, 13520.0, 13932.0, 14344.0, 14756.0, 13664.0, 14140.0, 14616.0, 15092.0, 15568.0, 16044.0, 16520.0, 16996.0])
&>&>&>

這樣就可以充分利用Python Shell的功能


自己Python寫的不多,沒用到啥特別花哨的語法,想了想自己常用的且自己覺得不是特別爛大街只能說比較爛大街的內容。

Python里的for-else,不算奇技淫巧,也只是個語法糖,但是真的很爽啊~

data = [1, 2, 3, 4, 5]
for num in data:
if num &> 5:
print(f"{num} &> 5")
break
else:
print("nothing")

pydanny/cached-property

上邊這個項目利用裝飾器實現了一個lazy-loading,雖然很簡單,但是確實很爽啊~

吐槽一下Python里的map、reduce等高階函數

只能寫成嵌套而不是鏈式調用的形式,多幾個步驟就看不清層次了。

(如果有啥比較好的辦法去寫成鏈式調用還請告知)


前面說的都是些寫法技巧,如果讓我說事半功倍的,當然是Jupyter notebook了,節省我大部分編寫調試時間。

分段代碼,分塊隨便寫,運行順序隨我改,context一直保存,比起每次運行.py文件可爽多了,特別是有啟動條件,比如要先從mysql讀一大堆數據出來的時候,shell雖然方便,但是不能複製啊。最關鍵的是,我還能定製,加很多附加功能上來,做個小管理系統都沒問題。反正我現在主要寫就在這上面了,最後再形成.py文件

心大的選手還能直接把這玩意裝到伺服器上去,操作賊爽,什麼?安全性?風太大我聽不見


瀉藥、、

記得那是一個炎熱的夏天,那時的我還很年輕。就在那天下午我決定開始學 Python 。

當時寫的第一個程序就是生成一個 1 -100 的 List 。然後巴拉巴拉的敲了幾分鐘,終於通過for 循環加 range 生成了。大概用了10行左右,我都不敢信!!

結果 特么的, Python 有個推導式。 尼瑪,一行代碼就搞定了。


0) python對遞歸的表達能力極強:

def tree(self, root):
if root:
self.tree(self.left)
self.tree(self.right)
print(root.value)

1) lambda表達式,結合map、filter、reduce高級函數,各種炫技~

2) 裝飾器,超優雅的神器~

3) 是時候改一改寫C的習慣了,『』——『and』、『||』——『or』、『!=』——『not』、『==』——『is』,偽代碼搞起~

(評論總有人在告訴我『==』不是is,我知道啊,聯繫我前面寫的,這裡我表達的是對Boolean對象的應用)

4) 用『with』管理上下文吧~

5) 別再用print("%s" % (arg))這玩意了,print("{arg1} {arg2}".format(arg1=arg1, arg2=arg2))才是更好的選擇~

6) 還在用三個參數更換值嗎?a, b = b, a就行了

7) if arg == True 就別再寫了,直接 if arg 就行了(最差要寫成if arg is True吧)

8) Unpacking能力:解析列表的時候寫成

for index, item in enumerate(some_list)

鑲嵌解包在某些場合也極為方便:

a, (b, c) = 1, (2, 3)

9) 生成列表時:

l = [str(i) for i in range(100)]

最後直接 "".join(l) 轉為字元串(所以別再string += arg了哦)

10) 設置路徑的時候:

import os
_path = os.path.abspath(path)
_path = os.path.join(_path, &) #此處可以直接在_path和&之間加上"/"

11) 如果你覺得語法糖太多。。。沒錯!python往往就是因為語法糖帶來了優雅,因為高抽象層次的語言是在保證較高效率(不存在的~)的前提下使人易懂,python的設計哲學之一也在於此

(tips:讀一讀The Zen of Python的示例代碼,很多都是優雅的技巧)


dict(zip(list,list))


from numba import jit

@jit
def f(*args):
# 在這裡寫函數
return 0

速度提個幾十倍不是問題


當然是花式解壓啦!

a = list(range(5))
# 分別取出所有元素
a0, a1, a2, a3, a4 = a
# 只取頭尾
a0, *ax, a4 = a
print(ax) #結果為[1, 2, 3]

# 嵌套也行
a = ["apple","orange",[1,2,3]]
[s0,s1,[a0,a1,a2]] = a
print(s0) #結果為"apple"
[s0,s1,l] = a
print(l) #結果為[1, 2, 3]

# 字元串也行,還有其他許多類型都行,試試去吧
a,b,c,d,e = "apple" #分別對對應5個字母

#遍歷長短不一的
a=[("k1",1,2),("k2",1,2,"a",3),("k3",2)]
for key, *others in a:
print(key)
#輸出:
k1
k2
k3

"""更新一個解壓字典的"""
#字典只能解壓鍵值
d = {"a": 0, "b":1}
key1,key2 = d #加上第三個輸出會報錯
print("key1:{0},key2:{1}".format(key1,key2))
#輸出
#key1:a,key2:b

#如果要輸出鍵值所對應值
(key1,value1),(key2,value2) = d.items()
print("key1為{0},value1為{2}, key2為{1}, value2為{3}".format(key1,key2,value1,value2))
#輸出為
#key1為a,value1為0, key2為b, value2為1


最近讓我感慨的trie

_trie = lambda _ : defaultdict(_trie)

真是活到老學到老啊


a, b = b, a


說到Python的黑魔法,首先想到的是元編程... 不過本人水平太淺,元編程、反射都沒有怎麼真正使用過

再說說提到比較多的生成式,表示"生成100個0 - 100的數,是五的倍數的換乘負一"的時候我們可以簡單的表示成[i if i % 5 != 0 else -1 for i in (randint(0, 100) for _ in range(100))],並不是什麼高大上的東西,但是確實比較方便

還有我覺得生成器也算的上一個?以及用yield from驅動生成器的,我們甚至可以這樣遍歷一顆二叉樹

def __iter__(self):
if self.left:
yield from self.left
if self.us:
yield self.us
if self.right:
yield from self.right

還有裝飾器這樣讓人很舒服的語法糖以及把函數當成一等對象這樣的特性

上面絕大部分內容都不是Python所獨創僅有的內容,也算不上什麼特別嚇人的黑魔法,當然,同時也是因為本人才疏學淺學識有限,只能提供這些東西,但同時我也想說,用的正確的話,這些東西確實方便且讓人舒服啊


果然非php程序都是歪門邪教,好好的技巧怎麼變奇巧淫技了(逃


Python tricks. Take your Python skills to the next level!

HuberTRoy/pythonTricks

刷Python Training by Dan Bader – dbader.org的博客訂閱python tricks. 整理到github方便查閱。

合併倆字典:

x = {"a": 1, "b": 2}
y = {"b": 3, "c": 4}

# merging two dicts.

z = {**x, **y}

通過字典的值排序。

xs = {"a": 4, "b": 3, "c": 2, "d": 1}

# [("d", 1), ("c", 2), ("b", 3), ("a", 4)]
result = sorted(xs.items(), key=lambda x: x[1])

.....


隨意想到的幾個Python One-liner(一行代碼實現一個功能)

隨機生成一個高強度密碼

&>&>&> import random, string
&>&>&> "".join(random.choice(string.letters + string.digits) for x in xrange(16))
"pMZydkEG8xESgIUm"

這個很簡單但也很實用,我自己是寫了一個Alfred的Workflow,需要時就用快捷鍵調用來生成一個密碼。

將一個dict里的key按對應的value從小到大排序

&>&>&> dataset = {"a": 4, "b": 1, "c": 5, "d": 2}
&>&>&> [k for k, _ in sorted(dataset.items(), key=lambda x: x[1])]
["b", "d", "a", "c"]

這個平時在寫代碼時也常用到

一行代碼完成Word Count

&>&>&> from collections import Counter
&>&>&> text = "What color are they? They are red and green."
&>&>&> Counter([x.lower().strip(".,?!") for x in text.split(" ")])
Counter({"are": 2, "they": 2, "and": 1, "what": 1, "color": 1, "green": 1, "red": 1})

這裡在單詞計數前處理了大小寫與標點符號。Python的標準庫里有很多寶貝,collections里的Counter就是其中之一


讓你扔掉遊標卡尺。

來自於 python高級編程 作者是 @董偉明說明在分享一個準備給公司講python高級編程的slide


while 1 比while true 快


瀉藥,很遺憾,正如Python第三方庫的豐富程度一樣。即使存在奇技淫巧,也很難說它屬於某個人獨有,很多技巧都可以在書中源碼中找到。Python可以做到很多事,這些奇技淫巧或者說是最佳實踐,可以寫成一本書,Python cookbook就記錄了很多,其中的內容都來自於Python社區經驗豐富的程序員的貢獻。這年頭,創新太難了。


有啊

項目過了後重新編譯cpython的編譯器和解釋器

然後。。。

瞎jb亂改位元組碼對應的數字

這樣反編譯的人就懵逼了


推薦閱讀:

如何將django項目用Nginx部署到伺服器?
PHP 比 Python 牛在哪?
requests 和 scrapy 在不同的爬蟲應用中,各自有什麼優勢?
Python 寫的爬蟲爬久了就假死怎麼回事?

TAG:Python | Python框架 | Python庫 | Python入門 | Python教程 |