Python中的那些「坑」

1.哪一個是True,哪一個是False?

這裏要看三組代碼:html

# 第一組:python

>>>a=256正則表達式

>>>b = 256緩存

>>>a is bapp

# 第二組:函數

>>>a = 257測試

>>>b = 257優化

>>>a is bui

# 第三組:spa

>>>a = 257; b = 257

>>>a is b

問題來了,這三組代碼的運行結果分別是什麼呢?答案是True、False和True。第一組和第三組結果是True好像沒問題,那爲何第二組的結果是False呢?這裏先用id()來查看一下a和b的地址是什麼:

# 第一組:

>>>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是同樣的呢?這是由於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()

都知道正則表達式中的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>

爲何最後會多出來"</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代碼中的標籤個數,發現"</body></html>"是第17和第18個,而由於re.S被當作16傳給count參數了,就致使最後兩個標籤沒有被替換掉。

 

3.字符串的lstrip()

相信不少人都用過lstrip(),在處理字符串的時候頗有用,好比:

 

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

 

 

這很簡單,也沒什麼問題,可是看下面這個例子:
print("ababacac".lstrip("ab"))
# cac
爲何結果不是acac呢?這是由於當lstrip()中傳入一個字符串後,lstrip()會把這個字符串拆成一個個字符,而後才從左往右進行檢查,若是匹配到就刪除,直到出現第一個不一樣的字符,因此最後"ababa"被刪掉了,結果也就是"cac"了。要避免這種狀況的話,能夠用replace()方法進行替換。

4.嵌套列表

若是要你建立一個包含三個空列表的列表,你會怎麼作呢?

# 選項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並非建立了三個不一樣的列表,而是建立了三個指向同一個列表的對象,因此,當咱們操做第一個列表時,其餘兩個列表內容也會發生變化。

相關文章
相關標籤/搜索