基于Python2.7學習
(一)概述
一、為什么學Python
- 語法簡單,易上手;
- 豐富的庫支持,對Json支持,http、ftp、file、進程等;
- 完整的生態圈,一切皆有可能(大數據,云計算,自動化運維等常見);
結合unix-shell和C的使用習慣,在2000年發布2.0實現垃圾回收和Unicode支持。
二、特點
- 免費開源
- 動態數據類型,高層語言(沒有類型檢查)
- 可移植行,個別模塊跟操作系統os有關
- 面向對象
- 可擴展性,底層用C實現
- 豐富的標準庫
三、生態圈
- 不同解釋器支持
- web應用開發
- 科學計算與大數據分析
- 云計算
幾種解釋器:
- Cpython解釋器:C語言實現,常見解釋器;
- Jython解釋器:JVM,Java庫;
- IronPython:.NET
- pypy:基于JIT的python解釋器,即時編譯;
四、Python web開發框架
- Django,最流行和成熟的web開發框架
- Tornado,Facebook開發的高性能web服務
- Uliueb,國人開發的web框架
- Flask
五、Python社區
華蟒用戶組,中文社區
啄木鳥社區
豆瓣Python小組
六、安裝Django
pip install django --index-url=http://pypi.douban.com/simple
python manage.py install
(二)Python基礎
一、Python參數傳遞
參數傳遞順序依次:
- 位置參數傳遞
- 關鍵字傳遞
- 表傳遞(列表)
- 字典傳遞
位置參數傳遞:值傳遞;
關鍵字傳遞:根據每個參數的名字傳遞;
表傳遞:表傳遞給函數的是一個指針,指針指向序列在內存中的位置;
字典傳遞:包裹傳參;
例如:
def f(a, b=None, c=3, *args, **kwargs):
pass
混合傳參順序:先位置,再關鍵字,再包裹位置,再包裹關鍵字;
關鍵字傳參與位置傳參混用時,位置傳參須在關鍵字傳參之前;
def foo(name, count=1, *args, **kwargs):
print name
print count
print args
print kwargs
foo("python", 12, *(13,14,15), **{'a':1, 'b':2})
foo("python", *(13,14,15), **{'a':1, 'b':2})
二、MVT架構
三、Django框架
- 包管理器安裝
pip install django --index-url http://pypi.douban.com/simple
倉庫:
http://pypi.douban.com/simple # 豆瓣python模塊鏡像
http://pypi.python.org/pypi # 中央倉庫
- 從源碼安裝
下載Django的壓縮包并解壓;然后執行:
python setup.py install
- 創建第一個Django的project
django-admin.py startproject [projname]
項目目錄結構:
manage.py # Django應用的管理工具
project/
settings.py # 整個項目的核心配置文件,數據庫、緩存、session等
urls.py # URL轉發的配置文件
wsgi.py
manage.py:管理Django項目命令行工具,支持多個命令,支持擴展自定義的命令,創建數據庫schema,啟動內嵌的應用服務器;
python manage.py [subcomand]
python manage.py help
settings.py:整個項目的核心配置文件
- 數據庫的連接信息
- 緩存配置
- session配置
- 靜態文件配置,比如:css、js
- 用戶自定義信息
運行app:
python manage.py startapp [app name]
- ORM
- Django原生支持關系映射;
- 每個APP的models.py里面包含了schema的信息;
- 每次啟動項目的時候,都會去驗證models.py中的schema和數據庫中表對應結構的一致性;
- 通過
python manage.py syncdb
來創建表;
model類:
每個model類表示一張表,生成的數據庫表的名字默認是APP的名字_類的名字
;
每個model類里面都有多個Filed的Instance變量;
primary key:
默認情況下每個Model類,Django都會自動添加一個id的Integer Field變量作為主鍵;
用戶也可以自己指定pk字段,默認就可以;
Query:
[Model Class].Objects.get()
eg. Blog.Objects.get(pk=1)
[Model Class].Objects.[filter/exclude] # 根據特定條件篩選記錄
[Model Class].Objects.all() # 返回表中的全部數據
QuerySet:
Filter/exclude/all :三個API返回都是一個QuerySet的對象;
QuerySet :可以理解為Model實例的集合;
Lazy Mode :真正Query時查詢,不是時時查詢;
QuerySet in Chain :
Blog.Objects.all().filter(count_it=10)
ORM缺陷:
需要先手工創建一個空的數據庫,無法更新schema的變量;第三方解決http://south.aeracode.org/,自Django1.7+,migration被構建到Django核心模塊中,可以使用migration工具遷移schema,更新數據庫。
- URL與視圖的映射
- 無參數的映射
url(r'^test/$', get_blog_view)
- 帶位置參數的映射
url(r'^(\d{4})/$', get_blog_view)
def get_blog_view(req, bid):
pass
- 關鍵字參數的映射
url(r'^(?P<blog id>\d{4})/$', get_blog_view)
def get_blog_view(req, blogid):
pass
URL采用最先匹配原則,匹配范圍大的URL放在最后。
- Template
{...} 變量
{% ... %} 模板標簽
{% IF %} ... {% END IF %}
{% FOR %} ... {% END FOR %}
模板上下文:
視圖函數返回一個模板的時候,需要傳入一個上下文(Context),Context是一個字典,key表示的是模板中的變量名字,value表示渲染完成后實際展示在HTML中的內容。
def ament_datetime(request):
now = datetime.datetime.now()
return render_to_response('current_datetime.html', {'current_date': now})
模板繼承:
css、HEADER、FOOTER寫一次,其他模塊可用
通過Block ... Extend
繼承
靜態文件處理:
JS、CSS等靜態文件的請求處理,settings.py中的STATIC
變量指定了靜態文件的根目錄。
四、Python語法
- 編寫腳本文件在第一行添加代碼
#!/usr/bin/python
#!/usr/local/bin/python
在第二行添加:
# coding:utf8
#-*- coding:utf8 -*-
- 鏈式賦值:
a, b = "django", 2
python不支持A++,A--操作;
Python3:只支持長整型;
切片操作:slice
布爾值:True ,False
dict[key] 查找,效率為O(1)
字典中key唯一,可以Hash的值。
dict[key]查找,也可以用key in dict方式來判斷字典是否包含key的鍵。
- 循環語句
for ... :
...
else:
...
當for, while正常循環退出時,會執行else語句;當for, while非正常退出時,不會執行else語句;
非正常退出,相當于break
try ... :
...
except _, e:
...
except e2:
...
else:
...
finally:
...
不拋異常時,執行else語句
- Python多重繼承
Class A(ParentA, ParentB, ...):
pass
__init__
是Class構造函數,用來初始化對象
isDuplicate(s) # s是一個字符串,是否含有重復的字符
isPalindrome(s) # s是一個字符串,字符串是否是回文
- 搜索路徑
Python會在以下路徑中搜索他想要的尋找的模塊:
- 程序所在文件夾
- 標準庫的安裝路徑
- 操作系統環境變量PYTHONPATH所包含的路徑
- Python解釋器負責內存管理
id():返回對象的內存地址
引用計數為0時,GC才回收內存
整型緩沖池:整型數據被放到一個緩沖池中
a=1
b=1
id(a)與id(b)一樣,用來判斷是否為同一對象。
is:用來判斷兩個變量是不是指向同一個內存對象
python緩存整數和短字符串,因此每個對象只存有一份,所有整數的引用都指向同一個對象。即使使用賦值語句,也只是創造了新的引用,而不是對象本身。
- 包管理器
pip是Python自帶的包管理程序
pip install web.py
pip uninstall web.py
pip install --upgrade web.py
which python # 查看Python安裝路徑
whereis python # 查看Python安裝路徑
pip install --install-option="--prefix=/home/vamei/util/" web.py # 模塊安裝路徑:/home/vamei/util/
- global
def func1():
global i
global lock
if __name__ == "__main__":
i = 100
lock = threading.Lock()
func1()
在函數中使用global聲明全局變量;i、lock為不可變數據對象,被當作一個局部變量,所以用global聲明;
對于可變數據對象,則不需要global聲明;可以將可變數據對象作為參數來傳遞給線程函數,這些線程將共享這些可變數據對象。
- 線程
在UNIX平臺上,當某個進程終結之后,該進程需要被其父進程調用wait,否則進程成為僵尸進程(Zombie),所以有必要對每個process對象調用join()方法(實際上等同于wait)。對于多線程來說,由于只有一個進程,所以不存在此必要性。
多線程,可以使用共享資源,比如使用全局變量或傳遞參數。
多進程應避免共享資源,每個進程有自己獨立的內存空間,可以通過共享內存和Manager的方法共享資源。 - 列表解析
列表解析比for循環性能好很多
[expr for iter in iterable [if condition]] # 列表解析
filter(function, iter):用來對列表中的元素進行過濾,function返回false時,該元素就被丟棄。
map(function, iter):把function(x)作用于列表的每一個元素,然后函數的結果根據順序構成一個新的列表返回。
列表解析缺點:
內存使用效率較低,每次都要把被操作的列表中的元素一次性裝載到內存里。
另一個解決方案:生成器表達式
- 每次只加載一個元素到內存中
- 返回一個可迭代的對象
- 生成器表達式
(expr for iter in iterable [if condition]) # 返回generator對象
res = (expr for iter in iteralbe [if condition])
for i in res:
print i
對內存要求較高時,使用生成器表達式
返回范圍較大的列表時用xrange
- 字典和集合
字典:任何一個可以被Hash的數據類型都可以用作key;字典是無序的,值可以是任意數據類型;基于Hash表實現。
類實例做key,需要類實現__hash__
方法返回哈希值。
列表不可以做key,字典本身不能做key
元組可以做key,但要求元組中不包含列表、字典等可變類型的數據結構。
使用hash()函數來檢查是否可以用作key
字符串可以做key
d = {'a':1, 'b':2}
d = dict(a=1, b=2)
d.get('c', 'Default') # 若字典中沒有key為c,則返回默認值Default
d.keys() # 返回已存在的key的可迭代對象
if 'a' in d:
print e.get('a') # 使用in判斷key是否在字典中
集合:元素不可重復,一組無序排列的可哈希的值,支持Union、intersection等。
set:可變集合,值是可哈希的
frozenset:不可變集合
in
:判斷是否存在,for
:遍歷
集合操作函數:
更新集合:add、remove、update
高級操作:
- union:聯合(|)
- intersection:交集(&)
- difference:差集(-)
- symmetric_difference:異或(^)
五、函數式編程
- 函數對象
def foo():
pass
foo:函數對象
foo():函數調用
a = foo
a() # 等價函數調用foo()
不支持重載,在同一模塊中定義相同名字的函數,無論參數個數,后定義的一個會覆蓋之前的那個。
可以返回多個值,以元組形式返回,也可以用多個變量接收返回的多個值。
- lambda
返回可調用的函數對象
不需要return來返回結果
函數聲明和定義均在一行
foo = lambda x : x+1 if x > 10 else x - 10
foo(1)
- 變量查找順序
- 局部作用域
- 全局作用域
- global關鍵字
- 閉包
def fx(x):
def gy(y):
return x + y
return gy
foo = fx(5)
print foo(10) # 結果15
裝飾器:被用于有切面需求的場景,較為經典的有插入日志、性能測試、事務處理、Web權限校驗、Cache等。
- 無參數decorator
生成一個新的裝飾器函數 - 有參decorator
有參裝飾,裝飾函數先處理參數,再生成一個新的裝飾器函數,然后對函數進行裝飾。
- 面向對象編程
特征:
- 抽象/實現
- 封裝/接口
- 合成
- 派生/繼承
- 多態
- 自省/反射
class A(): # 經典類
pass
class B(object): # 新式類
pass
建議使用新式類,新式類必須有一個父類;
可使用type()測試,type(A)和type(B)
type(A):返回<type 'classobj'>
type(B):返回<type 'type'>
調用父類的__init__
方法:
A.__init__(self) # 經典類
super(B, self).__init__()
實例方法:
方法定義在類中,第一個位置參數為self,self表示實例對象的本省,只能被實例所調用;在調用實例方法時,不需顯示地傳入self,解釋器默認傳入。
Python構造函數:__init__
,但不是真正的構造函數,不會創建對象。
使用__new__
來構造對象
使用__init__
來初始化對象
當使用A()創建實例時,默認使用__init__
方法初始化對象。
類變量和實例變量:
類變量綁定在類上,實例共享;實例變量綁定在實例對象上,通常使用self.x來表示實例變量。給實例對象賦值時,默認創建實例變量;在查找時,先查找對象本身的屬性實例變量,再查找類的屬性類變量。
class A(object):
author = "Guido"
def __init__(self, page):
self.page = page
book_a = A(10)
book_b = A(100)
book_a.author = "python"
print book_a.author # 輸出"python",author作為book_a的實例變量
print book_b.author # 輸出"Guido",沒有賦值,使用類變量,可用id()檢查
- 類方法和靜態方法
類方法的第一個位置參數不是self,而是cls,表示綁定到類上。
使用@staticmethod
來裝飾一個靜態方法,靜態方法不需要self和cls。
使用@classmethod
來裝飾一個類函數。
類方法:
@classmethod
def class_method(cls):
pass
靜態方法:
@staticmethod
def static_method(msg):
print "[" + msg + "]"
子類若沒有自己定義__init__
方法,會默認調用基類的__init__
方法;
若子類定義了__init__
方法,則需要顯式調用基類的__init__
方法,并且傳入self參數;
super()
:只工作在新式類
dir()
:查看對象所有屬性和方法
__dict__
:類的字典屬性
__doc__
:類的文檔屬性
__new__
:類函數,構造對象
__init__
:初始化對象
__del__
:當對象的引用計數為0時,自動調用,釋放內存,要首先調用基類的__del__
__X
:定義private變量,只有類的內部可以引用
對于實例對象不存在的屬性進行賦值,會動態創建這個屬性,新式類可以通過設定__slot__
的類屬性來防止這個問題。
issubclass(sub, sup) # 判斷是否為子類
isinstance(obj, classType) # 判斷是否為類的實例
super(A, self) 返回Instance
super(A, cls) 返回type
- 單元測試
- nose
- pytest
namespace:相當于字典
模塊中的變量相當于單例模式
hashcod要求唯一,計算下標
- Python單例模式
class A(object):
instance = None
def __new__(cls, *args, **kwargs):
if not cls.instance:
cls.instance = object.__new__(cls, *args, **kwargs)
return cls.instance
print id(A())
print id(A()) # 值相同
- python常用模塊
模塊文檔API:
https://docs.python.org/2/library/
使用場景:
- 操作系統相關
- 文件路徑處理
- 網絡處理
- 數據處理
os.path模塊:處理文件路徑
os.path.join("/a", "b", "c", "d.txt")
__file__ # 獲取當前文件/模塊的路徑
os模塊:
- 系統環境變量
- Linux系統上的文件處理
- 進程處理
os.environ:可以改環境變量
sys:獲取傳入給程序的外部參數argv,進程的輸入輸出流sys.stdout,sys.stdin環境信息相關。
import sys
sys.executable #判斷程序運行的環境
Python從外部獲取的參數為字符串。
# 重定向stdout
_back = sys.stdout
f = open("txt.txt", "w")
sys.stdout = f
print "kkk"
f.close()
sys.platform:查看程序運行在什么平臺
subprocess:
Popen:用來創建子進程
網絡相關:
- urllib
- httplib
數據處理:
- xml模塊
- json模塊
六、virtualenv和virtualenvwrapper
- virtualenv
pip install virtualenv
pip freeze
pip freeze | wc -l # 統計安裝的模塊
virtualenv ENV # 創建一個virtualenv的一個虛擬環境ENV
source ./ENV/bin/activate # 啟動ENV
deactivate # 離開virtualenv環境
which python # 查看Python可執行文件的路徑
所有安裝在系統范圍內的包對于virtualenv是可見的,這意味著若將simplejson安裝在系統Python目錄中,它會自動提供給所有的virtualenv使用。這種行為可以被更改,在創建virtualenv時增加--no-site-packages
選項的virtualenv就不會讀取系統包,例如:virtualenv ENV --no-site-package
。
- virtualenvwrapper
建立在virtualenv上的工具,通過它可以方便的創建/激活/管理/銷毀虛擬環境。
workon ENV # 啟用ENV
workon # 列出所有虛擬環境
mkvirtualenv ENV # 創建
workon ENV
rmvirtualenv ENV
七、回顧
- 當應用計數為0時,GC回收變量占用的 內存;
del 變量名
:刪除變量,釋放占用的內存;
is
語句:用來判斷兩個變量是不是指向同一個內存對象; - 聲明編碼格式,支持中文
# coding:utf8 或
# -*- coding:utf8 -*- # 一般放在第二行
#!/usr/bin/python # 放在第一行
- built-in類型
- 數值類型
- 布爾類型
- 序列類型
- 集合類型
- 映射類型
- python模塊
Python程序由多個模塊文件組成,模塊是程序執行的唯一入口;模塊是可以被其他模塊導入,模塊文件為文件名。
- 模塊執行最簡單方法
python [module].py
#! /usr/bin/python # 當前python解釋器
- 也可以使用./module.py來調用
模塊中定義了什么:
- 變量[模塊級別]
- 函數的定義
- 類的定義
- 程序的實際調用邏輯
- 數據類型
使用弱類型
- built-in類型
- 自定義的類型(類,integer)
變量名字大小寫敏感,以下劃線、數字、字母命名,以下劃線、字母開頭;
支持多個變量的同時定義,簡化代碼編寫:
a, b = 'django', 2
數據類型:
- 整型:32/64 bit,在python3已移除
- 長整型:沒有長度限制,受內存大小限制
- 浮點型
- 復數類型
/ # 普通除法,兩個均為整數時,四舍五入;為浮點數時,結果為浮點數;
// # 地板除,只保留整數部分
空列表、空元組、空字符串、0均表示False
對象三要素:
- identity(身份),對應于內存地址,不可修改
- type(類型),不可修改
- value(值),immutable不可修改和mutable可修改
list | tuple | string正負下標表示:
- 正:0,1,2,...,n-1
- 負:-n,-n-1,...,-2,-1
list支持extend操作,支持原地修改
[list].extend([list])
list(), tuple():創建了一個新的序列對象
字符串是不可變序列,任何一點修改都會創建新的字符串對象。每次'+'操作都會生成一個新的字符串對象。
"".join(序列)
拷貝:
- 淺拷貝:list,tuple工廠函數;切片;copy模塊的copy函數;
淺拷貝不會生成一個新的 序列,指向同一個列表。 - 深拷貝:生成一個新的序列
import copy
c = copy.deepcopy(a)
Tips:持續更新。。。