當前位置:
首頁 > 知識 > 鮮為人知的 Python 語法

鮮為人知的 Python 語法

(點擊

上方藍字

,速關注我們)




編譯: Python 開發者 - 伯樂在線讀者

 ,

英文:medium


http://python.jobbole.com/89252/




所有人(好吧,不是所有人)都知道 python 是一門用途廣泛、易讀、而且容易入門的編程語言。


但同時 python 語法也允許我們做一些很奇怪的事情。


使用 lambda 表達式重寫多行函數


眾所周知 python 的 lambda 表達式不支持多行代碼。但是可以模擬出多行代碼的效果。



def

f

()

:


    

x

=

"string"


    

if

x

.

endswith

(

"g"

)

:

        

x

=

x

[

:-

1

]

    

r

=

""


    

for

i

in

xrange

(

len

(

x

))

:


        

if

x

[

i

]

!=

"i"

:


            

r

+=

x

[

i

]


    

return

r


f

()


->

"strn"




雖然看起來很奇怪,但是上面的函數可以使用下面的 

lambda

 表達式函數代替:





(

lambda

:

([

x

for

x

in

[

"string"

]],

x

.

endswith

(

"g"

)

and

[

x

for

x

in

[

x

[

:-

1

]]],

[

r

for

r

in

[

""

]],

[

x

[

i

]

!=

"i"

and

[

r

for

r

in

[

r

+

x

[

i

]]]

for

i

in

xrange

(

len

(

x

))],

r

)[

-

1

])()


->

"strn"




永遠不要在生產環境寫這樣的代碼 :)


三元運算符


現代的 python 提供了更簡便的語法:



b if a else c




也可以通過下面的方式重寫:





(

a

and

[

b

]

or

[

c

])[

0

]


 


(

b

,

c

)[

not

a

]




順便說一下,下面的變體是錯誤的:





a

and

b

or

c


True

and

[]

or

[

1

]

->

[

1

],

but

:

[]

if

True

else

[

1

]

->

[]




通過列表推導式移除重複的元素


讓我們來把字元串 

x = "tteesstt"

 轉換成 

"test"

 吧。


1.在原字元串中和上一個字元比較:



"".join(["" if i and j == x[i-1] else j for i,j in enumerate(x)]




2.把前一個字元保存到臨時變數中:





""

.

join

([(

""

if

i

==

a

else

i

,

[

a

for

a

in

[

i

]])[

0

]

for

a

in

[

""

]

for

i

in

x

])


""

.

join

([(

""

if

i

==

a

.

pop

()

else

i

,

a

.

append

(

i

))[

0

]

for

a

in

[[

""

]]

for

i

in

x

])




3.在新字元串中和上一個字元比較:





[(

not

r.endswith(i)

and

[

r

for

r

in

[r+i]], r)[-1]

for

r

in

[""]

for

i

in

x][-1]




4.通過 reduce 函數和 lambda 表達式:





reduce(

lambda

a, b:

a

if

a.endswith(b)

else

a + b, x)




通過列表推導式獲得斐波拉契數列


1.把中間值保存在列表中





[(

lambda

:

(

l

[

-

1

],

l

.

append

(

l

[

-

1

]

+

l

[

-

2

]))[

0

])()

for

l

in

[[

1

,

1

]]

for

x

in

xrange

(

19

)]


[(

l

[

-

1

],

l

.

append

(

l

[

-

1

]

+

l

[

-

2

]))[

0

]

for

l

in

[[

1

,

1

]]

for

x

in

xrange

(

19

)]




2.把中間值保存到字典中:





[

i

for

x

in

[(

lambda

:

(

l

[

"a"

],

l

.

update

({

"a"

:

l

[

"a"

]

+

l

[

"b"

]}),

l

[

"b"

],

l

.

update

({

"b"

:

l

[

"a"

]

+

l

[

"b"

]}))[

::

2

])()

for

l

in

[{

"a"

:

1

,

"b"

:

1

}]

for

x

in

xrange

(

10

)]

for

i

in

x

]


[

i

for

x

in

[(

l

[

"a"

],

l

.

update

({

"a"

:

l

[

"a"

]

+

l

[

"b"

]}),

l

[

"b"

],

l

.

update

({

"b"

:

l

[

"a"

]

+

l

[

"b"

]}))[

::

2

]

for

l

in

[{

"a"

:

1

,

"b"

:

1

}]

for

x

in

xrange

(

10

)]

for

i

in

x

]




3.通過 reduce 函數和 lambda 表達式:





reduce

(

lambda

a

,

b

:

a

+

[

a

[

-

1

]

+

a

[

-

2

]],

xrange

(

10

),

[

1

,

1

])


reduce

(

lambda

a

,

b

:

a

.

append

(

a

[

-

1

]

+

a

[

-

2

])

or

a

,

xrange

(

10

),

[

1

,

1

])




4.速度最快的變體:





[l.append(l[-1] + l[-2]) or l for l in [[1, 1]] for x in xrange(10)][0]




使用列表推導式產生死循環



[a.append(b) for a in [[None]] for b in a]


列表切片技巧


1.複製列表:





l

=

[

1

,

2

,

3

]


m

=

l

[

:

]


m


->

[

1

,

2

,

3

]




2.移除/替換 列表中的任意元素:





l

=

[

1

,

2

,

3

]


l

[

1

:-

1

]

=

[

4

,

5

,

6

,

7

]


l


->

[

1

,

4

,

5

,

6

,

7

,

3

]




3.在列表的開頭添加元素:





l

=

[

1

,

2

,

3

]


l

[

:

0

]

=

[

4

,

5

,

6

]


l


->

[

4

,

5

,

6

,

1

,

2

,

3

]




4.在列表的尾部添加元素:





l

=

[

1

,

2

,

3

]


l

[

-

1

:

]

=

[

l

[

-

1

],

4

,

5

,

6

]


l


->

[

1

,

2

,

3

,

4

,

5

,

6

]




5.反轉列表:





l

=

[

1

,

2

,

3

]


l

[

:

]

=

l

[

::-

1

]




替換方法位元組碼


Python 阻止替換類實例中的方法,因為 python 給類實例中的方法賦予了只讀屬性:



class

A

(

object

)

:


    

def

x

(

self

)

:


        

print

"hello"


a

=

A

()


def

y

(

self

)

:


    

print

"world"


a

.

x

.

im_func

=

y


->

TypeError

:

readonly

attribute




但是可以在位元組碼的層面上進行替換:





a

.

x

.

im_func

.

func_code

=

y

.

func

_

code


a

.

x

()


->

"world"




注意!

 這不僅對當前的實例有影響,而且對整個類都有影響(準確的說是與這個類綁定的函數)(譯者注:此處應該是筆誤,推測作者原意是:準確的說是與這個函數綁定的所有類),並且所有其他的實例也會受到影響:





new_a

=

A

()


new_a

.

x

()


->

"world"




讓可變元素作為函數參數默認值


把可變對象作為函數參數的默認值是非常危險的一件事,並且在面試中有大量關於這方面棘手的面試問題。但這一點對於緩存機制非常有幫助。


1.階乘函數:





def

f

(

n

,

c

=

{})

:


    

if

n

in

c

:


        

return

c

[

n

]


    

if

(

n

<

2

)

:


        

r

=

1


    

else

:


        

r

=

n

*

f

(

n

-

1

)


    

c

[

n

]

=

r


    

return

r


f

(

10

)


->

3628800


f

.

func_defaults


({

1

:

1

,


  

2

:

2

,


  

3

:

6

,


  

4

:

24

,


  

5

:

120

,


  

6

:

720

,


  

7

:

5040

,


  

8

:

40320

,


  

9

:

362880

,


  

10

:

3628800

},)




2.斐波拉契數列:





def

fib

(

n

,

c

=

{})

:


    

if

n

in

c

:


        

return

c

[

n

]


    

if

(

n

<

2

)

:


        

r

=

1


    

else

:


        

r

=

fib

(

n

-

2

)

+

fib

(

n

-

1

)


    

c

[

n

]

=

r


    

return

r


fib

(

10

)


->

89


fib

.

func_defaults

[

0

].

values

()


->

[

1

,

1

,

2

,

3

,

5

,

8

,

13

,

21

,

34

,

55

,

89

]




【關於投稿】




如果大家有原創好文投稿,請直接給公號發送留言。




① 留言格式:


【投稿】+《 文章標題》+ 文章鏈接

② 示例:


【投稿】

《不要自稱是程序員,我十多年的 IT 職場總結》:http://blog.jobbole.com/94148/



③ 最後請附上您的個人簡介哈~




看完本文有收穫?請轉

發分享給更多人


關注「P

ython開發者」,提升Python技能



喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Python開發者 的精彩文章:

爬蟲進階:反反爬蟲技巧
深夜,學妹說她想做Python數據分析師

TAG:Python開發者 |