python中也有隱藏彩蛋,你知道嗎?

可否帶我飛?

<code>

import

antigravity/<code>antigravity 模塊是 Python 開發人員發佈的少數復活節彩蛋之一.import antigravity 會打開一個 Python 的經典 XKCD 漫畫頁面.不止如此. 這個復活節彩蛋裡還有一個復活節彩蛋. 如果你看一下代碼, 就會發現還有一個函數實現了 XKCD's geohashing 算法.

自動打開的xkcd漫畫頁面

連Python也知道愛是難言的

<code>

import

this

/<code>

執行這句會發生什麼?

<code>

The

Zen of Python, by Tim Peters

Beautiful

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!

Process

finished with exit code 0

/<code>

這又是一個復活節彩蛋,實際它的源碼就一個py文件,打印了這些信息,然後什麼都沒幹

else無處不在

在Python裡else已經不侷限在if判斷裡了,它出現在眾多邏輯處理中

for......else......

<code>

def

does_exists_num

(l, to_find)

:

for

num

in

l:

if

num == to_find: print(

"Exists!"

)

break

else

: print(

"Does not exist"

) some_list = [

1

,

2

,

3

,

4

,

5

] does_exists_num(some_list,

4

) does_exists_num(some_list,

-1

) /<code>

當for循環中執行了break,就不會執行else下的語句,要注意continue不會受此影響

<code>

try

:

pass

except

: print(

"Exception occurred!!!"

)

else

: print(

"Try block executed successfully..."

) /<code>

同樣的不出現異常的時候,執行else語句

私有不私有?

<code>

class

Yo

(object)

:

def

__init__

(self)

:

self.__honey =

True

self.bitch =

True

Yo().bitch Yo().__honey Yo()._Yo__honey /<code>

雙下劃線私有變量如何完成私有變量特性的?實際是python解釋器默認把雙下劃線開頭的變量重命名了,命名方式為:_類名__varname

更快的 +=

<code>

import

timeit

print

(timeit.timeit(

"s1 = s1 + s2 + s3"

, setup=

"s1 = ' ' * 100000; s2 = ' ' * 100000; s3 = ' ' * 100000"

, number=

100

))

print

(timeit.timeit(

"s1 += s2 + s3"

, setup=

"s1 = ' ' * 100000; s2 = ' ' * 100000; s3 = ' ' * 100000"

, number=

100

)) /<code>

連接兩個以上的字符串時 += 比 + 更快, 因為在計算過程中第一個字符串 (例如, s1 += s2 + s3 中的 s1) 不會被銷燬,就是 += 執行的是追加操作,少了一個銷燬新建的動作。

來做個巨大的字符串吧!

<code>

def

add_string_with_plus

(iters)

:

s =

""

for

i

in

range(iters): s +=

"xyz"

assert

len(s) ==

3

*iters

def

add_bytes_with_plus

(iters)

:

s =

b""

for

i

in

range(iters): s +=

b"xyz"

assert

len(s) ==

3

*iters

def

add_string_with_format

(iters)

:

fs =

"{}"

*iters s = fs.format(*([

"xyz"

]*iters))

assert

len(s) ==

3

*iters

def

add_string_with_join

(iters)

:

l = []

for

i

in

range(iters): l.append(

"xyz"

) s =

""

.join(l)

assert

len(s) ==

3

*iters

def

convert_list_to_string

(l, iters)

:

s =

""

.join(l)

assert

len(s) ==

3

*iters print(timeit(add_string_with_plus(

10000

))) print(timeit(add_bytes_with_plus(

10000

))) print(timeit(add_string_with_format(

10000

))) print(timeit(add_string_with_join(

10000

))) l = [

"xyz"

] *

10000

print(timeit(convert_list_to_string(l,

10000

))) print(timeit(add_string_with_plus(

100000

))) print(timeit(add_bytes_with_plus(

100000

))) print(timeit(add_string_with_format(

100000

))) print(timeit(add_string_with_join(

100000

))) l = [

"xyz"

]*

100000

print(timeit(convert_list_to_string(l,

100000

))) /<code>不要用 + 去生成過長的字符串, 在 Python 中, str 是不可變得, 所以在每次連接中你都要把左右兩個字符串複製到新的字符串中. 如果你連接四個長度為10的字符串, 你需要拷貝 (10+10) + ((10+10)+10) + (((10+10)+10)+10) = 90 個字符而不是 40 個字符. 隨著字符串的數量和大小的增加, 情況會變得越發的糟糕 (就像add_bytes_with_plus 函數的執行時間一樣)更建議使用 .format. 或 % 語法 ,但是對於短字符串, 它們比 + 稍慢一點.如果你所需的內容已經以可迭代對象的形式提供了, 使用 ''.join(可迭代對象) 要快多了.add_string_with_plus 的執行時間沒有像 add_bytes_with_plus 一樣出現二次增加是因為解釋器會如同上一個列子所討論的一樣優化 +=. 用 s = s + "x" + "y" + "z" 替代 s += "xyz" 的話, 執行時間就會二次增加了.

<code>

def

add_string_with_plus

(iters)

:

s =

""

for

i

in

range(iters): s = s +

"x"

+

"y"

+

"z"

assert

len(s) ==

3

*iters print(timeit(add_string_with_plus(

10000

))) print(timeit(add_string_with_plus(

100000

))) /<code>

[] = ()

看著奇怪但能正確運行的語句,語句在語義上是正確的 (解包一個空的 tuple 並賦值給 list)'a'[0][0][0][0][0] 在語義上也是正確的, 因為在 Python 中字符串同時也是序列(可迭代對象支持使用整數索引訪問元素).

++和--運算符

<code>a = 5

print

(a)

print

(++a)

print

(--a) /<code>

注意python 裡沒有 ++ 操作符. 這其實是兩個 + 操作符.++a 被解析為 +(+a) 最後等於 a. --a 同理.

本地變量數量

Python 使用 2個字節存儲函數中的本地變量.

理論上, 這意味著函數中只能定義65536個變量. 但是,Python 內置了一個方便的解決方案,可用於存儲超過2^16個變量名. 下面的代碼演示了當定義了超過65536個局部變量時堆棧中發生的情況

<code>

import

dis exec(

""" def f(): """

+

""" """

.join([

"X"

+str(x)+

"="

+ str(x)

for

x

in

range(

65539

)])) f() print(dis.dis(f))/<code>

'abc'.count('') == 4

<code>

print

(

'abc'

.count(

''

) == 4) /<code>

下面這個方法能更好的說明問題

<code>def count(s,

sub

): result =

0

for

i

in

range(

len

(s) +

1

-

len

(

sub

)): result += (s[i:i +

len

(

sub

)] ==

sub

)

return

result/<code>

這個行為是由於空子串('')與原始字符串中長度為0的切片相匹配導致的.