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


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

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

傳遞參數時候不要使用列表

def foo(num,age=[]):
	age.append(num)
	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 = []
    age.append(num)
    print("num", num)
    return age
print(foo(1))
print(foo(2))
print(foo(3))

for。。。else的使用場景

在刷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:
        num.append(i) #根據定義如果都無法正常才加入
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有關,就不會知道結果是下面這個樣子

{1: 'B', 2: 'C'}

這是為什么呢?
因為,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))

關於if判斷條件正確寫法

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 = {"A":1, "B":2}  #etc
print(my_dict[type])

另外我們在使用給對象的屬性賦值的時候

class A():
    def __init__(self,dicts):
        self.name=dicts["name"]
        self.age=dicts["age"]
        self.sex=dicts["sex"]
        self.hobby=dicts["hobby"]
if __name__ == '__main__':
     dicts={"name":"lisa","age":23,"sex":"women","hobby":"hardstyle"}
     a=A(dicts)

我們看到我們需要換取傳入的字典的各個鍵值,並創建鍵值同名一個屬性,這里我們只有4個還好,想象一下如果我們傳入的字典有100個鍵。。。如何還是這樣一個一個賦值不敢想不敢想,人家都寫完代碼了,你還在賦值有木有。。
其實一開始的那段代碼已經給出了答案,如果不會也沒關系,
下面我們就來點pythonic的python。來解決這個問題。
上面代碼簡化為:

class A():
    def __init__(self,dicts):
        self.__dict__.update(dicts)
        print(self.__dict__)

if __name__ == '__main__':
     dicts={"name":"lisa","age":23,"sex":"women","hobby":"hardstyle"}
     a=A(dicts)

小心閉包中的坑,python的惰性計算

我們觀察下面的代碼

ls = []
for x in range(5):
    ls.append(lambda: x**2)
print(ls[0]())
print(ls[1]())
print(ls[2]())

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

16
16
16

這是什么鬼?
其實這和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轉整的時候數字前不能有0

eval("02")

會發生錯誤:

Traceback (most recent call last):
  File "/demo/1.py", line 1, in <module>
    eval("02")
  File "<string>", line 1
    02
     ^
SyntaxError: invalid token

While 1比While True快?

python2的時候是這樣,以為python3 True=1所以結果實際是一樣的。
由於Python2中,True/False不是關鍵字,因此我們可以對其進行任意的賦值,這就導致程序在每次循環時都需要對True/False的值進行檢查;而對於1,則被程序進行了優化,而后不會再進行檢查。
Python3中,由於True/False已經是關鍵字了,不允許進行重新賦值,因此,其執行結果與while 1不再有區別

處理長的字符串

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

("""多文本""")

關於requests模塊的編碼問題

作者實際上提供了個自動識別網頁編碼的代碼,在獲取res(請求的對象),獲取源碼之前使用
下面的代碼即可獲取正確的網站編碼。

res.encoding=res.apparent_encoding

更多工具使用以及python技巧,請關注公眾號:python學習開發。

如果您喜歡我的文章不防動動小手轉發一波,謝謝。
點擊閱讀原文進入我的博客園,看代碼更方便。
由於人數超過100所以需要添加我微信:italocxa,然后拉您入群。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM