Python 中的這些坑,早看早避免

2021-09-11 11:54:59 字數 4768 閱讀 5664

python中的這些坑,早看早避免。

說一說python中遇到的坑,躲坑看這一篇就夠了

def foo(num,age=):

print("num",num)

return age

print(foo(1))

print(foo(2))

print(foo(3))

複製**

上面的**輸出的結果並不是我們預期的那樣,列印出三個陣列[1],[2],[3]。

而是下面這樣.

num 1

[1]num 2

[1, 2]

num 3

[1, 2, 3]

複製**

為什麼會這樣呢,原因就是引數age是乙個列表,列表是乙個可變物件,同時在作為函式引數時,相當於全域性變數,在函式預處理時就已經分配了記憶體空間。那麼我們如何修改呢?

其實很簡單只要不讓列表引數作為列表,一般可變型別物件作為引數的時候預設都是給定none,然後根據物件判斷是否為空,如果為空再去定義成列表,修改如下:

def foo(num, age=none):

if not age:

age =

print("num", num)

return age

print(foo(1))

print(foo(2))

print(foo(3))

複製**

在刷pythontip的時候遇到這道題,覺得很有必要和大家普及下for。。else的用處,好了下面我們開始:

輸出100以內的所有素數,素數之間以乙個空格區分(注意,最後乙個數字之後不能有空格)。

#在一般領域,對正整數n,如果用2到根號n之間的所有整數去除,均無法整除,則n為質數又叫素數。

import math

num = #存放1-100之間的素數

for i in range(2, 100):

for j in range(2, int(math.sqrt(i)) + 1):

if i % j == 0:

break

else:

for index, i in enumerate(num):

if index == len(num) - 1:

print(i)

else:

print(i, end=" ")

複製**

根據關鍵語句「所有整數去除,均無法整除,則n為質數又叫素數。」,轉化成程式也就是說在所有的的數字都迴圈完了,還不能出才作為質數,也就是最後的那個else,體現了這句話。由此可以看出for。。else還是挺重要的。

看下面的**,猜想輸出結果:

a = {}

a[1] = "a"

a[1.0] = "b"

a[2] = "c"

print(a)

複製**

如果不知道字典裡的鍵和hash有關,就不會知道結果是下面這個樣子

複製**

這是為什麼呢?

因為,python中的字典是通過檢查鍵值是否相等以及雜湊值來確定兩個鍵是否相同.

具有相同值的不可變物件在python中始終具有相同的雜湊值.

因為1=1.0

所以hash(1)==hash(1.0).同樣的我們知道python中的true相等,我們試著

計算其hash值可以看到hash(1)==hash(true)。

由此我們可以得到如下等式:

hash(1)==hash(1.0)==hash(true)

複製**

因為只不可變物件才存在hash值所以 hash()不存在。同樣我們可以推斷出

hash(0) == hash(false) == hash("")

複製**

根據pep285中review部分第6條所述,bool類其實是從int類繼承而來.

print(isinstance(true, int))

複製**

python3中0==()={}=none=false="",所以當我們在判斷列表,或者字典字串是否為空的時候不用再使用 a==none,這樣的語句了。

a=

b={}

c=""

if not a:

print("a不為空")

if not b:

print("b不為空")

if not c:

print("c不為空")

複製**

一般我們寫if判斷的時候,我們都寫成下面這種形式:

if

type == "a":

print(1)

elif

type == "b":

print(2)

複製**

像這樣的我們需要寫好多重複**的程式,此時就要考慮是否優化了,針對這種情況我們可以優先考慮字典。

my_dict =   #etc

print(my_dict[type])

複製**

另外我們在使用給物件的屬性賦值的時候

class a():

def __init__(self,dicts):

self.name=dicts["name"]

self.age=dicts["age"]

self.***=dicts["***"]

self.hobby=dicts["hobby"]

if __name__ == '__main__':

dicts=

a=a(dicts)

複製**

我們看到我們需要換取傳入的字典的各個鍵值,並建立鍵值同名乙個屬性,這裡我們只有4個還好,想象一下如果我們傳入的字典有100個鍵。。。如何還是這樣乙個乙個賦值不敢想不敢想,人家都寫完**了,你還在賦值有木有。。

其實一開始的那段**已經給出了答案,如果不會也沒關係,

下面我們就來點pythonic的python。來解決這個問題。

上面**簡化為:

class a():

def __init__(self,dicts):

self.__dict__.update(dicts)

print(self.__dict__)

if __name__ == '__main__':

dicts=

a=a(dicts)

複製**

我們觀察下面的**

ls = 

for x in range(5):

print(ls[0]())

print(ls[1]())

print(ls[2]())

複製**

我們以為它會輸出[0],[1],[4].但實際情況是。。。。。

16

1616

複製**

這是什麼鬼?

其實這和python的惰性求值有關。惰性求值,也就是延遲求值,表示式不會在它被繫結到變數之後就立即求值,而是等用到時再求值。x實際不在lambda的作用域中。只有當lambda被呼叫時,x的值才會被傳給它。也就是最後的一次迴圈中x為4,後面的ls[1],ls[1],ls[2],ls[3]實際都是16。同時這是面試常考的乙個點,希望大家牢記。

這個問題考察了閉包。

執行檔案的路徑和當前的路徑這是兩個概念

獲取檔案的當前路徑時可以的使用

import os

os.getcwd()

複製**

但是在需要執行的檔案的獲取其執行路徑的時候就最好不要用這個了。

一般使用下面這種方式,動態的獲取路徑

import sys

sys.path[0]

複製**

eval("02")

複製**

會發生錯誤:

traceback (most recent call last):

file "/demo/1.py", line 1, in

eval("02")

file "", line 102^

syntaxerror: invalid token

複製**

python2的時候是這樣,以為python3 true=1所以結果實際是一樣的。

由於python2中,true/false不是關鍵字,因此我們可以對其進行任意的賦值,這就導致程式在每次迴圈時都需要對true/false的值進行檢查;而對於1,則被程式進行了優化,而後不會再進行檢查。

python3中,由於true/false已經是關鍵字了,不允許進行重新賦值,因此,其執行結果與while 1不再有區別

對於長的字串我們一般使用"""多文字"""的形式,但是換行的時候容易導致**出錯,此時可以考慮在外面加個小括號,像這樣

(""

"多文字"

"")複製**

作者實際上提供了個自動識別網頁編碼的**,在獲取res(請求的物件),獲取原始碼之前使用

下面的**即可獲取正確的**編碼。

複製**

四十以後的醒悟,早看早醒悟

原帖位址 四十以後才明白 朋友就像是水中的魚,深水層和淺水層的魚永遠也不會走在一起 窮和富,官和民,草根和顯貴都不可能成為真正的朋友,因為各自對人生的感悟不同,最關鍵是他們對待世界和自然的心不同。即使是富和富,官和官,顯貴和顯貴也不會成為真正的朋友。因為有利益,有分別,有取捨,有輕重,有顧慮,能分出...

三十以後的醒悟。早看早醒悟

三十以後才明白 朋友就像是水中的魚,深水層和淺水層的魚永遠也不會走在一起 窮和富,官和民,草根和顯貴都不可能成為真正的朋友,因為各自對人生的感悟不同,最關鍵是他們對待世界和自然的心不同。即使是富和富,官和官,顯貴和顯貴也不會成為真正的朋友。因為有利益,有分別,有取捨,有輕重,有顧慮,能分出三六九等,...

Python中函式預設引數的早繫結

class defaultconfiguration object def init self print calling defaultconfiguration.init classmethod def get cls return defaultconfiguration print do s...