預備知識:
空值是Python裏一個特殊的值,用None表示。None不能理解爲0,由於0是有意義的,而None是一個特殊的空值。此外,
Python還提供了列表、字典等多種數據類型,還容許建立自定義數據類型。Python的註釋以 # 開頭,後面的文字直到行
尾都算註釋# 這一行所有都是註釋...print 'hello' # 這也是註釋 會輸出hello若是一個字符串包含不少須要轉義
的字符,對每個字符都進行轉義會很麻煩。爲了不這種狀況,咱們能夠在字符串前面加個前綴 r ,表示這是一個 raw 字符串,裏面的字符就不須要轉義了。例如:r'\(~_~)/ \(~_~)/'
可是r'...'表示法不能表示多行字符串,也不能表示包含'和 "的字符串(爲何?)
若是要表示多行字符串,能夠用'''...'''表示:
'''Line 1
Line 2
Line 3'''
上面這個字符串的表示方法和下面的是徹底同樣的:
'Line 1\nLine 2\nLine 3'
還能夠在多行字符串前面添加 r ,把這個多行字符串也變成一個raw字符串:
r'''Python is created by "Guido".
It is free and easy to learn.
Let's start learn Python in imooc!'''
----------------------------------------------------------------------------------------------------------------------------------------------------------
a = True
print a and 'a=T' or 'a=F'
計算結果不是布爾類型,而是字符串 'a=T',這是爲何呢?由於Python把0、空字符串''和None當作 False,其餘數
值和非空字符串都當作 True,因此:True and 'a=T' 計算結果是 'a=T'
繼續計算 'a=T' or 'a=F' 計算結果仍是 'a=T'要解釋上述結果,又涉及到 and 和 or 運算的一條重要法則:短路計
算。1. 在計算 a and b 時,若是 a 是 False,則根據與運算法則,整個結果一定爲 False,所以返回 a;若是 a 是 True,則整個計算結果一定取決與 b,所以返回 b。2. 在計算 a or b 時,若是 a 是 True,則根據或運算法則,整個計算結果一定爲 True,所以返回 a;若是 a 是 False,則整個計算結果一定取決於 b,所以返回 b。因此Python解釋器在作布爾運算時,只要能提早肯定計算結果,它就不會日後算了,直接返回結果。
Python內置的一種數據類型是列表:list。list是一種有序的集合,能夠隨時添加和刪除其中的元素。list是數學意義上的有序集合,也就是說,list中的元素是按照順序排列的。構造list很是簡單,按照上面的代碼,直接用 [ ] 把list的全部元素都括起來,就是一個list對象。一般,咱們會把list賦值給一個變量,這樣,就能夠經過變量來引用
list:classmates = ['Michael', 'Bob', 'Tracy']
print classmates
因爲Python是動態語言,因此list中包含的元素並不要求都必須是同一種數據類型,咱們徹底能夠在list中包含各類:
L = ['Michael', 100, True]
索引從 0 開始,也就是說,第一個元素的索引是0,第二個元素的索引是1,以此類推。咱們能夠用 -1 這個索引來表示最後一個元素,相似的,倒數第二用 -2 表示,倒數第三用 -3 表示,倒數第四用 -4 表示
append()老是把新的元素添加到 list 的尾部。list的 insert()方法,它接受兩個參數,第一個參數是索引號,第二個參數是待添加的新元素
pop()方法老是刪掉list的最後一個元素,而且它還返回這個元素,因此咱們執行 L.pop() 後,會打印出這個元素。能夠用 pop(2)把索引爲2的元素刪除
替換: L = ['Adam', 'Lisa', 'Bart'] L[2] = 'Paul'
tuple是另外一種有序的列表,中文翻譯爲「 元組 」。tuple 和 list 很是相似,可是,tuple一旦建立完畢,就不能修
改了。建立tuple和建立list惟一不一樣之處是用( )替代了[ ]。獲取 tuple 元素的方式和 list 是如出一轍的
t = (1) print t結果爲1,由於()既能夠表示tuple,又能夠做爲括號表示運算時的優先級,結果 (1) 被Python解釋
器計算出結果 1,致使咱們獲得的不是tuple,而是整數 1。
正是由於用()定義單元素的tuple有歧義,因此 Python 規定,單元素 tuple 要多加一個逗號「,」,這樣就避免了歧義:t = (1,) print t 結果爲(1,)
tuple一開始指向的list並無改爲別的list,因此,tuple所謂的「不變」是說,tuple的每一個元素,指向永遠不變。
即指向'a',就不能改爲指向'b',指向一個list,就不能改爲指向其餘對象,但指向的這個list自己是可變的!
注意: Python代碼的縮進規則。具備相同縮進的代碼被視爲代碼塊,上面的3,4行 print 語句就構成一個代碼塊(但不包括第5行的print)。若是 if 語句判斷爲 True,就會執行這個代碼塊。
縮進請嚴格按照Python的習慣寫法:4個空格,不要使用Tab,更不要混合Tab和空格,不然很容易形成由於縮進引發的語法錯誤。
注意: if 語句後接表達式,而後用:表示代碼塊開始。
若是你在Python交互環境下敲代碼,還要特別留意縮進,而且退出縮進須要多敲一行回車 練習:
score=55
if score >= 60:
score=bytes(score)
print 'passed:'+score
else:
print 'nopass'
age = 8
if age >= 6:
print 'teenager'
elif age >= 18:
print 'adult'
else:
print 'kid'
Python的 for 循環就能夠依次把list或tuple的每一個元素迭代出來:L = ['Adam', 'Lisa', 'Bart']
for name in L:
print name
注意: name 這個變量是在 for 循環中定義的,意思是,依次取出list中的每個元素,並把元素賦值給 name,而後執行for循環體,這樣,遍歷一個list或tuple就很是容易了
花括號 {} 表示這是一個dict,而後按照 key: value, 寫出來便可。最後一個 key: value 的逗號能夠省略。因爲
dict也是集合,len() 函數能夠計算任意集合的大小:
能夠簡單地使用 d[key] 的形式來查找對應的 value
經過 key 訪問 dict 的value,若是key不存在,會直接報錯:KeyError。要避免 KeyError 發生,有兩個辦法:一是先判斷一下 key 是否存在,用 in 操做符:
if 'Paul' in d:
print d['Paul']
二是使用dict自己提供的一個 get 方法,在Key不存在的時候,返回None
dict的第一個特色是查找速度快,不管dict有10個元素仍是10萬個元素,查找速度都同樣。而list的查找速度隨着元素增長而逐漸降低。
不過dict的查找速度快不是沒有代價的,dict的缺點是佔用內存大,還會浪費不少內容,list正好相反,佔用內存小,可是查找速度慢。因爲dict是按 key 查找,因此,在一個dict中,key不能重複。
dict的第二個特色就是存儲的key-value序對是沒有順序的!這和list不同
dict的第三個特色是做爲 key 的元素必須不可變,Python的基本類型如字符串、整數、浮點數都是不可變的,均可以做爲 key。可是list是可變的,就不能做爲 key。
d = {
'Adam': 95,
'Lisa': 85,
'Bart': 59
}要把新同窗'Paul'的成績 72 加進去,用賦值語句 d['Paul'] = 72若是 key 已經存在,則賦值會用新的 value 替
換掉原來的 value
練習:
d = {
'Adam': 95,
'Lisa': 85,
'Bart': 59
}
for key in d:
print key
print d[key]
print d.get(key)
set 持有一系列元素,這一點和 list 很像,可是set的元素沒有重複,並且是無序的,這點和 dict 的 key很像。建立 set 的方式是調用 set() 並傳入一個 list,list的元素將做爲set的元素:s = set(['A', 'B', 'C'])添加劇復元素,重複元素最後只存在一個
因爲set存儲的是無序集合,因此咱們無法經過索引來訪問。
訪問 set中的某個元素實際上就是判斷一個元素是否在set中。
s = set(['Adam', 'Lisa', 'Bart', 'Paul'])
Bart是該班的同窗嗎?'Bart' in s輸出True
遍歷:
s = set([('Adam', 95), ('Lisa', 85), ('Bart', 59)])
for name in s:
print name
輸出('Lisa', 85)
('Adam', 95)
('Bart', 59)
添加元素時,用set的add()方法,刪除set中的元素時,用set的remove()方法,不存在會報錯
在Python中,定義一個函數要使用 def 語句,依次寫出函數名、括號、括號中的參數和冒號:,而後,在縮進塊中編寫函數體,函數的返回值用 return 語句返回。return None能夠簡寫爲return。
在語法上,返回一個tuple能夠省略括號,而多個變量能夠同時接收一個tuple,按位置賦給對應的值,因此,Python的函數返回多值其實就是返回一個tuple
使用遞歸函數須要注意防止棧溢出。在計算機中,函數調用是經過棧(stack)這種數據結構實現的,每當進入一個函數調用,棧就會加一層棧幀,每當函數返回,棧就會減一層棧幀。因爲棧的大小不是無限的,因此,遞歸調用的次數過多,會致使棧溢出。
Python自帶的 int() 函數,其實就有兩個參數,int()函數的第二個參數是轉換進制,若是不傳,默認是十進制
(base=10),若是傳了,就用傳入的參數。
可變參數的名字前面有個 * 號,咱們能夠傳入0個、1個或多個參數給可變參數
在python2中有input和raw_input兩個函數,其中raw_input將全部輸入做爲字符串看待,返回字符串類型。
input函數支持表達式、數字類型、字符串類型,接受爲表達式時,只返回其執行結果。
在python3中對input和raw_input函數進行了整合,僅保留了input函數(認爲raw_input函數是冗餘的)。
同時改變了input的用法——將全部的輸入按照字符串進行處理,並返回一個字符串。
sqrt()方法返回x的平方根(x>0)。
語法
如下是sqrt()方法的語法:
import math
math.sqrt( x )
注意:此函數是沒法直接訪問的,因此咱們須要導入math模塊,而後須要用math的靜態對象來調用這個函數。參數
1. x -- 這是一個數值表達式。返回值
此方法返回x的平方根,對於x>0。例子下面的例子顯示了sqrt()方法的使用。
#!/usr/bin/python
import math # This will import math module
print "math.sqrt(100) : ", math.sqrt(100)
print "math.sqrt(7) : ", math.sqrt(7)
print "math.sqrt(math.pi) : ", math.sqrt(math.pi)
當咱們運行上面的程序,它會產生如下結果:
math.sqrt(100) : 10.0
math.sqrt(7) : 2.64575131106
math.sqrt(math.pi) : 1.77245385091
map()是 Python 內置的高階函數,它接收一個函數 f 和一個 list,並經過把函數 f 依次做用在 list 的每一個元素上
,獲得一個新的 list 並返回。注意:map()函數不改變原有的 list,而是返回一個新的 list。
在使用Python編譯的時候出現以下錯誤:
SyntaxError: Non-ASCII character '\xe5' in file Test1.py on line 8, but no encoding declared; see
http://www.python.org/peps/pep-0263.html for details
解決方法
python的默認編碼文件是用的ASCII碼,將文件存成了UTF-8,編譯就能夠經過。或在在py文件開頭(必須是第一行)加入
[python] view plain copy
#coding=utf-8
或者
[python] view plain copy
# -*- coding:utf-8 -*-
緣由
若是要在python2的py文件裏面寫中文,則必需要添加一行聲明文件編碼的註釋,不然python2會默認使用ASCII編碼。
能夠使用unicode函數
print u'你好';
print (unicode("請輸入銷售額", encoding="utf-8"))
將utf-8編碼轉換爲unicode就能夠輸出中文了。
將ASCII字符轉換爲對應的數值即‘a’-->65,使用ord函數,ord('a')
反正,使用chr函數,將數值轉換爲對應的ASCII字符,chr(65)
reduce()函數也是Python內置的一個高階函數。reduce()函數接收的參數和 map()相似,一個函數 f,一個list,但行爲和 map()不一樣,reduce()傳入的函數 f 必須接收兩個參數,reduce()對list的每一個元素反覆調用函數f,並返回最終結果值。reduce()還能夠接收第3個可選參數,做爲計算的初始值。
例如,編寫一個f函數,接收x和y,返回x和y的和:
def f(x, y):
return x + y
調用 reduce(f, [1, 3, 5, 7, 9])時,reduce函數將作以下計算:
先計算頭兩個元素:f(1, 3),結果爲4;
再把結果和第3個元素計算:f(4, 5),結果爲9;
再把結果和第4個元素計算:f(9, 7),結果爲16;
再把結果和第5個元素計算:f(16, 9),結果爲25;
因爲沒有更多的元素了,計算結束,返回結果25。
filter()函數接收一個函數 f 和一個list,這個函數 f 的做用是對每一個元素進行判斷,返回 True或 False,filter
()根據判斷結果自動過濾掉不符合條件的元素,返回由符合條件元素組成的新list。
注意: s.strip(rm) 刪除 s 字符串中開頭、結尾處的 rm 序列的字符。
當rm爲空時,默認刪除空白符(包括'\n', '\r', '\t', ' ')
Python內置的 sorted()函數可對list進行升序排序
但 sorted()也是一個高階函數,它能夠接收一個比較函數來實現自定義排序,比較函數的定義是,傳入兩個待比較的元
素 x, y,若是 x 應該排在 y 的前面,返回 -1,若是 x 應該排在 y 的後面,返回 1。若是 x 和 y 相等,返回 0。
定義一個函數 f(),咱們讓它返回一個函數 g,能夠這樣寫:
def f():
print 'call f()...'
# 定義函數g:
def g():
print 'call g()...'
# 返回函數g:
return g
調用函數 f,咱們會獲得 f 返回的一個函數:
>>> x = f() # 調用f()
call f()...
>>> x # 變量x是f()返回的函數:
<function g at 0x1037bf320>
>>> x() # x指向函數,所以能夠調用
call g()... # 調用x()就是執行g()函數定義的代碼
內層函數引用了外層函數的變量(參數也算變量),而後返回內層函數的狀況,稱爲閉包(Closure)。
閉包的特色是返回的函數還引用了外層函數的局部變量,因此,要正確使用閉包,就要確保引用的局部變量在函數返回後不能變。舉例以下:
# 但願一次返回3個函數,分別計算1x1,2x2,3x3:
def count():
fs = []
for i in range(1, 4):
def f():
return i*i
fs.append(f)
return fs
f1, f2, f3 = count()
你可能認爲調用f1(),f2()和f3()結果應該是1,4,9,但實際結果所有都是 9(請本身動手驗證)。
緣由就是當count()函數返回了3個函數時,這3個函數所引用的變量 i 的值已經變成了3。因爲f一、f二、f3並無被調用,因此,此時他們並未計算 i*i,當 f1 被調用時:
>>> f1()
9 # 由於f1如今才計算i*i,但如今i的值已經變爲3
所以,返回函數不要引用任何循環變量,或者後續會發生變化的變量。
def count():
fs = []
for i in range(1, 4):
def f(j):
def g():
return j*j
return g
r = f(i)
fs.append(r)
return fs
f1, f2, f3 = count()
print f1(), f2(), f3()
輸出1 4 9
關鍵字lambda 表示匿名函數,冒號前面的 x 表示函數參數。
匿名函數有個限制,就是隻能有一個表達式,不寫return,返回值就是該表達式的結果。
Python的 decorator 本質上就是一個高階函數,它接收一個函數做爲參數,而後,返回一個新函數。
使用 decorator 用Python提供的 @ 語法,這樣能夠避免手動編寫 f = decorate(f) 這樣的代碼。要讓 @log 自適應任何參數定義的函數,能夠利用Python的 *args 和 **kw,保證任意個數的參數老是能正常調用。
在定義 Person 類時,能夠爲Person類添加一個特殊的__init__()方法,當建立實例時,__init__()方法被自動調用,咱們就能在此爲每一個實例都統一加上如下屬性:php
class Person(object):
def __init__(self, name, gender, birth):
self.name = name
self.gender = gender
self.birth = birth
__init__() 方法的第一個參數必須是 self(也能夠用別的名字,但建議使用習慣用法),後續參數則能夠自由指定,和定義函數沒有任何區別。css
相應地,建立實例時,就必需要提供除 self 之外的參數:html
xiaoming = Person('Xiao Ming', 'Male', '1991-1-1')
xiaohong = Person('Xiao Hong', 'Female', '1992-2-2')
只有以雙下劃線開頭的"__job"不能直接被外部訪問。
可是,若是一個屬性以"__xxx__"的形式定義,那它又能夠被外部訪問了,以"__xxx__"定義的屬性在Python的類中被稱
爲特殊屬性,有不少預約義的特殊屬性能夠使用,一般咱們不要把普通屬性用"__xxx__"定義。
以單下劃線開頭的屬性"_xxx"雖然也能夠被外部訪問,可是,按照習慣,他們不該該被外部訪問。
在class中定義的所有是實例方法,實例方法第一個參數 self 是實例自己。
要在class中定義類方法,須要這麼寫:
class Person(object):
count = 0
@classmethod
def how_many(cls):
return cls.count
def __init__(self, name):
self.name = name
Person.count = Person.count + 1
print Person.how_many()
p1 = Person('Bob')
print Person.how_many()
經過標記一個 @classmethod,該方法將綁定到 Person 類上,而非類的實例。類方法的第一個參數將傳入類自己,通
常將參數名命名爲 cls,上面的 cls.count 實際上至關於 Person.count。
由於是在類上調用,而非實例上調用,所以類方法沒法得到任何實例變量,只能得到類的引用。
若是已經定義了Person類,須要定義新的Student和Teacher類時,能夠直接從Person類繼承:
class Person(object):
def __init__(self, name, gender):
self.name = name
self.gender = gender
定義Student類時,只須要把額外的屬性加上,例如score:
class Student(Person):
def __init__(self, name, gender, score):
super(Student, self).__init__(name, gender)
self.score = score
必定要用 super(Student, self).__init__(name, gender) 去初始化父類,不然,繼承自 Person 的 Student 將沒有 name 和 gender。
函數super(Student, self)將返回當前類繼承的父類,即 Person ,而後調用__init__()方法,注意self參數已在
super()中傳入,在__init__()中將隱式傳遞,不須要寫出(也不能寫)。
當咱們拿到變量 p、s、t 時,能夠使用 isinstance 判斷類型:
>>> isinstance(p, Person)
True # p是Person類型
>>> isinstance(p, Student)
False # p不是Student類型
>>> isinstance(p, Teacher)
False # p不是Teacher類型
對於實例變量,dir()返回全部實例屬性,包括`__class__`這類有特殊意義的屬性。注意到方法`whoAmI`也是 s 的一個屬性。
如何去掉`__xxx__`這類的特殊屬性,只保留咱們本身定義的屬性?回顧一下filter()函數的用法。
dir()返回的屬性是字符串列表,若是已知一個屬性名稱,要獲取或者設置對象的屬性,就須要用 getattr() 和 setattr( )函數了:
>>> getattr(s, 'name') # 獲取name屬性
'Bob'
>>> setattr(s, 'name', 'Adam') # 設置新的name屬性
>>> s.name
'Adam'
>>> getattr(s, 'age') # 獲取age屬性,可是屬性不存在,報錯:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'age'
>>> getattr(s, 'age', 20) # 獲取age屬性,若是屬性不存在,就返回默認值20:
20
若是要把一個類的實例變成 str,就須要實現特殊方法__str__(),Python 定義了__str__()和__repr__()兩種方法,
__str__()用於顯示給用戶,而__repr__()用於顯示給開發人員。
有一個偷懶的定義__repr__的方法:
class Person(object):
def __init__(self, name, gender):
self.name = name
self.gender = gender
def __str__(self):
return '(Person: %s, %s)' % (self.name, self.gender)
__repr__ = __str__
要讓 len() 函數工做正常,類必須提供一個特殊方法__len__(),它返回元素的個數。例如,咱們寫一個 Students 類,把名字傳進去:
class Students(object):
def __init__(self, *args):
self.names = args
def __len__(self):
return len(self.names)
對 int、str 等內置數據類型排序時,Python的 sorted() 按照默認的比較函數 cmp 排序,可是,若是對一組
Student 類的實例排序時,就必須提供咱們本身的特殊方法 __cmp__():
class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
def __str__(self):
return '(%s: %s)' % (self.name, self.score)
__repr__ = __str__
def __cmp__(self, s):
if self.name < s.name:
return -1
elif self.name > s.name:
return 1
else:
return 0
上述 Student 類實現了__cmp__()方法,__cmp__用實例自身self和傳入的實例 s 進行比較,若是 self 應該排在前
面,就返回 -1,若是 s 應該排在前面,就返回1,若是二者至關,返回 0。全部的函數都是可調用對象。
一個類實例也能夠變成一個可調用對象,只須要實現一個特殊方法__call__()。
咱們把 Person 類變成一個可調用對象:
class Person(object):
def __init__(self, name, gender):
self.name = name
self.gender = gender
def __call__(self, friend):
print 'My name is %s...' % self.name
print 'My friend is %s...' % friend
如今能夠對 Person 實例直接調用:
>>> p = Person('Bob', 'male')
>>> p('Tim')
My name is Bob...
My friend is Tim...
Python進階(二十一)-Python學習進階資料
學習Python已經將近2周了,掌握了基本的語法,並學習了簡單的爬蟲操做,現將相關學習資料整理以下。大部分資料均取材於慕課網,感受一路學下來受益不淺。前端
固然,這其中也不乏收費的教學視頻。不過,Maybe能夠在別的地方找到該資源~(竊喜)java
注
Demonode
Python進階(一)-初識Python數據元素:列表&元組
Python不像JS或者PHP這種弱類型語言裏在字符串鏈接時會自動轉換類型,而是直接報錯。要解決這個方法只有提早把int轉成string,而後再拼接字符串便可。python
如代碼:mysql
1
2
3
4
5
|
str = '你的分數是:'
num = 82
text = str + num + '分 | 瓊臺博客'
print text
|
執行結果nginx
直接報錯:TypeError: cannot concatenate 'str' and 'int' objectsgit
解決這個方法只有提早把num轉換爲字符串類型,能夠使用bytes函數把int型轉換爲string型。
代碼:
1
2
3
4
5
6
|
str = '你的分數是:'
num = 82
num = bytes(num)
text = str + num + '分 | 瓊臺博客'
print text
|
結果搞定:
畢業論文已完成,下面就是等待盲審結果了。在此期間,已感受論文無從看起。就學習一下Python吧,據說這是一門很神奇的語言。下面言歸正傳~
在線文檔查詢:點擊查看
IDE:IntelJ。
有關IntelJ的安裝與註冊詳見博文《IntelliJ IDEA 2016註冊方法和註冊碼》。
下面介紹一下Python中幾種不熟悉的數據元素:列表、元組、字典、時間。
1列表
1.1初始化列表
list=['physics', 'chemistry', 1997, 2000];
1.2訪問列表中的值
list[0]
1.3更新列表
nums[0]="ljq";
1.4刪除列表元素
del nums[0];
1.5列表腳本操做符
列表對+和的操做符與字符串類似。+號用於組合列表,號用於重複列表,例如:
print len([1, 2, 3]); print [1, 2, 3] + [4, 5, 6]; print ['Hi!'] * 4; print 3 in [1, 2, 3] for x in [1, 2, 3]: print x,
1.6列表截取
L=['spam', 'Spam', 'SPAM!']; print L[2]; #'SPAM!' print L[-2]; #'Spam' print L[1:]; #['Spam', 'SPAM!']
1.7列表函數&方法
list.append(obj) list.count(obj) list.extend(seq) list.index(obj) list.insert(index, obj) list.pop(obj=list[-1]) list.remove(obj) list.reverse() list.sort([func])
2元組(tuple)
Python的元組與列表相似,不一樣之處在於元組的元素不能修改;元組使用小括號(),列表使用方括號[];元組建立很簡單,只須要在括號中添加元素,並使用逗號(,)隔開便可,
tup1 = ('physics', 'chemistry', 1997, 2000);
建立空元組,例如:
tup = ();
元組中只有一個元素時,須要在元素後面添加逗號,例如:
tup1 = (50,);
元組與字符串相似,下標索引從0開始,能夠進行截取,組合等。
2.1訪問元組
tup1 = ('physics', 'chemistry', 1997, 2000); tup1[0]
2.2修改元組
元組中的元素值是不容許修改的,但咱們能夠對元組進行鏈接組合,例如:
tup1 = (12, 34.56); tup2 = ('abc', 'xyz');
tup1[0] = 100; tup3 = tup1 + tup2; print tup3;
2.3刪除元組
元組中的元素值是不容許刪除的,能夠使用del語句來刪除整個元組,例如:
tup = ('physics', 'chemistry', 1997, 2000); print tup; del tup;
2.4元組運算符
與字符串同樣,元組之間能夠使用+號和*號進行運算。這就意味着他們能夠組合和複製,運算後會生成一個新的元組。
2.5元組索引&截取
L = ('spam', 'Spam', 'SPAM!'); print L[2]; #'SPAM!' print L[-2]; #'Spam' print L[1:]; #['Spam', 'SPAM!']
2.6元組內置函數
Python進階(二)-初識Python數據元素:字典&時間
3字典
3.1字典簡介
字典(dic dictionary)是除列表以外python中最靈活的內置數據結構類型。 列表是有序的對象結合,字典是無序的對象集合。二者之間的區別在於:字典當中的元素是經過鍵來存取的,而不是經過偏移存取。
字典由鍵和對應的值組成。字典也被稱做關聯數組或哈希表。基本語法以下:
也可如此建立字典:
每一個鍵與值必須用冒號隔開(:),每對用逗號分割,總體放在花括號中({})。鍵必須獨一無二,但值則沒必要;值能夠取任何數據類型,但必須是不可變的,如字符串,數或元組。
3.2訪問字典裏的值
3.3修改字典
向字典添加新內容的方法是增長新的鍵/值對,修改或刪除已有鍵/值對。
以下實例:
3.4刪除字典
3.5字典內置函數&方法
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
4日期和時間
4.1獲取當前時間
說明:time.struct_time(tm_year=2014, tm_mon=3, tm_mday=21, tm_hour=15, tm_min=13, tm_sec=56, tm_wday=4, tm_yday=80, tm_isdst=0)屬於struct_time元組,struct_time元組具備以下屬性:
4.2獲取格式化的時間
能夠根據需求選取各類格式,可是最簡單的獲取可讀的時間模式的函數是asctime():
4.2.1日期轉換爲字符串
首選:print time.strftime(‘%Y-%m-%d %H:%M:%S’);
其次:print datetime.datetime.strftime(datetime.datetime.now(), ‘%Y-%m-%d %H:%M:%S’)
最後:print str(datetime.datetime.now())[:19]
4.2.2字符串轉換爲日期
4.2.3獲取日期差
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
4.2.4獲取時間差
注意時間是浮點數,帶毫秒。
那麼要獲取當前時間,須要格式化一下:
4.2.5獲取上個月最後一天
4.2.6字符串日期格式化爲秒數
返回浮點類型
4.2.7日期格式化爲秒數
返回浮點類型
4.2.8秒數轉字符串
Python進階(三)-函數式編程之reduce()
官方解釋以下:
Apply function of two arguments cumulatively to the items of sequence, from left to right, so as to reduce the sequence to a single value. For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates ((((1+2)+3)+4)+5). The left argument, x, is the accumulated value and the right argument, y, is the update value from the sequence. If the optional initializer is present, it is placed before the items of the sequence in the calculation, and serves as a default when the sequence is empty. If initializer is not given and sequence contains only one item, the first item is returned.
格式: reduce (func, seq[, init()])
reduce()函數即爲化簡函數,它的執行過程爲:每一次迭代,都將上一次的迭代結果(注:第一次爲init元素,若是沒有指定init則爲seq的第一個元素)與下一個元素一同傳入二元func函數中去執行。在reduce()函數中,init是可選的,若是指定,則做爲第一次迭代的第一個元素使用,若是沒有指定,就取seq中的第一個元素。
舉例
有一個序列集合,例如[1,1,2,3,2,3,3,5,6,7,7,6,5,5,5],統計這個集合全部鍵的重複個數,例如1出現了兩次,2出現了兩次等。大體的思路就是用字典存儲,元素就是字典的key,出現的次數就是字典的value。方法依然不少
第一種:for循環判斷
第二種:比較取巧的,先把列表用set方式去重,而後用列表的count方法
第三種:用reduce方式
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
經過上面的例子發現,凡是要對一個集合進行操做的,而且要有一個統計結果的,可以用循環或者遞歸方式解決的問題,通常狀況下均可以用reduce方式實現。
Python進階(四)-淺談Python閉包
在函數內部定義的函數和外部定義的函數是同樣的,只是他們沒法被外部訪問:
將 g 的定義移入函數 f 內部,防止其餘代碼調用 g:
可是,考察定義的 calc_sum 函數:
注意: 發現無法把 lazy_sum 移到 calc_sum 的外部,由於它引用了 calc_sum 的參數 lst。
- 像這種內層函數引用了外層函數的變量(參數也算變量),而後返回內層函數的狀況,稱爲閉包(Closure)。
閉包的特色是返回的函數還引用了外層函數的局部變量,因此,要正確使用閉包,就要確保引用的局部變量在函數返回後不能變。舉例以下:
你可能認爲調用f1(),f2()和f3()結果應該是1,4,9,但實際結果所有都是 9(請本身動手驗證)。
緣由就是當count()函數返回了3個函數時,這3個函數所引用的變量 i 的值已經變成了3。因爲f一、f二、f3並無被調用,因此,此時他們並未計算 i*i,當 f1 被調用時:
所以,返回函數不要引用任何循環變量,或者後續會發生變化的變量。
舉例
返回閉包不能引用循環變量,請改寫count()函數,讓它正確返回能計算1x一、2x二、3x3的函數。
考察下面的函數 f:
它能夠正確地返回一個閉包g,g所引用的變量j不是循環變量,所以將正常執行。
在count函數的循環內部,若是藉助f函數,就能夠避免引用循環變量i。
參考代碼:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
程序實例
Python進階(五)-淺談python匿名函數
高階函數能夠接收函數作參數,有些時候,咱們不須要顯式地定義函數,直接傳入匿名函數更方便。
在Python中,對匿名函數提供了有限支持。仍是以map()函數爲例,計算 f(x)=x2 時,除了定義一個f(x)的函數外,還能夠直接傳入匿名函數:
經過對比能夠看出,匿名函數 lambda x: x * x 實際上就是:
- 關鍵字lambda 表示匿名函數,冒號前面的 x 表示函數參數。
匿名函數有個限制,就是隻能有一個表達式,不寫return,返回值就是該表達式的結果。
使用匿名函數,能夠沒必要定義函數名,直接建立一個函數對象,不少時候能夠簡化代碼:
返回函數的時候,也能夠返回匿名函數:
舉例
利用匿名函數簡化如下代碼:
定義匿名函數時,沒有return關鍵字,且表達式的值就是函數返回值。
參考代碼:
Python進階(六)-python編寫無參數decorator
Python的 decorator 本質上就是一個高階函數,它接收一個函數做爲參數,而後,返回一個新函數。
使用 decorator 用Python提供的 @ 語法,這樣能夠避免手動編寫 f = decorate(f) 這樣的代碼。
考察一個@log的定義:
對於階乘函數,@log工做得很好:
結果:
call factorial()…
3628800
可是,對於參數不是一個的函數,調用將報錯:
結果:
Traceback (most recent call last):
File 「test.py」, line 15, in
print add(1,2)
TypeError: fn() takes exactly 1 argument (2 given)
由於 add() 函數須要傳入兩個參數,可是 @log 寫死了只含一個參數的返回函數。
要讓 @log 自適應任何參數定義的函數,能夠利用Python的 *args 和 **kw,保證任意個數的參數老是能正常調用:
如今,對於任意函數,@log 都能正常工做。
舉例
請編寫一個@performance,它能夠打印出函數調用的時間。
計算函數調用的時間能夠記錄調用先後的當前時間戳,而後計算兩個時間戳的差。
參考代碼:
Python進階(七)-淺談python3和Python2的區別
無論使用何種版本的Python語言,都須要遵循編程規範,不應有的縮進必定不能有。不然會出現莫名其妙的錯誤,以下圖所示:
在應用Python編程時,首先要明確所使用Python版本,由於版本2與3之間存在着不少細節性的差別。稍有不慎就會入坑~下面介紹一下具體應用中的細節性差別。
具體參照:https://docs.python.org/3/whatsnew/3.0.html
print函數
Python3中print爲一個函數,必須用括號括起來;Python2中print爲class)。Python 2 的 print 聲明已經被 print() 函數取代了,這意味着咱們必須包裝咱們想打印在小括號中的對象。
舉例
在Python 2中:
在Python 3中:
reduce()函數
在Python 3裏,reduce()函數已經被從全局名字空間裏移除了,它如今被放置在fucntools模塊裏。使用時要先引入from functools import reduce
try except
try:
except Exception, e :
打開文件
原: file( ….. )
或 open(…..)
改成:
只能用 open(…..)
從鍵盤錄入一個字符串
原: raw_input( 「提示信息」 )
改成: input( 「提示信息」 )
整形除法自動轉爲float
python2:
1/2
2/2
1//2
0
1
0
python3:
1/2
2/2
1//2
0.5
1.0
0
xrange重命名爲range.
!=取代 < >
long重命名爲int.
exec變成函數
Py3.X源碼文件默認使用utf-8編碼,這就使得如下代碼是合法的:
python3中替換python2中cmp函數
Python 3.4.3 的版本中已經沒有cmp函數,被operator模塊代替,在交互模式下使用時,須要導入模塊。在沒有導入模塊狀況下,會出現下面的錯誤:
提示找不到cmp函數了,那麼在python3中該如何使用這個函數呢?
因此要導入模塊
看下面給的內置函數
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
這幾個函數就是用來替換以前的cmp,函數的返回值是布爾值。
除法
- 在python3.0中,/ 如今老是執行真除法,無論操做數的類型,都會返回包含任何餘數的一個浮點結果。// 執行Floor除法,它截除掉餘數而且針對整數操做數返回一個整數,若是有任何一個操做數是浮點數類型,則返回一個浮點數。
- 在python2.6中,/ 表示傳統除法,若是兩個操做數都是整數的話,執行截斷的整數除法(好像是Floor除法????);不然,執行浮點除法(保留餘數,好像是真除法?)。//執行Floor除法,而且像在python3.0中同樣工做,對於整數執行截斷除法,對於浮點數執行浮點除法。
Python進階(八)-編寫帶參數decorator
繼續考察@log 裝飾器:
發現對於被裝飾的函數,log打印的語句是不能變的(除了函數名)。
若是有的函數很是重要,但願打印出’[INFO] call xxx()…’,有的函數不過重要,但願打印出’[DEBUG] call xxx()…’,這時,log函數自己就須要傳入’INFO’或’DEBUG’這樣的參數,相似這樣:
把上面的定義翻譯成高階函數的調用,就是:
上面的語句看上去仍是比較繞,再展開一下:
上面的語句又至關於:
因此,帶參數的log函數首先返回一個decorator函數,再讓這個decorator函數接收my_func並返回新函數:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
執行結果:
[DEBUG] test()…
None
對於這種3層嵌套的decorator定義,你能夠先把它拆開:
拆開之後會發現,調用會失敗,由於在3層嵌套的decorator定義中,最內層的wrapper引用了最外層的參數prefix,因此,把一個閉包拆成普通的函數調用會比較困難。不支持閉包的編程語言要實現一樣的功能就須要更多的代碼。
舉例
在@performance實現打印秒的同時,請給 @performace 增長一個參數,容許傳入’s’或’ms’:
要實現帶參數的@performance,就須要實現:
須要3層嵌套的decorator來實現。
參考代碼:
Python進階(九)-Python陷阱:Nonetype
今天解決一位網友的問題,內容以下:
請教代碼問題
結果:
[1, 4, 9, 16]
None
這樣寫輸出爲何有None
針對這一問題,本身在IDEA中進行了調試,發現果真多輸出了一行None。出現這一現象確實很使人費解。
本身寫了簡單的測試語句,以下:
經過斷點調試,內容以下:
發現b的值確實爲None,且其類型爲NoneType。
那麼什麼是Nonetype?
要理解這個,首先要理解Python對象,python對象具備三個特性:身份、類型、值。
這三個特性在對象建立時被賦值。只有值能夠改變,其餘只讀。類型自己也是對象。
Null與None是Python的特殊類型,Null對象或者是None Type,它只有一個值None.
它不支持任何運算也沒有任何內建方法. None和任何其餘的數據類型比較永遠返回False。
None有本身的數據類型NoneType。你能夠將None複製給任何變量,可是你不能建立其餘NoneType對象。
一句話總結:Null對象是python對象,又叫作NoneType,None是這個對象的值。
看過了NoneType的解釋,之因此出現None就很好理解了。
NoneType之因此出現是由於定義了一個變量或函數,卻沒有值或者返回值,所以會默認值爲None。
而在上面的程序中,雖然高階函數calc_prod()有返回值ff,可是ff()卻沒有返回值,則傳遞到外層函數calc_prod()一樣沒有返回值,故輸出了None。 若代碼改成以下所示,則能夠完美實現列表的輸出。
Python進階(十)-Python 編程規範
在學習一門新的編程語言時,掌握其良好的編程規範可避免一些細節性錯誤的發生。去除一些沒必要要的學習障礙。
分號
不要在行尾加分號, 也不要用分號將兩條命令放在同一行.
行長度
每行不超過80個字符
例外:
不要使用反斜槓鏈接行.
Python會將圓括號, 中括號和花括號中的行隱式鏈接起來 , 你能夠利用這個特色. 若是須要, 你能夠在表達式外圍增長一對額外的圓括號.
若是一個文本字符串在一行放不下, 能夠使用圓括號來實現隱式行鏈接:
在註釋中,若是必要,將長的URL放在一行上。
Yes:
No:
注意上面例子中的元素縮進; 你能夠在本文的縮進部分找到解釋.
括號
寧缺毋濫的使用括號
除非是用於實現行鏈接, 不然不要在返回語句或條件語句中使用括號. 不過在元組兩邊使用括號是能夠的.
Yes:
No:
縮進
用4個空格來縮進代碼
絕對不要用tab, 也不要tab和空格混用. 對於行鏈接的狀況, 你應該要麼垂直對齊換行的元素(見行長度部分的示例), 或者使用4空格的懸掛式縮進(這時第一行不該該有參數):
Yes:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
No:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
空行
頂級定義之間空兩行, 方法定義之間空一行
頂級定義之間空兩行, 好比函數或者類定義. 方法定義, 類定義與第一個方法之間, 都應該空一行. 函數或方法中, 某些地方要是你以爲合適, 就空一行.
空格
按照標準的排版規範來使用標點兩邊的空格。
括號內不要有空格.
Yes:
No:
不要在逗號, 分號, 冒號前面加空格, 但應該在它們後面加(除了在行尾).
Yes:
if x == 4 :
print x , y
x , y = y , x
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
Shebang
大部分.py文件沒必要以#!做爲文件的開始. 根據 PEP-394 , 程序的main文件應該以 #!/usr/bin/python2或者 #!/usr/bin/python3開始.
(譯者注: 在計算機科學中, Shebang (也稱爲Hashbang)是一個由井號和歎號構成的字符串行(#!), 其出如今文本文件的第一行的前兩個字符. 在文件中存在Shebang的狀況下, 類Unix操做系統的程序載入器會分析Shebang後的內容, 將這些內容做爲解釋器指令, 並調用該指令, 並將載有Shebang的文件路徑做爲該解釋器的參數. 例如, 以指令#!/bin/sh開頭的文件在執行時會實際調用/bin/sh程序.)
#!先用於幫助內核找到Python解釋器, 可是在導入模塊時, 將會被忽略. 所以只有被直接執行的文件中才有必要加入#!.
註釋
確保對模塊, 函數, 方法和行內註釋使用正確的風格
文檔字符串
Python有一種獨一無二的的註釋方式: 使用文檔字符串. 文檔字符串是包, 模塊, 類或函數裏的第一個語句. 這些字符串能夠經過對象的doc成員被自動提取, 而且被pydoc所用. (你能夠在你的模塊上運行pydoc試一把, 看看它長什麼樣). 咱們對文檔字符串的慣例是使用三重雙引號」「」( PEP-257 ). 一個文檔字符串應該這樣組織: 首先是一行以句號, 問號或驚歎號結尾的概述(或者該文檔字符串單純只有一行). 接着是一個空行. 接着是文檔字符串剩下的部分, 它應該與文檔字符串的第一行的第一個引號對齊. 下面有更多文檔字符串的格式化規範.
模塊
每一個文件應該包含一個許可樣板. 根據項目使用的許可(例如, Apache 2.0, BSD, LGPL, GPL), 選擇合適的樣板.
函數和方法
下文所指的函數,包括函數, 方法, 以及生成器.
一個函數必需要有文檔字符串, 除非它知足如下條件:
外部不可見
很是短小
簡單明瞭
文檔字符串應該包含函數作什麼, 以及輸入和輸出的詳細描述. 一般, 不該該描述」怎麼作」, 除非是一些複雜的算法. 文檔字符串應該提供足夠的信息, 當別人編寫代碼調用該函數時, 他不須要看一行代碼, 只要看文檔字符串就能夠了. 對於複雜的代碼, 在代碼旁邊加註釋會比使用文檔字符串更有意義.
關於函數的幾個方面應該在特定的小節中進行描述記錄, 這幾個方面以下文所述. 每節應該以一個標題行開始. 標題行以冒號結尾. 除標題行外, 節的其餘內容應被縮進2個空格.
Args:
列出每一個參數的名字, 並在名字後使用一個冒號和一個空格, 分隔對該參數的描述.若是描述太長超過了單行80字符,使用2或者4個空格的懸掛縮進(與文件其餘部分保持一致). 描述應該包括所需的類型和含義. 若是一個函數接受*foo(可變長度參數列表)或者**bar (任意關鍵字參數), 應該詳細列出*foo和**bar.
Returns: (或者 Yields: 用於生成器)
描述返回值的類型和語義. 若是函數返回None, 這一部分能夠省略.
Raises:
列出與接口有關的全部異常.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
類
類應該在其定義下有一個用於描述該類的文檔字符串. 若是你的類有公共屬性(Attributes), 那麼文檔中應該有一個屬性(Attributes)段. 而且應該遵照和函數參數相同的格式.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
塊註釋和行註釋
最須要寫註釋的是代碼中那些技巧性的部分. 若是你在下次代碼審查的時候必須解釋一下, 那麼你應該如今就給它寫註釋. 對於複雜的操做, 應該在其操做開始前寫上若干行註釋. 對於不是一目瞭然的代碼, 應在其行尾添加註釋.
‘# We use a weighted dictionary search to find out where i is in
‘# the array. We extrapolate position based on the largest num
‘# in the array and the array size and then do binary search to
‘# get the exact number.’
if i & (i-1) == 0: # true iff i is a power of 2
爲了提升可讀性, 註釋應該至少離開代碼2個空格.
另外一方面, 毫不要描述代碼. 假設閱讀代碼的人比你更懂Python, 他只是不知道你的代碼要作什麼.
‘# BAD COMMENT: Now go through the b array and make sure whenever i occurs
‘# the next element is i+1
類
若是一個類不繼承自其它類, 就顯式的從object繼承. 嵌套類也同樣.
Yes: class SampleClass(object):
pass
class OuterClass(object):
class InnerClass(object):
pass
class ChildClass(ParentClass):
「」「Explicitly inherits from another class already.」「」
No: class SampleClass:
pass
class OuterClass:
class InnerClass:
pass
繼承自 object 是爲了使屬性(properties)正常工做, 而且這樣能夠保護你的代碼, 使其不受Python 3的一個特殊的潛在不兼容性影響. 這樣作也定義了一些特殊的方法, 這些方法實現了對象的默認語義, 包括 new, init, delattr, getattribute, setattr, hash, repr, and str .
字符串
即便參數都是字符串, 使用%操做符或者格式化方法格式化字符串. 不過也不能一律而論, 你須要在+和%之間好好斷定.
Yes: x = a + b
x = ‘%s, %s!’ % (imperative, expletive)
x = ‘{}, {}!’.format(imperative, expletive)
x = ‘name: %s; score: %d’ % (name, n)
x = ‘name: {}; score: {}’.format(name, n)
No: x = ‘%s%s’ % (a, b) # use + in this case
x = ‘{}{}’.format(a, b) # use + in this case
x = imperative + ‘, ’ + expletive + ‘!’
x = ‘name: ’ + name + ‘; score: ’ + str(n)
避免在循環中用+和+=操做符來累加字符串. 因爲字符串是不可變的, 這樣作會建立沒必要要的臨時對象, 而且致使二次方而不是線性的運行時間. 做爲替代方案, 你能夠將每一個子串加入列表, 而後在循環結束後用 .join 鏈接列表. (也能夠將每一個子串寫入一個 cStringIO.StringIO 緩存中.)
Yes: items = [‘
‘]
for last_name, first_name in employee_list:
items.append(‘’ % (last_name, first_name))
items.append(‘
‘)
employee_table = 」.join(items)
No: employee_table = ‘’
for last_name, first_name in employee_list:
employee_table += ‘’ % (last_name, first_name)
employee_table += ‘
’
在同一個文件中, 保持使用字符串引號的一致性. 使用單引號’或者雙引號」之一用以引用字符串, 並在同一文件中沿用. 在字符串內能夠使用另一種引號, 以免在字符串中使用. GPyLint已經加入了這一檢查.
(譯者注:GPyLint疑爲筆誤, 應爲PyLint.)
Yes:
Python(‘Why are you hiding your eyes?’)
Gollum(「I’m scared of lint errors.」)
Narrator(‘「Good!」 thought a happy Python reviewer.’)
No:
Python(「Why are you hiding your eyes?」)
Gollum(‘The lint. It burns. It burns us.’)
Gollum(「Always the great lint. Watching. Watching.」)
爲多行字符串使用三重雙引號」「」而非三重單引號’‘’. 當且僅當項目中使用單引號’來引用字符串時, 纔可能會使用三重’‘’爲非文檔字符串的多行字符串來標識引用. 文檔字符串必須使用三重雙引號」「」. 不過要注意, 一般用隱式行鏈接更清晰, 由於多行字符串與程序其餘部分的縮進方式不一致.
Yes:
print (「This is much nicer.\n」
「Do it this way.\n」)
No:
print 「」「This is pretty ugly.
Don’t do this.
「」「
文件和sockets
在文件和sockets結束時, 顯式的關閉它.
除文件外, sockets或其餘相似文件的對象在沒有必要的狀況下打開, 會有許多反作用, 例如:
- 1.它們可能會消耗有限的系統資源, 如文件描述符. 若是這些資源在使用後沒有及時歸還系統, 那麼用於處理這些對象的代碼會將資源消耗殆盡.
- 2.持有文件將會阻止對於文件的其餘諸如移動、刪除之類的操做.
並且, 幻想當文件對象析構時, 文件和sockets會自動關閉, 試圖將文件對象的生命週期和文件的狀態綁定在一塊兒的想法, 都是不現實的. 由於有以下緣由:
- 1.沒有任何方法能夠確保運行環境會真正的執行文件的析構.不一樣的Python實現採用不一樣的內存管理技術, 好比延時垃圾處理機制. 延時垃圾處理機制可能會致使對象生命週期被任意無限制的延長.
- 2.對於文件意外的引用,會致使對於文件的持有時間超出預期(好比對於異常的跟蹤, 包含有全局變量等).
推薦使用 「with」語句 以管理文件:
對於不支持使用」with」語句的相似文件的對象,使用
TODO註釋
爲臨時代碼使用TODO註釋, 它是一種短時間解決方案. 不算完美, 但夠好了.
TODO註釋應該在全部開頭處包含」TODO」字符串, 緊跟着是用括號括起來的你的名字, email地址或其它標識符. 而後是一個可選的冒號. 接着必須有一行註釋, 解釋要作什麼. 主要目的是爲了有一個統一的TODO格式, 這樣添加註釋的人就能夠搜索到(並能夠按需提供更多細節). 寫了TODO註釋並不保證寫的人會親自解決問題. 當你寫了一個TODO, 請註上你的名字.
‘# TODO(kl@gmail.com): Use a 「*」 here for string repetition.
‘# TODO(Zeke) Change this to use relations.
「`
若是你的TODO是」未來作某事」的形式, 那麼請確保你包含了一個指定的日期(「2009年11月解決」)或者一個特定的事件(「等到全部的客戶均可以處理XML請求就移除這些代碼」).
導入格式
每一個導入應該獨佔一行
Yes: import os
import sys
No: import os, sys
導入總應該放在文件頂部, 位於模塊註釋和文檔字符串以後, 模塊全局變量和常量以前. 導入應該按照從最通用到最不通用的順序分組:
標準庫導入
第三方庫導入
應用程序指定導入
每種分組中, 應該根據每一個模塊的完整包路徑按字典序排序, 忽略大小寫.
import foo
from foo import bar
from foo.bar import baz
from foo.bar import Quux
from Foob import ar
語句
一般每一個語句應該獨佔一行
不過, 若是測試結果與測試語句在一行放得下, 你也能夠將它們放在同一行. 若是是if語句, 只有在沒有else時才能這樣作. 特別地, 毫不要對 try/except 這樣作, 由於try和except不能放在同一行.
Yes:
if foo: bar(foo)
No:
if foo: bar(foo)
else: baz(foo)
try: bar(foo)
except ValueError: baz(foo)
try:
bar(foo)
except ValueError: baz(foo)
訪問控制
在Python中, 對於瑣碎又不過重要的訪問函數, 你應該直接使用公有變量來取代它們, 這樣能夠避免額外的函數調用開銷. 當添加更多功能時, 你能夠用屬性(property)來保持語法的一致性.
(譯者注: 重視封裝的面向對象程序員看到這個可能會很反感, 由於他們一直被教育: 全部成員變量都必須是私有的! 其實, 那真的是有點麻煩啊. 試着去接受Pythonic哲學吧)
另外一方面, 若是訪問更復雜, 或者變量的訪問開銷很顯著, 那麼你應該使用像 get_foo() 和 set_foo() 這樣的函數調用. 若是以前的代碼行爲容許經過屬性(property)訪問 , 那麼就不要將新的訪問函數與屬性綁定. 這樣, 任何試圖經過老方法訪問變量的代碼就無法運行, 使用者也就會意識到複雜性發生了變化.
命名
module_name, package_name, ClassName, method_name, ExceptionName, function_name, GLOBAL_VAR_NAME, instance_var_name, function_parameter_name, local_var_name.
應該避免的名稱
單字符名稱, 除了計數器和迭代器.
包/模塊名中的連字符(-)
雙下劃線開頭並結尾的名稱(Python保留, 例如init)
命名約定
所謂」內部(Internal)」表示僅模塊內可用, 或者, 在類內是保護或私有的.
用單下劃線(_)開頭表示模塊變量或函數是protected的(使用import * from時不會包含).
用雙下劃線(__)開頭的實例變量或方法表示類內私有.
將相關的類和頂級函數放在同一個模塊裏. 不像Java, 不必限制一個類一個模塊.
對類名使用大寫字母開頭的單詞(如CapWords, 即Pascal風格), 可是模塊名應該用小寫加下劃線的方式(如lower_with_under.py). 儘管已經有不少現存的模塊使用相似於CapWords.py這樣的命名, 但如今已經不鼓勵這樣作, 由於若是模塊名碰巧和類名一致, 這會讓人困擾.
Python之父Guido推薦的規範
Type Public Internal
Modules lower_with_under _lower_with_under
Packages lower_with_under
Classes CapWords _CapWords
Exceptions CapWords
Functions lower_with_under() _lower_with_under()
Global/Class Constants CAPS_WITH_UNDER _CAPS_WITH_UNDER
Global/Class Variables lower_with_under _lower_with_under
Instance Variables lower_with_under _lower_with_under (protected) or __lower_with_under (private)
Method Names lower_with_under() _lower_with_under() (protected) or __lower_with_under() (private)
Function/Method Parameters lower_with_under
Local Variables lower_with_under
Main
即便是一個打算被用做腳本的文件, 也應該是可導入的. 而且簡單的導入不該該致使這個腳本的主功能(main functionality)被執行, 這是一種反作用. 主功能應該放在一個main()函數中.
在Python中, pydoc以及單元測試要求模塊必須是可導入的. 你的代碼應該在執行主程序前老是檢查 if name == ‘main’ , 這樣當模塊被導入時主程序就不會被執行.
def main():
…
if name == ‘main‘:
main()
全部的頂級代碼在模塊導入時都會被執行. 要當心不要去調用函數, 建立對象, 或者執行那些不該該在使用pydoc時執行的操做.
Python進階(十一)-定義實例方法
一個實例的私有屬性就是以__開頭的屬性,沒法被外部訪問。那這些屬性定義有什麼用?
雖然私有屬性沒法從外部訪問,可是,從類的內部是能夠訪問的。除了能夠定義實例的屬性外,還能夠定義實例的方法。
實例的方法就是在類中定義的函數,它的第一個參數永遠是 self,指向調用該方法的實例自己,其餘參數和一個普通函數是徹底同樣的。
get_name(self) 就是一個實例方法,它的第一個參數是self。init(self, name)其實也可看作是一個特殊的實例方法。
調用實例方法必須在實例上調用:
在實例方法內部,能夠訪問全部實例屬性,這樣,若是外部須要訪問私有屬性,能夠經過方法調用得到,這種數據封裝的形式除了能保護內部數據一致性外,還能夠簡化外部調用的難度。
舉例
請給 Person 類增長一個私有屬性 __score,表示分數,再增長一個實例方法 get_grade(),能根據 __score 的值分別返回 A-優秀, B-及格, C-不及格三檔。
注意get_grade()是實例方法,第一個參數爲self。
參考代碼:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
運行結果
Python進階(十二)-淺談python中的方法
咱們在 class 中定義的實例方法其實也是屬性,它其實是一個函數對象:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
也就是說,p1.get_grade 返回的是一個函數對象,但這個函數是一個綁定到實例的函數,p1.get_grade() 纔是方法調用。
由於方法也是一個屬性,因此,它也能夠動態地添加到實例上,只是須要用 types.MethodType() 把一個函數變爲一個方法:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
給一個實例動態添加方法並不常見,直接在class中定義要更直觀。
舉例
因爲屬性能夠是普通的值對象,如 str,int 等,也能夠是方法,還能夠是函數,你們看看下面代碼的運行結果,請想想 p1.get_grade 爲何是函數而不是方法:
直接把 lambda 函數賦值給 self.get_grade 和綁定方法有所不一樣,函數調用不須要傳入 self,可是方法調用須要傳入 self。
Python進階(十三)-淺談sorted 函數應用
衆所周知,def cmp 做爲方法存在,用sort對實例進行排序時,會用到class 中的cmp。可是,在python3中,取消了 sorted對cmp的支持。
python3 中有關排序的sorted方法以下:
其中,key接受一個函數,這個函數只接受一個元素,默認爲None。
reverse是一個布爾值。若是設置爲True,列表元素將被倒序排列,默認爲False。
下面着重介紹key的做用原理:
key指定一個接收一個參數的函數,這個函數用於從每一個元素中提取一個用於比較的關鍵字。默認值爲None 。
例1
結果:[(‘dave’,’B’, 10), (‘jane’, ‘B’, 12), (‘john’, ‘A’, 15)]
例2
這是一個字符串排序,排序規則:小寫<大寫<奇數<偶數
s = ‘asdf234GDSdsf23’ #排序:小寫-大寫-奇數-偶數
原理:先比較元組的第一個值,若是相等就比較元組的下一個值,以此類推。
先看一下Boolean value 的排序:
print(sorted([True,Flase]))===>結果[False,True]
Boolean 的排序會將 False 排在前,True排在後 .
- 1.x.isdigit()的做用是把數字放在前邊,字母放在後邊.
- 2.x.isdigit() and int(x) % 2 == 0的做用是保證奇數在前,偶數在後。
- 3.x.isupper()的做用是在前面基礎上,保證字母小寫在前大寫在後.
- 4.最後的x表示在前面基礎上,對全部類別數字或字母排序。
最後結果:addffssDGS33224
例3
一道面試題:
解題思路:先按照正負排前後,再按照大小排前後。
Python進階(十四)- 基礎課程結課總結:高階函數
在慕課網完成了廖雪峯老師的《Python入門》與《Python進階》兩門基礎課程。在此作一下簡單的知識點小結。
函數式編程
Python特色:
- 不是純函數式編程(容許變量存在);
- 支持高階函數(能夠傳入函數做爲變量);
- 支持閉包(能夠返回函數);
- 有限度的支持匿名函數;
高階函數:
- 變量能夠指向函數;
- 函數的參數能夠接收變量;
- 一個函數能夠接收另外一個函數做爲參數;
內置高階函數map()
map函數有兩個參數,一個是函數,另外一個是列表,返回值爲對傳入的列表中每個元素執行傳入的函數操做以後獲得的列表;
內置高階函數reduce()
reduce函數也有兩個參數,一個是函數,另外一個是列表,返回值爲對list的每個元素反覆調用函數f,獲得最終結果,如下函數爲連乘;
內置高階函數filter()
filter函數接受函數參數f和列表參數lst,f對lst元素進行判斷,返回lst元素中調用f函數結果爲true的元素組成的列表(將不知足f函數條件的元素過濾掉);
自定義排序函數sorted()
sorted函數接受一個列表lst和一個函數參數f,f爲自定義的比較lst元素大小的函數,返回值爲lst中元素按f函數排列的列表;
返回函數:
閉包
內層函數使用外層函數的參數,而後返回內層函數;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
匿名函數
傳入函數參數不須要顯式定義函數,能夠用lambda x:statement x爲參數,statement爲對參數執行的語句;
裝飾器
給函數添加新功能,並簡化該函數調用;
無參數裝飾器
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
帶參數裝飾器
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
利用functool.wraps做用在返回的新函數上,使得調用裝飾器之後不改變原函數的信息
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
偏函數
functools.partial(f,f的默認參數) 減小須要提供給f的參數
Python進階(十五)-file文件操做
Python下文件操做與Java差很少。打開文件的模式有三種:
- r,只讀模式(默認)。
- w,只寫模式。【不可讀;不存在則建立;存在則刪除內容;由於會清空原有文件的內容,必定要慎用】
- a,追加模式。【可讀; 不存在則建立;存在則只追加內容;】
注意最後要記得關閉文件:f.close()
python只能將字符串寫入到文本文件。要將數值數據存儲到文本本件中,必須先試用函數str()將其轉換爲字符串格式。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
參考資料
http://www.yiibai.com/python3/file_methods.html
Python進階(十六)-正則表達式
正則表達式是一個特殊的字符序列,它能幫助你方便的檢查一個字符串是否與某種模式匹配。
Python 自1.5版本起增長了re 模塊,它提供 Perl 風格的正則表達式模式。
在python中使用正則表達式,須要引入re模塊;下面介紹下該模塊中的一些方法;
compile和match
re模塊中compile用於生成pattern的對象,再經過調用pattern實例的match方法處理文本最終得到match實例;經過使用match得到信息;
re.compile(strPattern[, flag]):
這個方法是Pattern類的工廠方法,用於將字符串形式的正則表達式編譯爲Pattern對象。第二個參數flag是匹配模式,取值能夠使用按位或運算符’|’表示同時生效,好比re.I | re.M。另外,你也能夠在regex字符串中指定模式,好比re.compile(‘pattern’, re.I | re.M)與re.compile(‘(?im)pattern’)是等價的。
可選值有:
- re.I(re.IGNORECASE): 忽略大小寫(括號內是完整寫法,下同)
- M(MULTILINE): 多行模式,改變’^’和’$’的行爲
- S(DOTALL): 點任意匹配模式,改變’.’的行爲
- L(LOCALE): 使預約字符類 \w \W \b \B \s \S 取決於當前區域設定
- U(UNICODE): 使預約字符類 \w \W \b \B \s \S \d \D 取決於unicode定義的字符屬性
- X(VERBOSE): 詳細模式。這個模式下正則表達式能夠是多行,忽略空白字符,並能夠加入註釋。
Match
Match對象是一次匹配的結果,包含了不少關於這次匹配的信息,能夠使用Match提供的可讀屬性或方法來獲取這些信息。
屬性:
- string: 匹配時使用的文本。
- re: 匹配時使用的Pattern對象。
- pos: 文本中正則表達式開始搜索的索引。值與Pattern.match()和Pattern.seach()方法的同名參數相同。
- endpos: 文本中正則表達式結束搜索的索引。值與Pattern.match()和Pattern.seach()方法的同名參數相同。
- lastindex: 最後一個被捕獲的分組在文本中的索引。若是沒有被捕獲的分組,將爲None。
- lastgroup: 最後一個被捕獲的分組的別名。若是這個分組沒有別名或者沒有被捕獲的分組,將爲None。
方法:
group([group1, …])
得到一個或多個分組截獲的字符串;指定多個參數時將以元組形式返回。group1能夠使用編號也能夠使用別名;編號0表明整個匹配的子串;不填寫參數時,返回group(0);沒有截獲字符串的組返回None;截獲了屢次的組返回最後一次截獲的子串。
groups([default]):
以元組形式返回所有分組截獲的字符串。至關於調用group(1,2,…last)。default表示沒有截獲字符串的組以這個值替代,默認爲None。
groupdict([default])
返回以有別名的組的別名爲鍵、以該組截獲的子串爲值的字典,沒有別名的組不包含在內。default含義同上。
start([group])
返回指定的組截獲的子串在string中的起始索引(子串第一個字符的索引)。group默認值爲0。
end([group])
返回指定的組截獲的子串在string中的結束索引(子串最後一個字符的索引+1)。group默認值爲0。
span([group])
返回(start(group), end(group))。
expand(template)
將匹配到的分組代入template中而後返回。template中能夠使用\id或\g、 \g引用分組,但不能使用編號0。\id與\g是等價的;但\10將被認爲是第10個分組,若是你想表達 \1以後是字符’0’,只能使用\g<1>0。
pattern
Pattern對象是一個編譯好的正則表達式,經過Pattern提供的一系列方法能夠對文本進行匹配查找。
Pattern不能直接實例化,必須使用re.compile()進行構造。
Pattern提供了幾個可讀屬性用於獲取表達式的相關信息:
- pattern: 編譯時用的表達式字符串。
- flags: 編譯時用的匹配模式。數字形式。
- groups: 表達式中分組的數量。
- groupindex: 以表達式中有別名的組的別名爲鍵、以該組對應的編號爲值的字典,沒有別名的組不包含在內。
實例方法[ | re模塊方法]:
match(string[, pos[, endpos]]) | re.match(pattern, string[, flags])
這個方法將從string的pos下標處起嘗試匹配pattern;若是pattern結束時仍可匹配,則返回一個Match對象;若是匹配過程當中pattern沒法匹配,或者匹配未結束就已到達endpos,則返回None。
pos和endpos的默認值分別爲0和len(string);re.match()沒法指定這兩個參數,參數flags用於編譯pattern時指定匹配模式。
注意:這個方法並非徹底匹配。當pattern結束時若string還有剩餘字符,仍然視爲成功。想要徹底匹配,能夠在表達式末尾加上邊界匹配符’$’。
search(string[, pos[, endpos]]) | re.search(pattern, string[, flags])
這個方法用於查找字符串中能夠匹配成功的子串。從string的pos下標處起嘗試匹配pattern,若是pattern結束時仍可匹配,則返回一個Match對象;若沒法匹配,則將pos加1從新嘗試匹配;直到pos=endpos時仍沒法匹配則返回None。 pos和endpos的默認值分別爲0和len(string));re.search()沒法指定這兩個參數,參數flags用於編譯pattern時指定匹配模式。
split(string[, maxsplit]) | re.split(pattern, string[, maxsplit])
按照可以匹配的子串將string分割後返回列表。maxsplit用於指定最大分割次數,不指定將所有分割。
findall(string[, pos[, endpos]]) | re.findall(pattern, string[, flags])
搜索string,以列表形式返回所有能匹配的子串。
finditer(string[, pos[, endpos]]) | re.finditer(pattern, string[, flags])
搜索string,返回一個順序訪問每個匹配結果(Match對象)的迭代器。
sub(repl, string[, count]) | re.sub(pattern, repl, string[, count])
使用repl替換string中每個匹配的子串後返回替換後的字符串。 當repl是一個字符串時,能夠使用\id或\g、\g引用分組,但不能使用編號0。 當repl是一個方法時,這個方法應當只接受一個參數(Match對象),並返回一個字符串用於替換(返回的字符串中不能再引用分組)。 count用於指定最多替換次數,不指定時所有替換。
subn(repl, string[, count]) |re.sub(pattern, repl, string[, count])
返回 (sub(repl, string[, count]), 替換次數)。
re.match函數
re.match 嘗試從字符串的起始位置匹配一個模式,若是不是起始位置匹配成功的話,match()就返回none。
函數語法:
re.match(pattern, string, flags=0)
函數參數說明:
匹配成功re.match方法返回一個匹配的對象,不然返回None。
咱們能夠使用group(num) 或 groups() 匹配對象函數來獲取匹配表達式。
實例 1
以上實例運行輸出結果爲:
(0, 3)
None
實例 2
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
以上實例執行結果以下:
matchObj.group() : Cats are smarter than dogs
matchObj.group(1) : Cats
matchObj.group(2) : smarter
re.search方法
re.search 掃描整個字符串並返回第一個成功的匹配。
函數語法:
re.search(pattern, string, flags=0)
函數參數說明:
匹配成功re.search方法返回一個匹配的對象,不然返回None。
咱們能夠使用group(num) 或 groups() 匹配對象函數來獲取匹配表達式。
實例一
實例二
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
輸出:
matchObj.group() : This is my blog
matchObj.group(1) : This
matchObj.group(2) : my
search和match區別
re.match只匹配字符串的開始,若是字符串開始不符合正則表達式,則匹配失敗,函數返回None;而re.search匹配整個字符串,直到找到一個匹配。
實例
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
以上實例運行結果以下:
No match!!
search –> matchObj.group() : dogs
檢索和替換
Python 的re模塊提供了re.sub用於替換字符串中的匹配項。
語法:
re.sub(pattern, repl, string, count=0)
參數:
- pattern : 正則中的模式字符串。
- repl : 替換的字符串,也可爲一個函數。
- string : 要被查找替換的原始字符串。
- count : 模式匹配後替換的最大次數,默認 0 表示替換全部的匹配。
實例
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
以上實例執行結果以下:
電話號碼 : 2004-959-559
電話號碼 : 2004959559
repl 參數是一個函數
如下實例中將字符串中的匹配的數字乘於 2:
執行輸出結果爲:
A46G8HFD1134
正則表達式修飾符 - 可選標誌
正則表達式能夠包含一些可選標誌修飾符來控制匹配的模式。修飾符被指定爲一個可選的標誌。多個標誌能夠經過按位 OR(|) 它們來指定。如 re.I | re.M 被設置成 I 和 M 標誌:
正則表達式模式
模式字符串使用特殊的語法來表示一個正則表達式:
- 字母和數字表示他們自身。一個正則表達式模式中的字母和數字匹配一樣的字符串。
- 多數字母和數字前加一個反斜槓時會擁有不一樣的含義。
- 標點符號只有被轉義時才匹配自身,不然它們表示特殊的含義。
- 反斜槓自己須要使用反斜槓轉義。
- 因爲正則表達式一般都包含反斜槓,因此你最好使用原始字符串來表示它們。模式元素(如 r’/t’,等價於’//t’)匹配相應的特殊字符。
下表列出了正則表達式模式語法中的特殊元素。若是你使用模式的同時提供了可選的標誌參數,某些模式元素的含義會改變。
正則表達式實例
字符匹配
參考資料
http://www.runoob.com/python3/python3-reg-expressions.html
Python進階(十七)-Python 字符串操做
去空格及特殊符號
複製字符串
鏈接字符串
查找字符
比較字符串
掃描字符串是否包含指定的字符
字符串長度
將字符串中的大小寫轉換
追加指定長度的字符串
字符串指定長度比較
複製指定長度的字符
將字符串前n個字符替換爲指定的字符
掃描字符串
翻轉字符串
查找字符串
分割字符串
鏈接字符串
截取字符串
python字符串跟整型互轉
參考資料
http://www.runoob.com/python3/python3-string.html
Python進階(十八)-Python3爬蟲實踐
這篇文章主要介紹瞭如何使用Python3爬取csdn博客訪問量的相關資料,在Python2已實現的基礎上實現Python3爬蟲,對比版本之間的差別所在,須要的朋友能夠參考下。
使用python來獲取本身博客的訪問量,也是後面將要開發項目的一部分,後邊會對博客的訪問量進行分析,以折線圖和餅圖等可視化的方式展現本身博客被訪問的狀況,使本身能更加清楚本身的哪些博客更受關注。其實,在較早以前博客專家自己就有這個功能,不知什麼緣由此功能被取消了。
一.網址分析
進入本身的博客頁面,網址爲:http://blog.csdn.net/sunhuaqiang1。 網址仍是比較好分析的:就是csdn的網址+我的csdn登陸帳號,咱們來看下一頁的網址。
看到第二頁的地址爲:http://blog.csdn.net/sunhuaqiang1/article/list/2後邊的數字表示如今正處於第幾頁,再用其餘的頁面驗證一下,確實是這樣的,那麼第一頁爲何不是http://blog.csdn.net/sunhuaqiang1/article/list/1呢,那麼咱們在瀏覽器中輸http://blog.csdn.net/sunhuaqiang1/article/list/1試試,哎,果真是第一頁啊,第一頁原來是被重定向了,http://blog.csdn.net/sunhuaqiang1被重定向到http://blog.csdn.net/sunhuaqiang1/article/list/1,因此兩個網址都能訪問第一頁,那麼如今規律就很是明顯了: http://blog.csdn.net/sunhuaqiang1/article/list/ + 頁號
二.獲取標題
右鍵查看網頁的源代碼,咱們看到能夠找到這樣一段代碼:
咱們能夠看到標題都是在標籤
中的。因此咱們能夠使用下面的正則表達式來匹配標題:
三.獲取訪問量
拿到了標題以後,就要得到對應的訪問量了,通過對源碼的分析,我看到訪問量的結構都是這樣的:
括號中的數字即爲訪問量,咱們能夠用下面的正則表達式來匹配:
其中,’.?’的含義是啓用正則懶惰模式。必須跟在或者+後邊用。
如:「< img src=」test.jpg」 width=」60px」 height=」80px」/>」
若是用正則匹配src中內容非懶惰模式匹配
匹配結果是:src=」test.jpg」 width=」60px」 height=」80px」
意思是從=」日後匹配,直到最後一個」匹配結束
懶惰模式正則:
結果:src=」test.jpg」
由於匹配到第一個」就結束了一次匹配。不會繼續向後匹配。由於他懶惰嘛。
- .表示除\n以外的任意字符
- *表示匹配0-無窮
- +表示匹配1-無窮
四.尾頁判斷
接下來咱們要判斷當前頁是否爲最後一頁,不然咱們就不能判斷何時結束了,我找到了源碼中‘尾頁’的標籤,發現是下面的結構:
因此咱們能夠用下面的正則表達式來匹配,若是匹配成功就說明當前頁不是最後一頁,不然當前頁就是最後一頁。
五.編程實現
下面是摘自的Python2版完整的代碼實現:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
因爲本身如今的IDE爲Python3,且本身在學習Python3。故在此基礎上實現Python2項目的升級改造,並在改造過程當中發現版本之間的差別性。如下爲Python3版本下的爬蟲代碼。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
下面是部分結果:
瑕疵:經過爬蟲結果能夠發現,在CSDN中,對於設置爲指定的文章,爬取結果存在必定的問題,還包含部分css代碼。
改善:經過更改獲取博文標題的正則表達式,便可解決此問題。
」
想法是好的,可是直接利用正則實現標題獲取時遇到了困難,暫時並未實現理想結果。
遂改變思路,將利用正則獲取後的字符串再進行二次正則,即替換操做,語句以下:
更改後的結果以下。並同時爲每篇博文進行了編號。
同時,本身還但願獲取到的信息包括:訪問總量、積分、等級、排名、粉絲、原創、轉載、譯文、評論等數據信息。
以上信息在網頁源碼中以下所示。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
則獲取訪問信息的正則表達式爲:
根據網頁源碼,可得出其正則表達式爲
通過以上操做,獲得的用戶Blog信息以下圖所示:
最終遇到的問題是:有關粉絲數的爬取遇到了問題,由於前面數據信息的獲取不須要用戶登陸,而用戶粉絲數是在用戶已登陸情景下獲取的,故須要將用戶登陸信息添加進去。犯愁~
PS:論文盲審送回來了,本身這段時間要用來修改論文了,後面的博客後面再說吧~
注意事項
- urllib2在3.5中爲urllib.request;
- raw_input()在3.5中爲input();
- python3中urllib.read()返回的是bytes對象,不是string,得把它轉換成string對象,用bytes.decode()方法;
- re.S意在使.匹配包括換行在內的全部字符;
- python3對urllib和urllib2進行了重構,拆分紅了urllib.request, urllib.response,urllib.parse,urllib.error等幾個子模塊,這樣的架構從邏輯和結構上說更加合理。urljoin如今對應的函數是urllib.parse.urljoin
注:Python2部分的爬蟲代碼爲網絡獲取,在此向匿名人士表示感謝。
Python進階(十九)-Python3安裝第三方爬蟲庫BeautifulSoup4
在作Python3爬蟲練習時,從網上找到了一段代碼以下:
本身實踐後,發現出現了錯誤,以下所示:
以上錯誤提示是說沒有發現名爲「bs4」的模塊。即「bs4」模塊未安裝。
進入Python安裝目錄,以做者IDE爲例,
控制檯提示第三方庫BeautifulSoup4安裝成功!回到以前的程序中,會發現IntelJ已經檢測到第三方庫BS4的安裝,已自更新項目,此時項目恢復正常,無錯誤提示。
常見問題
在作BS4爬蟲練習時,新建的文件名爲bs4.py,結果出現以下錯誤提示:
即ImportError: cannot import name BeautifulSoup通常有一下幾種狀況:
1. 在python2.x下安裝的BeautifulSoup在python3.x下運行會報這種錯,可用pip3 install Beautifulsoup4 .
2. 導入時指定bs4 像這樣: from bs4 import BeautifulSoup.
3. 太巧合,若是你測試的文件名正好命名爲bs4.py,那怎麼整都會報這個錯,把名字改爲其餘的吧。
附
BS4官方文檔
Python進階(二十)-Python爬蟲實例講解
本篇博文主要講解Python爬蟲實例,重點包括爬蟲技術架構,組成爬蟲的關鍵模塊:URL管理器、HTML下載器和HTML解析器。
爬蟲簡單架構
程序入口函數(爬蟲調度段)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
URL管理器
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
網頁下載器
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
網頁解析器
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
網頁輸出器
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
運行結果
附
完整代碼
Python進階(二十二)-Python3使用PyMysql鏈接mysql數據庫
python語言的3.x徹底不向前兼容,致使咱們在python2.x中能夠正常使用的庫,到了python3就用不了.好比說mysqldb。
目前MySQLdb並不支持python3.x,Python3.x鏈接MySQL的方案有:oursql, PyMySQL, myconnpy 等
下面來講下python3如何安裝和使用pymysql,另外兩個方案我會在之後再講。
1.pymysql安裝
pymysql就是做爲python3環境下mysqldb的替代物,進入命令行,使用pip安裝pymysql。
2.pymysql使用
若是想使用mysqldb的方式,那麼直接在py文件的開頭加入以下兩行代碼便可。
3.安裝測試示例
會看到控制檯輸出如下信息:
說明pymysql安裝成功,可正常使用。
4.pymysql操做示例
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
5.pymysql操做示例-銀行轉賬
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
數據庫插入操做
如下實例使用執行 SQL INSERT 語句向表 EMPLOYEE 插入記錄:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
connect參數
connect方法
cursor方法
fetch*方法介紹
DQL
DML
事務特性
Python進階(二十三)-Django使用pymysql鏈接MySQL數據庫作增刪改查
IDE說明
Python:3.5
Django:1.10
Pymysql:0.7.10
Mysql:5.5
注:Django1.10默認使用的是mysqlDB模塊來操做數據庫,而該模塊已不支持Python3,因此須要其餘的方式鏈接數據庫。
本文選擇使用pymysql鏈接組件。
前言
在學習完Python基礎以後,繼續學習Python Web開發方面的知識。首先決定學習Django Web開發框架。在鏈接數據庫一塊,視頻教學中使用的是django內置的sqlite數據庫,以前本身使用的是mysql數據庫,遂決定繼續使用mysql數據庫。
mysql鏈接配置
查看了使用mysql的settings.py項目配置文件信息,以下:
具體含義就再也不解釋了,一看就懂。配置好以後,在命令行項目目錄下輸入服務端運行命令:
卻出現了錯誤提示,信息以下:
Django.core.exceptions. ImproperlyConfigured:Error loading MySqldb module:no module named ‘MySQLdb’.
看來,Django1.10默認使用的是mysqldb鏈接組件。可是,在python3.x中已經不支持那個組件了,取而代之的則是pymysql鏈接組件。遂決定使用pymysql鏈接組件。
採用上述配置方式的話默認會調用mysqlDB模塊,因爲Python3已經不支持該模塊,因此須要修改該配置文件所在目錄下的init.py文件
再次執行方式一的數據庫同步命令便可。可是卻出現了以下錯誤提示:
ImportError:cannot import name 「Thing2Literal」
之因此出現以上錯誤,是由於MySQLdb裏面有一個Thing2Literal方法,在pymysql裏沒有,因此致使報錯。還有可能就是因爲pymysql的版本低,存在這個問題,建議下載最新版本的pymysql,因而我從新下載pymysql,版本是最新的0.7.10(pip install pymysql),而後進行以下操做:
1.將settings裏面的DATABASES改爲MySQL相關
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
2.在settings的上一級目錄中添加my.cnf 文件,內容以下:
在項目manage.py同級目錄下輸入命令
至此,數據表關聯成功,後面進行校驗操做。
設想:Django是否能夠讀取已存在的數據庫信息?必須得首先經過Django創建數據表嗎?答案是NO,不過能夠採用將Django生成的數據表保存於已存在數據庫中,而後將原來的數據代表更改成「項目名稱_數據表名」的形式,從而使用原有的數據表信息。
更新後的數據表信息以下:
建立超級管理員
業務邏輯層設計
接下來實現前端顯示數據表信息。
業務邏輯層信息以下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
前端顯示
客戶端前端顯示頁面信息以下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
顯示效果以下所示(有點醜):
管理端設計
Django另一個神奇的功能就是自帶Admin管理端。並且作的還挺精緻。登陸Django管理界面以前,須要首先建立超管員,在DOS窗口輸入命令
而後就是設置密碼、郵箱等註冊信息。建立好超管員身份以後,可在相應的auth_user數據表中查看信息。
其默認使用的英文,若更改成中文,只需修改settings.py在的語言設置,以下:
若要在管理端實現數據表信息的管理,只須要在admin.py中添加以下代碼便可實現。真可謂言簡意賅啊。
登陸管理端以後便可看到數據表中的信息。
列表項設置
其中,Blogs與Users分別對應數據庫中的blog_blog與blog_user數據表。點擊其中一個項目,例如點擊Blogs,顯示以下頁面:
這就有問題了,能夠看到在管理段博客列表中顯示的博客列表名稱均爲「Blog Object」即所獲取到的Blog對象。能否實現博客名稱顯示呢?答案是確定的。修改一下blog中的models.py。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
添加的重點就是在定義每個類時同時定義一個python內置的序列化函數str,這樣就能夠實現列表項目的顯示定製功能了。
點擊每個列表項可進入博文編輯頁面。
單頁顯示條數設置
在博客列表中,發現單頁顯示條目爲100,未免有點多,能否實現單頁顯示條數定製化操做呢。在admin.py中輸入如下代碼便可。
另外,可實如今列表顯示與字段相關的其它內容。例如在博客列表中,可附加顯示每篇博文的訪問量等信息。
具體的操做方法是在admin.py中修改代碼以下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
其中,list_display 就是來配置要顯示的字段的,固然也能夠顯示非字段內容,或者字段相關的內容,list_display中的參數就是待顯示的數據屬性。
搜索功能
在博客列表頁面須要實現搜索功能,一樣須要修改admin.py文件。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
實現效果以下:
數據屬性名稱設置
在查看博主信息時,看到博主屬性名稱均爲英文,能否實現別名替換?
原來在創建數據類時經過verbose_name屬性便可設置別名,models.py中代碼以下:
替換後的博主信息頁面以下:
數據類別名設置
同時,可取數據類的別名。例如,將「User」取別名爲「博主」。一樣須要在models.py中相應的數據類中添加以下代碼:
注:凡是涉及到管理端操做的功能均需在admin.py文件中添加便可。
在學習過程當中,發覺Django的後臺功能實在是太強大了,因爲models模塊實現了ORM框架。通過一系列操做,能夠發現管理端的數據CRUD操做已經徹底實現,無需用戶書寫任何數據庫操做代碼。省心省力啊!
附 Django學習資料
pymysql版本查看命令(請告知我,謝謝~)
Python進階(二十四)-Python中函數的參數定義和可變參數
剛學用Python的時候,特別是看一些庫的源碼時,常常會看到這樣的函數定義,這個和*讓人有點費解。其實只要把函數參數定義搞清楚了,就不難理解了。
先說說函數定義,咱們都知道,下面的代碼定義了一個函數funcA
顯然,函數funcA沒有參數。
下面這個函數funcB就有兩個參數了,
調用的時候,咱們須要使用函數名,加上圓括號擴起來的參數列表,好比 funcB(100, 99),執行結果是:
100
99
很明顯,參數的順序和個數要和函數定義中一致,若是執行funcB(100),Python會報錯的:
TypeError: funcB() takes exactly 2 arguments (1 given)
咱們能夠在函數定義中使用參數默認值,好比
在函數funcC的定義中,參數b有默認值,是一個可選參數,若是咱們調用funcC(100),b會自動賦值爲0。
OK,目前爲止,咱們要定義一個函數的時候,必需要預先定義這個函數須要多少個參數(或者說能夠接受多少個參數)。通常狀況下這是沒問題的,可是也有在定義函數的時候,不能知道參數個數的狀況(想想C語言裏的printf函數),在Python裏,帶*的參數就是用來接受可變數量參數的。看一個例子
調用funcD(1, 2, 3, 4, 5, 6)結果是
1
2
length of c is: 4
(3, 4, 5, 6)
咱們看到,前面兩個參數被a、b接受了,剩下的4個參數,所有被c接受了,c在這裏是一個tuple。咱們在調用funcD的時候,至少要傳遞2個參數,2個以上的參數,都放到c裏了,若是隻有兩個參數,那麼c就是一個empty tuple。
好了,一顆星咱們弄清楚了,下面輪到兩顆星。
上面的例子裏,調用函數的時候,傳遞的參數都是根據位置來跟函數定義裏的參數表匹配的,好比funcB(100, 99)和funcB(99, 100)的執行結果是不同的。在Python裏,還支持一種用關鍵字參數(keyword argument)調用函數的辦法,也就是在調用函數的時候,明確指定參數值賦值給哪一個形參。好比仍是上面的funcB(a, b),咱們經過這兩種方式調用
和
結果跟funcB(100, 99)都是同樣的,由於咱們在使用關鍵字參數調用的時候,指定了把100賦值給a,99賦值給b。也就是說,關鍵字參數可讓咱們在調用函數的時候打亂參數傳遞的順序!
另外,在函數調用中,能夠混合使用基於位置匹配的參數和關鍵字參數,前題是先給出固定位置的參數,好比
def funcE(a, b, c):
print a
print b
print c
調用funcE(100, 99, 98)和調用funcE(100, c=98, b=99)的結果是同樣的。
好了,通過以上鋪墊,兩顆星總算能夠出場了:
若是一個函數定義中的最後一個形參有 ** (雙星號)前綴,全部正常形參以外的其餘的關鍵字參數都將被放置在一個字典中傳遞給函數,好比:
調用funcF(100, c=’你好’, b=200),執行結果
100
c: 你好
b: 200
你們能夠看到,b是一個dict對象實例,它接受了關鍵字參數b和c。
Python進階(二十五)-Python讀寫文件
打開文件
使用open打開文件後必定要記得調用文件對象的close()方法。好比能夠用try/finally語句來確保最後能關閉文件。
注:不能把open語句放在try塊裏,由於當打開文件出現異常時,文件對象file_object沒法執行close()方法。
讀文件
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
寫文件
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
注意,調用writelines寫入多行在性能上會比使用write一次性寫入要高。
在處理日誌文件的時候,經常會遇到這樣的狀況:日誌文件巨大,不可能一次性把整個文件讀入到內存中進行處理,例如須要在一臺物理內存爲 2GB 的機器上處理一個 2GB 的日誌文件,咱們可能但願每次只處理其中200MB的內容。
在Python中,內置的File對象直接提供了一個readlines(sizehint) 函數來完成這樣的事情。如下面的代碼爲例:
每次調用 readlines(sizehint) 函數,會返回大約200MB的數據,並且所返回的必然都是完整的行數據,大多數狀況下,返回的數據的字節數會稍微比 sizehint 指定的值大一點(除最後一次調用 readlines(sizehint) 函數的時候)。一般狀況下,Python 會自動將用戶指定的 sizehint 的值調整成內部緩存大小的整數倍。
file在python是一個特殊的類型,它用於在python程序中對外部的文件進行操做。在python中一切都是對象,file也不例外,file有file的方法和屬性。下面先來看如何建立一個file對象:
file()函數用於建立一個file對象,它有一個別名叫open(),可能更形象一些,它們是內置函數。來看看它的參數。它參數都是以字符串的形式傳遞的。
name是文件的名字。
mode是打開的模式,可選的值爲rwaU,分別表明讀(默認)寫添加支持各類換行符的模式。用w或a模式打開文件的話,若是文件不存在,那麼就自動建立。此外,用w模式打開一個已經存在的文件時,原有文件的內容會被清空,由於一開始文件的操做的標記是在文件的開頭的,這時候進行寫操做,無疑會把原有的內容給抹掉。因爲歷史的緣由,換行符在不一樣的系統中有不一樣模式,好比在unix中是一個\n,而在windows中是‘\r\n’,用U模式打開文件,就是支持全部的換行模式,也就說‘\r’ ‘\n’ ‘\r\n’均可表示換行,會有一個tuple用來存貯這個文件中用到過的換行符。不過,雖然說換行有多種模式,讀到python中統一用\n代替。在模式字符的後面,還能夠加上+ b t這兩種標識,分別表示能夠對文件同時進行讀寫操做和用二進制模式、文本模式(默認)打開文件。
buffering若是爲0表示不進行緩衝;若是爲1表示進行「行緩衝「;若是是一個大於1的數表示緩衝區的大小,應該是以字節爲單位的。
file對象有本身的屬性和方法。先來看看file的屬性。
- closed #標記文件是否已經關閉,由close()改寫
- encoding #文件編碼
- mode #打開模式
- name #文件名
- newlines #文件中用到的換行模式,是一個tuple
- softspace #boolean型,通常爲0,聽說用於print
file的讀寫方法:
cmp(tuple1, tuple2) 比較兩個元組元素。 len(tuple) 計算元組元素個數。 max(tuple) 返回元組中元素最大值。 min(tuple) 返回元組中元素最小值。 tuple(seq) 將列表轉換爲元組。 dict = {'Alice': '2341', 'Beth': '9102', 'Cecil': '3258'};dict1 = { 'abc': 456 }; dict2 = { 'abc': 123, 98.6: 37 };dict = {'name': 'Zara', 'age': 7, 'class': 'First'}; print "dict['name']: ", dict['name']; print "dict['age']: ", dict['age'];dict = {'name': 'Zara', 'age': 7, 'class': 'First'}; dict["age"]=27; dict["school"]="wutong"; print "dict['age']: ", dict['age']; print "dict['school']: ", dict['school'];del dict['name']; dict.clear(); del dict ; cmp(dict1, dict2) len(dict) str(dict) type(variable) clear() copy() fromkeys() get(key, default=None) has_key(key) items() keys() setdefault(key, default=None) update(dict2) values() import time, datetime; localtime = time.localtime(time.time()) print "Local current time :", localtimeexpire_time = "2013-05-21 09:50:35" d = datetime.datetime.strptime(expire_time,"%Y-%m-%d %H:%M:%S") print d;oneday = datetime.timedelta(days=1) today = datetime.date.today() yesterday = datetime.date.today() - oneday tomorrow = datetime.date.today() + oneday today_zero_time=datetime.datetime.strftime(today, '%Y-%m-%d %H:%M:%S') print datetime.timedelta(milliseconds=1), print datetime.timedelta(seconds=1), print datetime.timedelta(minutes=1), print datetime.timedelta(hours=1), print datetime.timedelta(days=1), print datetime.timedelta(weeks=1)#1 day, 0:00:00 oneday = datetime.timedelta(days=1) #今天,2014-03-21 16:07:23.943000 today_time = datetime.datetime.now() #昨天,2014-03-20 16:07:23.943000 yesterday_time = datetime.datetime.now() - oneday #明天,2014-03-22 16:07:23.943000 tomorrow_time = datetime.datetime.now() + onedayprint datetime.datetime.strftime(today_time, '%Y-%m-%d %H:%M:%S') print datetime.datetime.strftime(yesterday_time, '%Y-%m-%d %H:%M:%S') print datetime.datetime.strftime(tomorrow_time, '%Y-%m-%d %H:%M:%S')last_month_last_day = datetime.date(datetime.date.today().year,datetime.date.today().month,1)-datetime.timedelta(1)expire_time = "2013-05-21 09:50:35" d = datetime.datetime.strptime(expire_time,"%Y-%m-%d %H:%M:%S") time_sec_float = time.mktime(d.timetuple()) print time_sec_floatd = datetime.date.today() time_sec_float = time.mktime(d.timetuple()) print time_sec_floattime_sec = time.time() print time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time_sec))
def statistics(lst): dic = {} for k in lst: if not k in dic: dic[k] = 1 else: dic[k] +=1 return dic lst = [1,1,2,3,2,3,3,5,6,7,7,6,5,5,5] print(statistics(lst)) def statistics2(lst): m = set(lst) dic = {} for x in m: dic[x] = lst.count(x) return dic lst = [1,1,2,3,2,3,3,5,6,7,7,6,5,5,5] print statistics2(lst) def statistics(dic,k): if not k in dic: dic[k] = 1 else: dic[k] +=1 return dic lst = [1,1,2,3,2,3,3,5,6,7,7,6,5,5,5] print reduce(statistics,lst,{}) 或者 d = {} d.extend(lst) print reduce(statistics,d) def g(): print 'g()...' def f(): print 'f()...' return gdef f(): print 'f()...' def g(): print 'g()...' return gdef calc_sum(lst): def lazy_sum(): return sum(lst) return lazy_sum def count(): fs = [ ] for i in range(1, 4): def f(): return i*i fs.append(f) return fs f1, f2, f3 = count()>>> f1() 9 def f(j): def g(): return j*j return gdef count(): fs = [] for i in range(1, 4): def f(j): def g(): return j*j return g r = f(i) fs.append(r) return fs f1, f2, f3 = count() print f1(), f2(), f3()
>>> map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]) [1, 4, 9, 16, 25, 36, 49, 64, 81]def f(x): return x * x>>> sorted([1, 3, 9, 5, 0], lambda x,y: -cmp(x,y)) [9, 5, 3, 1, 0]>>> myabs = lambda x: -x if x < 0 else x >>> myabs(-1) 1 >>> myabs(1) 1def is_not_empty(s): return s and len(s.strip()) > 0 filter(is_not_empty, ['test', None, '', 'str', ' ', 'END'])print filter(lambda s: s and len(s.strip())>0, ['test', None, '', 'str', ' ', 'END'])def log(f): def fn(x): print 'call ' + f.__name__ + '()...' return f(x) return fn@log def factorial(n): return reduce(lambda x,y: x*y, range(1, n+1)) print factorial(10)@log def add(x, y): return x + y print add(1, 2)def log(f): def fn(*args, **kw): print 'call ' + f.__name__ + '()...' return f(*args, **kw) return fnimport time def performance(f): def fn(*args, **kw): t1 = time.time() r = f(*args, **kw) t2 = time.time() print 'call %s() in %fs' % (f.__name__, (t2 - t1)) return r return fn @performance def factorial(n): return reduce(lambda x,y: x*y, range(1, n+1)) print factorial(10)print 'Hello, World!'print( 'Hello, World!') try: except Exception as e : >>> 中國 = 'china' >>>print(中國) china operator.lt(a, b) #至關於 a<b 從第一個數字或字母(ASCII)比大小 operator.le(a, b) #至關於a<=b operator.eq(a, b) #至關於a==b 字母徹底同樣,返回True operator.ne(a, b) #至關於a!=b operator.ge(a, b) #至關於 a>=b operator.gt(a, b) #至關於a>b operator.__lt__(a, b) operator.__le__(a, b) operator.__eq__(a, b) operator.__ne__(a, b) operator.__ge__(a, b) operator.__gt__(a, b)def log(f): def fn(x): print 'call ' + f.__name__ + '()...' return f(x) return fn@log('DEBUG') def my_func(): passmy_func = log('DEBUG')(my_func)log_decorator = log('DEBUG') my_func = log_decorator(my_func)log_decorator = log('DEBUG') @log_decorator def my_func(): passdef log(prefix): def log_decorator(f): def wrapper(*args, **kw): print '[%s] %s()...' % (prefix, f.__name__) return f(*args, **kw) return wrapper return log_decorator @log('DEBUG') def test(): pass print test() def log_decorator(f): def wrapper(*args, **kw): print '[%s] %s()...' % (prefix, f.__name__) return f(*args, **kw) return wrapper return log_decorator def log(prefix): return log_decorator(f)@performance('ms') def factorial(n): return reduce(lambda x,y: x*y, range(1, n+1))my_func = performance('ms')(my_func)import time def performance(unit): def perf_decorator(f): def wrapper(*args, **kw): t1 = time.time() r = f(*args, **kw) t2 = time.time() t = (t2 - t1) * 1000 if unit=='ms' else (t2 - t1) print 'call %s() in %f %s' % (f.__name__, t, unit) return r return wrapper return perf_decorator @performance('ms') def factorial(n): return reduce(lambda x,y: x*y, range(1, n+1)) print factorial(10)def calc_prod(lst): def ff(): print map(lambda x:x*x,lst) return ff f = calc_prod([1, 2, 3, 4]) print f()b = print(5) print(b)def calc_prod(lst): def ff(): return map(lambda x:x*x,lst) return ff f = calc_prod([1, 2, 3, 4]) print(f())foo_bar(self, width, height, color='black', design=None, x='foo',emphasis=None, highlight=0) if (width == 0 and height == 0 and color == 'red' and emphasis == 'strong'):x = ('This will build a very long long ' 'long long long long long long string')# See details at # http://www.example.com/us/developer/documentation/api/content/v2.0/csv_file_name_extension_full_specification.html# See details at # http://www.example.com/us/developer/documentation/api/content/\ # v2.0/csv_file_name_extension_full_specification.html if foo: bar() while x: x = bar() if x and y: bar() if not x: bar() return foo for (x, y) in dict.items(): ... if (x): bar() if not(x): bar() return (foo) foo = long_function_name(var_one, var_two, var_three, var_four) foo = { long_dictionary_key: value1 + value2, ... } foo = long_function_name( var_one, var_two, var_three, var_four) foo = { long_dictionary_key: long_dictionary_value, ... } foo = long_function_name(var_one, var_two, var_three, var_four) foo = long_function_name( var_one, var_two, var_three, var_four) foo = { long_dictionary_key: long_dictionary_value, ... }spam(ham[1], {eggs: 2}, [])spam( ham[ 1 ], { eggs: 2 }, [ ] )if x == 4: print x, y x, y = y, x ``` No: 參數列表, 索引或切片的左括號前不該加空格. Yes: spam(1) no: spam (1) Yes: dict['key'] = list[index] No: dict ['key'] = list [index] 在二元操做符兩邊都加上一個空格, 好比賦值(=), 比較(==, <, >, !=, <>, <=, >=, in, not in, is, is not), 布爾(and, or, not). 至於算術操做符兩邊的空格該如何使用, 須要你本身好好判斷. 不過兩側務必要保持一致. Yes: x == 1 No: x<1 當’=’用於指示關鍵字參數或默認參數值時, 不要在其兩側使用空格. Yes: def complex(real, imag=0.0): return magic(r=real, i=imag) No: def complex(real, imag = 0.0): return magic(r = real, i = imag) 不要用空格來垂直對齊多行間的標記, 由於這會成爲維護的負擔(適用於:, Yes: foo = 1000 # comment long_name = 2 # comment that should not be aligned dictionary = { "foo": 1, "long_name": 2, } No: foo = 1000 # comment long_name = 2 # comment that should not be aligned dictionary = { "foo" : 1, "long_name": 2, } def fetch_bigtable_rows(big_table, keys, other_silly_variable=None): """Fetches rows from a Bigtable. Retrieves rows pertaining to the given keys from the Table instance represented by big_table. Silly things may happen if other_silly_variable is not None. Args: big_table: An open Bigtable Table instance. keys: A sequence of strings representing the key of each table row to fetch. other_silly_variable: Another optional variable, that has a much longer name than the other args, and which does nothing. Returns: A dict mapping keys to the corresponding table row data fetched. Each row is represented as a tuple of strings. For example: {'Serak': ('Rigel VII', 'Preparer'), 'Zim': ('Irk', 'Invader'), 'Lrrr': ('Omicron Persei 8', 'Emperor')} If a key from the keys argument is missing from the dictionary, then that row was not found in the table. Raises: IOError: An error occurred accessing the bigtable.Table object. """ passclass SampleClass(object): """Summary of class here. Longer class information.... Longer class information.... Attributes: likes_spam: A boolean indicating if we like SPAM or not. eggs: An integer count of the eggs we have laid. """ def __init__(self, likes_spam=False): """Inits SampleClass with blah.""" self.likes_spam = likes_spam self.eggs = 0 def public_method(self): """Performs operation blah."""3.僅僅是從邏輯上關閉文件和sockets, 那麼它們仍然可能會被其共享的程序在無心中進行讀或者寫操做. 只有當它們真正被關閉後, 對於它們嘗試進行讀或者寫操做將會拋出異常, 並使得問題快速顯現出來.with open("hello.txt") as hello_file: for line in hello_file: print linecontextlib.closing(): import contextlib with contextlib.closing(urllib.urlopen("http://www.python.org/")) as front_page: for line in front_page: print line Legacy AppEngine 中Python 2.5的代碼如使用」with」語句, 須要添加 「from __future__ import with_statement」.
class Person(object): def __init__(self, name): self.__name = name def get_name(self): return self.__namep1 = Person('Bob') print p1.get_name() class Person(object): def __init__(self, name, score): self.__name = name self.__score = score def get_grade(self): if self.__score >= 80: return 'A' if self.__score >= 60: return 'B' return 'C' p1 = Person('Bob', 90) p2 = Person('Alice', 65) p3 = Person('Tim', 48) print p1.get_grade() print p2.get_grade() print p3.get_grade()
class Person(object): def __init__(self, name, score): self.name = name self.score = score def get_grade(self): return 'A' p1 = Person('Bob', 90) print p1.get_grade print p1.get_grade() import types def fn_get_grade(self): if self.score >= 80: return 'A' if self.score >= 60: return 'B' return 'C' class Person(object): def __init__(self, name, score): self.name = name self.score = score p1 = Person('Bob', 90) p1.get_grade = types.MethodType(fn_get_grade, p1, Person) print p1.get_grade() p2 = Person('Alice', 65) print p2.get_grade() class Person(object): def __init__(self, name, score): self.name = name self.score = score self.get_grade = lambda: 'A' p1 = Person('Bob', 90) print p1.get_grade print p1.get_grade()sorted(iterable,key=None,reverse=False)students = [('john', 'A', 15), ('jane', 'B', 12), ('dave','B', 10)] sorted(students,key=lambda s: x[2]) print("".join(sorted(s, key=lambda x: (x.isdigit(),x.isdigit() and int(x) % 2 == 0,x.isupper(),x))))list1=[7, -8, 5, 4, 0, -2, -5] #要求1.正數在前負數在後 2.正數從小到大 3.負數從大到小 sorted(list1,key=lambda x:(x<0,abs(x)))def add(x,y,f): return f(x)+f(y) add(-5,9,abs) def format_name(s): return s.title() print map(format_name, ['adam', 'LISA', 'barT']) def prod(x, y): return x*y; print reduce(prod, [2, 4, 5, 7, 12]) import math def is_sqr(x): return int(math.sqrt(x))*int(math.sqrt(x))==x print filter(is_sqr, range(1, 101)) def cmp_ignore_case(s1, s2): return cmp(s1.lower(),s2.lower()) print sorted(['bob', 'about', 'Zoo', 'Credit'], cmp_ignore_case)def calc_prod(lst): def prod(x,y): return x*y; def g(): return reduce(prod,lst) return g; f = calc_prod([1, 2, 3, 4]) print f() def count(): fs = [] for i in range(1, 4): def f(j): def g(): return j*j; return g fs.append(f(i)) return fs f1, f2, f3 = count() print f1(), f2(), f3() def is_not_empty(s): return s and len(s.strip()) > 0 print filter(lambda s:s and len(s.strip())>0, ['test', None, '', 'str', ' ', 'END']) def log(f): def fn(*args, **kw): print 'call ' + f.__name__ + '()...' return f(*args, **kw) return fn @log #調用日誌裝飾器 def factorial(n): return reduce(lambda x,y: x*y, range(1, n+1)) print factorial(10) def log(prefix): def log_decorator(f): def wrapper(*args, **kw): print '[%s] %s()...' % (prefix, f.__name__) return f(*args, **kw) return wrapper return log_decorator @log('DEBUG') #DEBUG爲給裝飾器傳入的參數 def test(): pass print test() import time, functools def performance(unit): def perf_decorator(f): @functools.wraps(f) def wrapper(*args, **kw): t1 = time.time() r = f(*args, **kw) t2 = time.time() t = (t2 - t1) * 1000 if unit=='ms' else (t2 - t1) print 'call %s() in %f %s' % (f.__name__, t, unit) return r return wrapper return perf_decorator @performance('ms') def factorial(n): return reduce(lambda x,y: x*y, range(1, n+1)) print factorial.__name__ import functools int2 = functools.partial(int, base=2) int2('1000000') #64
f = open('yesterday',encoding='utf-8') data = f.read() f.close() print(data) f = open('yesterday','r',encoding='utf-8') for i in range(5): print(f.readline()) f = open('yesterday','r',encoding='utf-8') for line in f.readlines(): print(line) f = open('yesterday','r',encoding='utf-8') for index,line in enumerate(f.readlines()): if index == 2: print('-----測試線----',line) continue print(line) f = open('yesterday','r',encoding='utf-8') for line in f: print(line) f = open('yesterday','r',encoding='utf-8') count = 0 for line in f: if count == 2: print('------測試線----:',line) count += 1 print(line) f = open('yesterday','w',encoding='utf-8') f.write("這就是一行測試\n") f.write("測試2\n") f.write("測試3") f = open('yesterday','a',encoding='utf-8') f.write("test1\n") f = open('yesterday','r',encoding='utf-8') print(f.tell()) print(f.readline()) print(f.tell()) f.seek(0) print(f.encoding) print(f.fileno()) print(f.isatty()) f.flush() f = open('yesterday','r+',encoding='utf-8') data = f.read() print(data) f.write("test...\n") ''' ''' with open('log','r') as f: ... with open('log1') as obj1, open('log2') as obj2: passimport re pattern = re.compile(r'rlovep') m = pattern.match('rlovep.com') if m: print(m.group()) import re print(re.match('www', 'www.runoob.com').span()) print(re.match('com', 'www.runoob.com')) import re line = "Cats are smarter than dogs" matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I) if matchObj: print ("matchObj.group() : ", matchObj.group()) print ("matchObj.group(1) : ", matchObj.group(1)) print ("matchObj.group(2) : ", matchObj.group(2)) else: print ("No match!!")import re print(re.search("rlovep","rlovep.com").span()) print(re.search("com","http://rlovep.com").span())import re line = "This is my blog" matchObj = re.search( r'(.*) is (.*?) .*', line, re.M|re.I) if matchObj: print ("matchObj.group() : ", matchObj.group()) print ("matchObj.group(1) : ", matchObj.group(1)) print ("matchObj.group(2) : ", matchObj.group(2)) else: print ("No match!!") import re line = "Cats are smarter than dogs"; matchObj = re.match( r'dogs', line, re.M|re.I) if matchObj: print ("match --> matchObj.group() : ", matchObj.group()) else: print ("No match!!") matchObj = re.search( r'dogs', line, re.M|re.I) if matchObj: print ("search --> matchObj.group() : ", matchObj.group()) else: print ("No match!!") import re phone = "2004-959-559 # 這是一個電話號碼" num = re.sub(r'#.*$', "", phone) print ("電話號碼 : ", num) num = re.sub(r'\D', "", phone) print ("電話號碼 : ", num) import re def double(matched): value = int(matched.group('value')) return str(value * 2) s = 'A23G4HFD567' print(re.sub('(?P<value>\d+)', double, s))s.strip().lstrip().rstrip(',') sStr1 = 'strcpy' sStr2 = sStr1 sStr1 = 'strcpy2' print sStr2 sStr1 = 'strcat' sStr2 = 'append' sStr1 += sStr2 print sStr1#strchr(sStr1,sStr2) # < 0 爲未找到 sStr1 = 'strchr' sStr2 = 's' nPos = sStr1.index(sStr2) print nPos sStr1 = 'strchr' sStr2 = 'strch' print cmp(sStr1,sStr2)#strspn(sStr1,sStr2) sStr1 = '12345678' sStr2 = '456' #sStr1 and chars both in sStr1 and sStr2 print len(sStr1 and sStr2) sStr1 = 'strlen' print len(sStr1)#strlwr(sStr1) sStr1 = 'JCstrlwr' sStr1 = sStr1.upper() #sStr1 = sStr1.lower() print sStr1 sStr1 = '12345' sStr2 = 'abcdef' n = 3 sStr1 += sStr2[0:n] print sStr1 sStr1 = '12345' sStr2 = '123bc' n = 3 print cmp(sStr1[0:n],sStr2[0:n]) sStr1 = '' sStr2 = '12345' n = 3 sStr1 = sStr2[0:n] print sStr1 sStr1 = '12345' ch = 'r' n = 3 sStr1 = n * ch + sStr1[3:] print sStr1 sStr1 = 'cekjgdklab' sStr2 = 'gka' nPos = -1 for c in sStr1: if c in sStr2: nPos = sStr1.index(c) break print nPos sStr1 = 'abcdefg' sStr1 = sStr1[::-1] print sStr1 sStr1 = 'abcdefg' sStr2 = 'cde' print sStr1.find(sStr2) sStr1 = 'ab,cde,fgh,ijk' sStr2 = ',' sStr1 = sStr1[sStr1.find(sStr2) + 1:] print sStr1 s = 'ab,cde,fgh,ijk' print(s.split(','))delimiter = ',' mylist = ['Brazil', 'Russia', 'India', 'China'] print delimiter.join(mylist)str = ’0123456789′ print str[0:3] #截取第一位到第三位的字符 print str[:] #截取字符串的所有字符 print str[6:] #截取第七個字符到結尾 print str[:-3] #截取從頭開始到倒數第三個字符以前 print str[2] #截取第三個字符 print str[-1] #截取倒數第一個字符 print str[::-1] #創造一個與原字符串順序相反的字符串 print str[-3:-1] #截取倒數第三位與倒數第一位以前的字符 print str[-3:] #截取倒數第三位到結尾 print str[:-5:-3] #逆序截取,具體啥意思沒搞明白?print ("整型:",int(50)) a=int(50) print("整型:",type(a)) numStr = "50"; print ("字符串:",type(numStr)) convertedInt = int(numStr); print("字符串轉換爲整型:",convertedInt) convertedstr=str(a) print("整型轉換爲字符串:",convertedInt)<span class="link_title"> <a href="/sunhuaqiang1/article/details/50651235"> ... </a> </span><span class="link_title"><a href=".*?">(.*?)</a></span><span class="link_view" title="閱讀次數"><a href="/sunhuaqiang1/article/details/51289580" title="閱讀次數">閱讀</a>(12718)</span><span class="link_view".*?><a href=".*?" title="閱讀次數">閱讀</a>\((.*?)\)</span>src=".*"src=".*?"<a href="/sunhuaqiang1/article/list/2">下一頁</a> <a href="/sunhuaqiang1/article/list/7">尾頁</a><a href=".*?">尾頁</a> ''' Created on 2016年2月13日 @author: *** 使用python爬取csdn我的博客的訪問量,主要用來練手 ''' import urllib2 import re page_num = 1 notLast = 1 account = str(raw_input('輸入csdn的登陸帳號:')) while notLast: baseUrl = 'http://blog.csdn.net/'+account myUrl = baseUrl+'/article/list/'+str(page_num) user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)' headers = {'User-Agent':user_agent} req = urllib2.Request(myUrl,headers=headers) myResponse = urllib2.urlopen(req) myPage = myResponse.read() notLast = re.findall('<a href=".*?">尾頁</a>',myPage,re.S) print '---------------第%d頁-------------' % (page_num,) title = re.findall('<span class="link_title"><a href=".*?">(.*?)</a></span>',myPage,re.S) titleList=[] for items in title: titleList.append(str(items).lstrip().rstrip()) view = re.findall('<span class="link_view".*?><a href=".*?" title="閱讀次數">閱讀</a>\((.*?)\)</span>',myPage,re.S) viewList=[] for items in view: viewList.append(str(items).lstrip().rstrip()) for n in range(len(titleList)): print '訪問量:%s 標題:%s' % (viewList[n].zfill(4),titleList[n]) page_num = page_num + 1 ''' Created on 2017年3月19日 @author: SUN HuaQiang 目的:使用python爬取csdn我的博客的訪問量,主要用來練手Python爬蟲 收穫:1.瞭解Python爬蟲的基本過程 2.在Python2的基礎上實現Python3,經過對比發現版本之間的差別 ''' import urllib.request import urllib import re page_num = 1 notLast = 1 account = str(input('請輸入csdn的登陸帳號:')) while notLast: baseUrl = 'http://blog.csdn.net/' + account myUrl = baseUrl+'/article/list/' + str(page_num) user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)' headers = {'User-Agent':user_agent} req = urllib.request.Request(myUrl,headers=headers) myResponse = urllib.request.urlopen(req) myPage = myResponse.read().decode() notLast = re.findall('<a href=".*?">尾頁</a>', myPage, re.S) print ('-----------第%d頁--------------' % (page_num,)) title = re.findall('<span class="link_title"><a href=".*?">(.*?)</a></span>',myPage,re.S) titleList=[] for items in title: titleList.append(str(items).lstrip().rstrip()) view = re.findall('<span class="link_view".*?><a href=".*?" title="閱讀次數">閱讀</a>\((.*?)\)</span>',myPage,re.S) viewList=[] for items in view: viewList.append(str(items).lstrip().rstrip()) for n in range(len(titleList)): print ('訪問量:%s 標題:%s' % (viewList[n].zfill(4),titleList[n])) page_num = page_num + 1for items in title: titleList.append(re.sub('<font color="red">.*?</font>', '', str(items).lstrip().rstrip()))<ul id="blog_rank"> <li>訪問:<span>459285次</span></li> <li>積分:<span>9214</span> </li> <li >等級: <span style="position:relative;display:inline-block;z-index:1" > <img src="http://c.csdnimg.cn/jifen/images/xunzhang/jianzhang/blog6.png" alt="" style="vertical-align: middle;" id="leveImg"> <div id="smallTittle" style=" position: absolute; left: -24px; top: 25px; text-align: center; width: 101px; height: 32px; background-color: #fff; line-height: 32px; border: 2px #DDDDDD solid; box-shadow: 0px 2px 2px rgba (0,0,0,0.1); display: none; z-index: 999;"> <div style="left: 42%; top: -8px; position: absolute; width: 0; height: 0; border-left: 10px solid transparent; border-right: 10px solid transparent; border-bottom: 8px solid #EAEAEA;"></div> 積分:9214 </div> </span> </li> <li>排名:<span>第1639名</span></li> </ul> <ul id="blog_statistics"> <li>原創:<span>425篇</span></li> <li>轉載:<span>44篇</span></li> <li>譯文:<span>2篇</span></li> <li>評論:<span>108條</span></li> </ul> #利用正則表達式獲取博客信息 sumVisit = re.findall( credit = re.findall( rank = re.findall( grade = re.findall( original = re.findall( reprint = re.findall( trans = re.findall( comment = re.findall(staData = re.findall( for i in staData: print(i[0] + from bs4 import BeautifulSoup import time, datetime from maya_Spider import url_manager, html_downloader, html_parser, html_outputer class Spider_Main(object): def __init__(self): self.urls = url_manager.UrlManager() self.downloader = html_downloader.HtmlDownloader() self.parser = html_parser.HtmlParser() self.outputer = html_outputer.HtmlOutputer() def craw(self, root_url): count = 1 self.urls.add_new_url(root_url) while self.urls.has_new_url(): try: new_url = self.urls.get_new_url() print('craw %d : %s' % (count, new_url)) html_content = self.downloader.download(new_url) new_urls, new_data = self.parser.parse(new_url, html_content) self.urls.add_new_urls(new_urls) self.outputer.collect_data(new_data) if count == 10: break count = count + 1 except: print('craw failed') self.outputer.output_html() if __name__ == '__main__': root_url = 'http://baike.baidu.com/view/21087.htm' print('開始計時..............') start_time = datetime.datetime.now() obj_spider = Spider_Main() obj_spider.craw(root_url) end_time = datetime.datetime.now() print('總用時:%ds'% (end_time - start_time).seconds)class UrlManager(object): def __init__(self): self.new_urls = set() self.old_urls = set() def add_new_url(self, url): if url is None: return if url not in self.new_urls and url not in self.old_urls: self.new_urls.add(url) def add_new_urls(self, urls): if urls is None or len(urls) == 0: return for url in urls: self.add_new_url(url) def has_new_url(self): return len(self.new_urls) != 0 def get_new_url(self): new_url = self.new_urls.pop() self.old_urls.add(new_url) return new_urlimport urllib import urllib.request class HtmlDownloader(object): def download(self, url): if url is None: return None user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)' headers = {'User-Agent':user_agent} req = urllib.request.Request(url,headers=headers) response = urllib.request.urlopen(req) return response.read().decode()import re import urllib from urllib.parse import urlparse from bs4 import BeautifulSoup class HtmlParser(object): def _get_new_urls(self, page_url, soup): new_urls = set() links = soup.find_all('a', href=re.compile(r'/item/.*?')) for link in links: new_url = link['href'] new_full_url = urllib.parse.urljoin(page_url, new_url) new_urls.add(new_full_url) return new_urls def _get_new_data(self, page_url, soup): res_data = {} res_data['url'] = page_url title_node = soup.find('dd', class_="lemmaWgt-lemmaTitle-title").find('h1') print(str(title_node.get_text())) res_data['title'] = str(title_node.get_text()) summary_node = soup.find('div', class_="lemma-summary") res_data['summary'] = summary_node.get_text() return res_data def parse(self, page_url, html_content): if page_url is None or html_content is None: return None soup = BeautifulSoup(html_content, 'html.parser', from_encoding='utf-8') new_urls = self._get_new_urls(page_url, soup) new_data = self._get_new_data(page_url, soup) return new_urls, new_dataclass HtmlOutputer(object): def __init__(self): self.datas = [] def collect_data(self, data): if data is None: return self.datas.append(data ) def output_html(self): fout = open('maya.html', 'w', encoding='utf-8') fout.write("<head><meta http-equiv='content-type' content='text/html;charset=utf-8'></head>") fout.write('<html>') fout.write('<body>') fout.write('<table border="1">') fout.write('''<tr style="color:red" width="90%"> <th>Theme</th> <th width="80%">Content</th> </tr>''') for data in self.datas: fout.write('<tr>\n') fout.write('\t<td align="center"><a href=\'%s\'>%s</td>' % (data['url'], data['title'])) fout.write('\t<td>%s</td>\n' % data['summary']) fout.write('</tr>\n') fout.write('</table>') fout.write('</body>') fout.write('</html>') fout.close()pip install pymysql3#引入pymysql import pymysql #當成是mysqldb同樣使用,固然也能夠不寫這句,那就按照pymysql的方式 pymysql.install_as_MySQLdb()import pymysql print(pymysql) import pymysql try: conn = pymysql.connect(host='localhost', port=3308, user='lmapp', passwd='lmapp', db='test', charset='utf8') cur = conn.cursor() sql_query = "select * from user" sql_insert = "insert into user(uid, uname, passwd) VALUES ('18853883587', 'SHQ', 'TEST')" sql_update = "update user set uname='ZQY' WHERE uid='18353102061'" sql_delete = "delete from user WHERE uid='18353102062'" cur.execute(sql_query) data = cur.fetchall() cur.execute(sql_insert) print(cur.rowcount) cur.execute(sql_update) print(cur.rowcount) cur.execute(sql_delete) print(cur.rowcount) for d in data : print(type(d[0])) print("UID: "+d[0]+' 用戶名: '+d[1]+" 密碼: "+d[2]) conn.commit() cur.close() conn.close() except Exception : conn.rollback() print("操做失敗") import pymysql class TranferMoney(object): def __init__(self, conn): self.conn = conn def check_acct_available(self, source_acctid): try: cursor = self.conn.cursor() sql_query = "select * from account where acctid='%s'"%source_acctid cursor.execute(sql_query) print('check_acct_available:', sql_query) rs = cursor.fetchall() if len(rs) != 1: raise Exception('賬號%s不存在'%source_acctid) finally: cursor.close() def has_enough_money(self, source_acctid, money): try: print(type(money)) cursor = self.conn.cursor() sql_query = "select * from account where acctid=%s and money >= %d"%(source_acctid, money) cursor.execute(sql_query) print('has_enough_money:', sql_query) rs = cursor.fetchall() if len(rs) != 1: raise Exception('賬號%s餘額不足'%source_acctid) finally: cursor.close() def reduce_money(self, source_acctid, money): try: cursor = self.conn.cursor() sql_query = "update account set money=money-%d where acctid = '%s'"%(money, source_acctid) cursor.execute(sql_query) print('reduce_money:', sql_query) if cursor.rowcount != 1: raise Exception('賬號%s減款錯誤'%source_acctid) finally: cursor.close() def add_money(self, source_acctid, money): try: cursor = self.conn.cursor() sql_query = "update account set money=money+%d where acctid = '%s'"%(money, source_acctid) cursor.execute(sql_query) print('reduce_money:', sql_query) if cursor.rowcount != 1: raise Exception('賬號%s加款錯誤'%source_acctid) finally: cursor.close() def transfer(self, source_acctid, target_accid, money): try: self.check_acct_available(source_acctid) self.check_acct_available(target_accid) self.has_enough_money(source_acctid, money) self.reduce_money(source_acctid, money) self.add_money(target_accid, money) self.conn.commit() except Exception as e: print("Exception:", e) self.conn.rollback() raise e if __name__ == '__main__': source_acctid = input("請輸入轉帳方賬號:") target_accid = input("請輸入收款方賬號:") money = input("請輸入轉款金額:") conn = pymysql.connect(host='localhost', port=3308, user='lmapp', passwd='lmapp', db='test', charset='utf8') tranfer_money = TranferMoney(conn) try: tranfer_money.transfer(source_acctid, target_accid, int(money)) print("轉帳成功") except Exception as e: print('Error:', e) finally: conn.close() import MySQLdb db = MySQLdb.connect("localhost","testuser","test123","TESTDB" ) cursor = db.cursor() sql = """INSERT INTO EMPLOYEE(FIRST_NAME, LAST_NAME, AGE, SEX, INCOME) VALUES ('Mac', 'Mohan', 20, 'M', 2000)""" try: cursor.execute(sql) db.commit() except: db.rollback() db.close() 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'mydatabaseName', 'USER': 'mydatabaseuser', 'PASSWORD': 'mypassword', 'HOST': '127.0.0.1', 'PORT': '3306', } python manage.py runserverimport pymysql pymysql.install_as_MySQLdb() DATABASES = { # 'default': { # 'ENGINE': 'django.db.backends.sqlite3', # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), # }, 'default': { 'ENGINE': 'django.db.backends.mysql', 'OPTIONS':{'read_default_file': os.path.join(BASE_DIR, 'database.cnf'),} #數據庫名 # 'NAME' : 'csdn', # 'USER' : 'lmapp', # 'PASSWORD' : 'lmapp', # 'HOST' : '127.0.0.1', # 'PORT' : '8088', } }[client] database = 'csdn' user = 'lmapp' password = 'lmapp' default-character-set = utf8 host = '127.0.0.1' port = 8088python manage.py makemigrations python manage.py migratepython manage.py createsuperuser # 按照提示輸入用戶名和對應的密碼就行了郵箱能夠留空,用戶名和密碼必填 # 修改 用戶密碼能夠用: python manage.py changepassword username from django.http import HttpResponse from django.shortcuts import render, render_to_response from blog import models def blogs(request): articles = models.Blog.objects.all() return render_to_response("blog/index.html",locals()) index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>CSDN</title> </head> <body> {{ article.title }} {{ article.viewcnt }} <body> <p>博文信息</p> {% for article in articles %} <p>{{article.title}}   :   {{article.viewcnt}}</p> <br> {% endfor %} </body> </body> </html>python manage.py createsuperuserLANGUAGE_CODE = 'zh-Hans'from django.contrib import admin # Register your models here. from blog.models import User,Blog admin.site.register(User) admin.site.register(Blog) from django.db import models class User(models.Model): uid = models.CharField(primary_key=True, max_length=30) homeurl = models.CharField(max_length=45) sumvisit = models.IntegerField() credit = models.IntegerField() grade = models.IntegerField() rank = models.IntegerField() fans = models.IntegerField() original = models.IntegerField() reprint = models.IntegerField() trans = models.IntegerField() comment = models.IntegerField() blogcnt = models.IntegerField() def __str__(self): return self.uid class Blog(models.Model): uid = models.CharField(max_length=30) title = models.CharField(max_length=200) url = models.CharField(primary_key=True, max_length=30, null=False) viewcnt = models.IntegerField() def __str__(self): return self.title#設置每頁顯示條目數 list_per_page = 30from django.contrib import admin # Register your models here. from blog.models import User,Blog class ArticleAdmin(admin.ModelAdmin): list_display = ('title', 'viewcnt',) admin.site.register(Blog,ArticleAdmin) admin.site.register(User) # admin.site.register(Blog)from django.contrib import admin from blog.models import User,Blog class ArticleAdmin(admin.ModelAdmin): list_display = ('title', 'viewcnt',) search_fields = ('title',) def get_search_results(self, request, queryset, search_term): queryset, use_distinct = super(ArticleAdmin, self).get_search_results(request, queryset, search_term) try: search_term_as_int = int(search_term) queryset |= self.model.objects.filter(age=search_term_as_int) except: pass return queryset, use_distinct admin.site.register(Blog,ArticleAdmin) admin.site.register(User) fans = models.IntegerField(verbose_name="粉絲")class Meta: verbose_name = "博文" verbose_name_plural = "博文"func(*args, **kwargs)
def funcA(): passdef funcB(a, b): print a print bdef funcC(a, b=0): print a print bdef funcD(a, b, *c): print a print b print "length of c is: %d " % len(c) print cfuncB(a=100, b=99)funcB(b=99, a=100)def funcF(a, **b): print a for x in b: print x + ": " + str(b[x])file_object = open('thefile.txt') try: all_the_text = file_object.read( ) finally: file_object.close( ) input = open('data', 'r') input = open('data') input = open('data', 'rb') file_object = open('thefile.txt') try: all_the_text = file_object.read( ) finally: file_object.close( ) file_object = open('abinfile', 'rb') try: while True: chunk = file_object.read(100) if not chunk: break do_something_with(chunk) finally: file_object.close( ) list_of_all_the_lines = file_object.readlines( ) for line in file_object: process line output = open('data', 'w') output = open('data', 'wb') output = open('data', 'w+') file_object = open('thefile.txt', 'w') file_object.write(all_the_text) file_object.close( ) file_object.writelines(list_of_text_strings)file = open('test.log', 'r') sizehint = 209715200 position = 0lines = file.readlines(sizehint) while not file.tell() - position < 0: position = file.tell() lines = file.readlines(sizehint)file(name[, mode[, buffering]]) F.read([size]) #size爲讀取的長度,以byte爲單位 F.readline([size]) #讀一行,若是定義了size,有可能返回的只是一行的一部分 F.readlines([size]) #把文件每一行做爲一個list的一個成員,並返回這個list。其實它的內部是經過循環調用readline()來實現的。若是提供size參數,size是表示讀取內容的總長,也就是說可能只讀到文件的一部分。 F.write(str) #把str寫到文件中,write()並不會在str後加上一個換行符 F.writelines(seq) #把seq的內容所有寫到文件中。這個函數也只是忠實地寫入,不會在每行後面加上任何東西。 file的其餘方法: F.close() #關閉文件。python會在一個文件不用後自動關閉文件,不過這一功能沒有保證,最好仍是養成本身關閉的習慣。若是一個文件在關閉後還對其進行操做會產生ValueError。 F.flush() #把緩衝區的內容寫入硬盤 F.fileno() #返回一個長整型的」文件標籤「 F.isatty() #文件是不是一個終端設備文件(unix系統中的) F.tell() #返回文件操做標記的當前位置,以文件的開頭爲原點 F.next() #返回下一行,並將文件操做標記位移到下一行。把一個file用於for ... in file這樣的語句時,就是調用next()函數來實現遍歷的。 F.seek(offset[,whence]) #將文件打操做標記移到offset的