程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

別說你沒踩過!Python中的那些你不知不覺會踩的“坑”

編輯:Python

1.哪個是True,哪個是False? (https://jq.qq.com/?_wv=1027&k=aLlhPAxB)

這裡要看三組代碼:

# 第一組:
>>>a=256
>>>b = 256
>>>a is b
# 第二組:
>>>a = 257
>>>b = 257
>>>a is b
# 第三組:
>>>a = 257; b = 257
>>>a is b

問題來了,這三組代碼的運行結果分別是什麼呢?

答案是True、False和True。第一組和第三組結果是True好像沒問題,那為什麼第二組的結果是False呢?

這裡先用id()來查看一下a和b的地址是什麼:(https://jq.qq.com/?_wv=1027&k=aLlhPAxB)

# 第一組:
>>>id(a)
>>>1426657040
>>>id(b)
>>>1426657040
# 第二組:
>>>id(a)
>>>363389616
>>>id(b)
>>>363392912
# 第三組:
>>>id(a)
>>>5722000
>>>id(b)
>>>5722000

可以看到第一組和第三組的a和b的id值是相同的,但是第二組是不同的。出現這種情況是因為Python為了避免重復的創建和回收,就把那些常用的整數緩存起來,每次需要使用時直接從緩存中拿,而不是重新創建,這些整數的范圍是[-5, 256],不在這個范圍之中的數字就要重新創建了。

那為什麼第三組的a和b是一樣的呢?(https://jq.qq.com/?_wv=1027&k=aLlhPAxB)

這是因為Python內部做了優化,對於在同一個代碼塊中的代碼,如果出現兩個值相同的整數,那麼它們將被重用。這裡可以用下面的代碼進行測試:

a = 257
b = 257
def func():
c = 257
print(a is c) # False
print(a is b) # True
func()

這段代碼中a和b的id值是一樣的,和c的id值不同。這是因為a和b在同一個代碼塊,而c處在func函數裡,屬於局部變量,和a不在同一個代碼塊。所以在創建c的時候會重新創建,但是創建b的時候會重用a這個對象。

在Python的交互式命令行中,每單獨一行都視為一個代碼塊,因此第三組中的a和b處在同一個代碼塊中,所以後者重用了前者,因此,兩個變量的id是相同的。

2.關於正則表達式re.sub() (https://jq.qq.com/?_wv=1027&k=aLlhPAxB)

都知道正則表達式中的re.sub()是用於字符串替換的,比如:

import re
def remove_tag(html):
text = re.sub('<.*?>', '', html, re.S)
return text

這段代碼的功能就是將html中的標簽都替換為空,沒什麼好說的,這裡可以用一段html代碼來測試一下:

html = """
<!DOCTYPE html><html lang="en">
<head><meta charset="UTF-8">
<title>Document</title>
</head><body></body></html>
"""
print(remove_tag(html))
# Document

運行結果和我們想象的一樣,但是如果html代碼再長一點呢?比如下面:

html = """
<!Dtp-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title>
</head><bodOCTYPE html><html lang="en"><head><meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta hty><h1>h1標題</h1><h2>h2標題</h2><h3>h3標題</h3></body></html>
"""
print(remove_tag(html))

運行結果如下:

Document
h1標題h2標題h3標題</body></html>

為什麼最後會多出來呢?這兩個標簽不應該被替換掉嗎?問題在於re.sub()的第四個參數,這裡先看下sub()函數的原型:

re.sub(pattern, repl, string, count=0, flags=0)

那為什麼我們把re.S放在count的位置也沒有報錯呢?難道說re.S是一個數字?打印出來看一下:

import re
print(re.S)
# 16

原來re.S還可以當數字用!這時候數一下上面那段html代碼中的標簽個數,發現是第17和第18個,而因為re.S被當做16傳給count參數了,就導致最後兩個標簽沒有被替換掉。

3.字符串的lstrip() (https://jq.qq.com/?_wv=1027&k=aLlhPAxB)

相信很多人都用過lstrip(),在處理字符串的時候很有用,比如:

print("aabbcc".lstrip('aa'))
# bbcc

這很簡單,也沒什麼問題,但是看下面這個例子:

print("ababacac".lstrip("ab"))
# cac

為什麼結果不是acac呢?

這是因為當lstrip()中傳入一個字符串後,lstrip()會把這個字符串拆成一個個字符,然後才從左往右進行檢查,如果匹配到就刪除,直到出現第一個不同的字符,所以最後ababa被刪掉了,結果也就是cac了。要避免這種情況的話,可以用replace()方法進行替換。

4.嵌套列表 (https://jq.qq.com/?_wv=1027&k=aLlhPAxB)

如果要你創建一個包含三個空列表的列表,你會怎麼做呢?

'''
學習中遇到問題沒人解答?小編創建了一個Python學習交流QQ群:660193417###
尋找有志同道合的小伙伴,互幫互助,群裡還有不錯的視頻學習教程和PDF電子書!
'''
# 選項1
li =[[] for i in range(3)]
# 選項2
li = [[]*3]
# 選項3
li = [[]]*3

如果你運行一下,就會知道選項1和選項3能夠得到我們想要的結果。這時候再運行一下下面這段代碼:

li = [[]]*3
li[0].append(1)
print(li)
# [[1], [1], [1]]

為什麼我們明明只給第一個列表增加了一個1,但是其他兩個列表也增加了一個1呢?這是因為[[]]*3並不是創建了三個不同的列表,而是創建了三個指向同一個列表的對象,所以,當我們操作第一個列表時,其他兩個列表內容也會發生變化。


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved