天天看點

Python 學習拾遺

該博文主要适應于python2.7,并沒有對py3進行測試。

主要記錄學習python過程中容易出現的一些小問題、小錯誤,相信能給你啟發。

1、剔除一個字元串中的所有空格(假設該字元串是s)

"".join(s.split())

樣例輸入:

s = '    123  4567    8   '

樣例輸出:

'12345678'

2、剔除檔案名字元串中的非法字元(假設字元串是s)

有的時候從網上抓取下來的标題需要作為檔案名儲存到本地(windows環境)

但是windows下檔案名中不能包含一些非法字元,例如‘/’、‘\’、‘?’ 神馬的

你可以用下面這段代碼剔除标題中的非法字元

pattern = re.compile(r'[/\:*?"<>|]')

s = re.sub(pattern,'',s)

s = '<<?I am title?>>'

'I am title'

3、清單解析、base64解密、chr()、int()、join()函數使用

這是知道創宇的餘弦出的一個解密小遊戲,給你一個字元串,你需要解密出一個郵箱位址。

密碼字元串為:

XDY1XDc2XDY5XDZjXDYzXDZmXDczXDQwXDY3XDZkXDYxXDY5XDZjXDJlXDYzXDZmXDZk

解密方式為先用base64解密,再進行16進制轉換,最後按ASCII碼輸出每個字元。

這個小遊戲很有意思,可以學習到一些python知識。

下面是解題步驟:

1、base64解密

s = 'XDY1XDc2XDY5XDZjXDYzXDZmXDczXDQwXDY3XDZkXDYxXDY5XDZjXDJlXDYzXDZmXDZk'

print base64.b64decode(s)

輸出:

\65\76\69\6c\63\6f\73\40\67\6d\61\69\6c\2e\63\6f\6d

這一看就是一種字元編碼,最先猜到是ASCII編碼。

為了友善觀察,将其拆分:

print base64.b64decode(s).split('\\')

['', '65', '76', '69', '6c', '63', '6f', '73', '40', '67', '6d', '61', '69', '6c', '2e', '63', '6f', '6d']

由于每個元素帶有字母,猜測是16進制數,轉換進制。

int(c,16) 可以将字元串c當成16進制數,将其轉換成10進制數傳回(注意傳回的是一個整數)

chr(n)     可以将一個整數n轉換成對應的ASCII字元。

于是有代碼:

for c in base64.b64decode(s).split('\\'):

  if c:   # 剔除空元素

    print chr(int(c,16)),

e v i l c o s @ g m a i l . c o m 

以上代碼可以用 清單解析 簡潔表示:

print [chr(int(c,16)) for c in base64.b64decode(s).split('\\') if c]

['e', 'v', 'i', 'l', 'c', 'o', 's', '@', 'g', 'm', 'a', 'i', 'l', '.', 'c', 'o', 'm']

3、join()連接配接為字元串

s.join(l)  表示将清單l中每個字元連接配接成一個字元串,用字元串s作為間隔

so,可以将上述清單連接配接成字元串:

print ''.join([chr(int(c,16)) for c in base64.b64decode(s).split('\\') if c])

[email protected]

以上,就得到餘弦大大的郵箱咯,是不是很有意思?

4.了解python繼承的小例子

1 #coding=gbk
 2 class A(object):
 3     name = 'boss'
 4     print name
 5     def __init__(self,name=None):
 6         print '2'
 7         if name is not None:
 8             self.name = name
 9         print self.name
10 
11 
12 class B(A):
13     print '1'
14     name = 'Boss'
15 
16 te = B()      

運作結果:

boss
1
2
Boss      

可以看出類中變量和函數的繼承調用關系。

執行個體化B,先是運作從A繼承來的語句,運作結果:

boss      

再運作B中的語句,運作結果:

1      

最後調用從A繼承過來的構造函數__init__(),運作結果:

2
Boss      

5.python清單解析中的雙重循環

如何将B清單中的每一個元素與A清單中的元素相加,生成一個新清單?

請看以下代碼:

1 A = [1,2,3]
2 B = [4,5,6]
3 print [x+y for x in A for y in B]      

以上清單解析的寫法相當于一個雙重循環,先周遊B中每一個元素,再周遊A中每一個元素,每輪循環進行元素相加操作,最後得到一個新清單。

6.max()的比較函數

max()函數原型:

max(arg1, arg2, *args[, key])       

例子:

1 #coding=gbk
2 A = [1,3,5,2,4]
3 
4 print max(A)                #  輸出A中最大的元素
5 print max(A,key=lambda x:x>2)    # 輸出A中第一個大于2的元素
6 
7 print max('af', 'be','cd')       # 輸出最大的字元串,比較規則為預設的字元串比較規則
8 print max('af', 'be','cd', key=lambda x: x[1])  # 輸出第二個字元最大的字元串      
5
3
cd
af      

key參數值為一個函數入口指針,你可以将自己定義的函數作為參數傳進來,max函數将根據你定義的函數來進行比較,你可以自己制訂比較規則。

lambda為python中一種定義函數(匿名函數)的方法,你也可以用def定義。

7.reverse()函數有傳回值嗎?

請看以下代碼,猜猜它會輸出什麼呢?

1 A = [1,2,3]
2 print A.reverse()      

是不是第一眼以為會輸出 [3,2,1] ?哈哈,錯了。真正的輸出是:

None      

看一下reverse()的文法:

list.reverse()
參數:NA
傳回值:該方法沒有傳回值,但是會對清單的元素進行反向排序。      

8.提取url中的host(域名)

使用urllib庫提供的函數,用法如下:

1 import urllib  
 2   
 3 protocol, rest = urllib.splittype('https://www.cnblogs.com:80/yym2013')  
 4 # protocol : https
 5 # rest     : //www.cnblogs.com:80/yym2013
 6   
 7 host, rest =  urllib.splithost(rest)  
 8 # host : www.cnblogs.com:80
 9 # rest : /yym2013
10   
11 host, port = urllib.splitport(host)  
12 # host : www.cnblogs.com
13 # port : 80      

參考自: python 擷取url的host

9.if-else 單行書寫方法

if a>b:
    t = a
else:
    t = b      

 轉換成if-else單行形式:

t = a if a>b else b      

10.open的檔案打開模式

r或rt 預設模式,文本模式讀
rb   二進制檔案
  
w或wt 文本模式寫,打開前檔案存儲被清空
wb  二進制寫,檔案存儲同樣被清空
  
a  追加模式,隻能寫在檔案末尾
a+ 可讀寫模式,寫隻能寫在檔案末尾
  
w+ 可讀寫,與a+的差別是要清空檔案内容
r+ 可讀寫,與a+的差別是可以寫到檔案任何位置      

特别注意:a+、w+、r+的差別,他們雖然都是讀寫模式,但使用效果是有差别的。

參考自:Python open()檔案處理使用介紹

11.關于檔案讀寫錯誤 IOError: [Errno 0] Error

  該錯誤通常在windows環境下,使用a+讀寫模式打開檔案,并對其先進行read()讀操作,然後進行write()寫入操作後出現的。原因是沒有進行flush或者seek等操作,python不知道檔案位置在哪了。

參考自:python IOError: [Errno 0] Error - freeDynasty

12、使用python發送郵件

參考自:使用python發送郵件

13、python的編号疊代

有時候想用下标記錄目前周遊的位置,同時又想有目前元素,自建一個變量變量作為下标又太low,優雅一些的做法是用内建函數enumerate()進行疊代。

這樣既會有下标,又會有目前疊代元素。

for index,s in enumerate(str):
    print '%d==>%s'%(index,s)      

14、list元素去重

我比較喜歡用set集合進行去重,另外如果要保留list的順序的話,需要使用sort進行排序。

詳見:python中對list去重的多種方法

15、如何用盡量簡潔的代碼輸出一個清單(list)的前五個元素

最直覺的寫法,定義一個下标變量index來控制輸出:

1 li = [1,2,3,4,5,6,7,8,9,10]
2 index = 0
3 for x in li:
4     if index>=5:
5         break
6     print x
7     index+=1      

觀察代碼,發現下标index可以用enumerate函數直接分離出來:

1 li = [1,2,3,4,5,6,7,8,9,10]
2 for index,x in enumerate(li):
3     if index>=5:
4         break
5     print x      

還有更簡單的寫法,使用清單的切片操作來簡化代碼:

1 li = [1,2,3,4,5,6,7,8,9,10]
2 for x in li[:5]:
3     print x      

16、readlines()會讀入換行符!

在一次用smtp服務發送郵件給自己的時候,我用readlines()讀取本地檔案。

将帶有email的username和password的那兩行行直接指派給使用者名和密碼變量。

結果導緻收到的郵件開頭帶有亂碼,檢查了各個地方都沒有發現bug在哪裡。

最後找到原因是輸入的使用者名和密碼最後分别帶有一個換行符,而郵件将多餘的内容作為亂碼來處理了。

解決方法是readlines()讀取每一行内容後,指派的時候需要先strip()去除字元串前後端多餘的空白符。

Freecode# : www.cnblogs.com/yym2013