国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

跟我一起Django-03Django工程師一定要知道的Python

2019-11-14 17:35:04
字體:
來源:轉載
供稿:網友

目錄:

  1. Python技術就是Django技術
  2. Python交互解釋器python&ipython
  3. Python語法基礎,注釋、變量和賦值,符號
  4. Python標準類型,布爾,數字,字符串str,列表list,元組tuple,字典dict
  5. Python流程控制
  6. Python異常處理
  7. 文件
  8. 函數
  9. 面向對象編程
  10. 正則表達式
  11. 常見錯誤
  12. 代碼風格
  13. 總結

參照內容:經典Django教程《Python+Django+Web開發指南》

重點概念:

交互解釋器tab還是空格對象的布爾值經典除法 真正除法內置數字工廠序列列表,字符串,元組列表推導式生成器表達式不可變字符串指示符內置序列函數表達式 語句匿名函數 lambda垃圾自動回收動態實例屬性

3.1 Python技術就是Django技術

Django提供了一個高級的框架,用它只需要很少代碼就可以完成一個Web應用。

Django使用Python寫成的,Python是一門OOP的開發語言,同時兼具系統語言(C、C++、java)的強大和腳本語言(Ruby和VB)的靈活迅速。

本節主要總結Django工程師一定要知道的Python概念,而不是一份通用的Python教程。

http://m.survivalescaperooms.com/ganiks

3.2 入門:Python交互解釋器

Python Shell中,不用去創建和保存一個源文件,就可以直接把代碼拿來測試。

>>> PRint 'Hello world!'Hello World!

來看一個復雜的例子:

ganiks.liu@MAMIS-GAIKS-LIU /E/mysite (master)$ pythonPython 2.7.5 (default, May 15 2013, 22:43:36) [MSC v.1500 32 bit (Intel)] on win32Type "help", "copyright", "credits" or "license" for more information.>>> for Word in ['capitalize', 'these', 'words']:... print word.upper()  File "<stdin>", line 2    print word.upper()        ^IndentationError: expected an indented block>>> for word in ['capitalize', 'these', 'words']:...     print word.upper()...CAPITALIZETHESEWORDS>>> for i in rang(0,5):...     print i...Traceback (most recent call last):  File "<stdin>", line 1, in <module>NameError: name 'rang' is not defined>>> for i in range(0,5):...     print i...01234>>>

python語法中重要的一個方面就是沒有區分代碼庫的花括號{ }, 而是用對齊來替代

更高級的交互解釋器iPython

iPython的能力完全是另一個數量級上的解釋器。它提供了系統shell訪問、命令行技術、自動對齊、命令行歷史等許多特性。

在解釋器里使用Django

要是能在Python的解釋器中調試Django應用是不是很酷?

  • 假如你只是按照常規啟動解釋器并且試著導入Django模塊,你只能得到一個
    DJANGO_SETTINGS_MODULE沒有設置的錯誤。為了方便起見,Django提供了一個manage.py
    shell命令,能進行一些必要的環境設置來避免
  • 如果安裝了 iPython, manage.py shell 會默認使用它。
  • 如果你安裝了iPython,又希望能使用標準Python解釋器的話,可以運行manage.py
    shell plain

3.3 Python基礎

  • 注釋 —— #
  • 變量和賦值 —— 除非你想解釋器詢問更多信息,否則你不可能百分百確定變量在任何給定的時刻是什么類型的對象

    $ pythonPython 2.7.5 (default, May 15 2013, 22:43:36) [MSC v.1500 32 bit (Intel)] on win32Type "help", "copyright", "credits" or "license" for more information.>>> foo = 'bar'>>> foo'bar'>>> type(foo)<type 'str'>>>> foo = 1>>> type(foo)<type 'int'>>>>
  • 運算符
  • 避免使用的符號
  • 結尾的 ;
  • $
  • 條件語句的()

Python的作者:只有干凈和容易閱讀的代碼才能避免混亂

3.4 Python標準類型

  • 標量(scalar)
  • 文字量(literal) 比如數字/字符串
  • 多個Python對象組織在一起的容器、數據結構

3.4.1 對象的布爾值

所有的Python值都可以表示為布爾值,這個的用處在哪里?
在于if和while語句里面做條件判斷~

>>> download_complete = False>>> bool(download_complete)False>>> bool(-1.2)True>>> bool("")False>>> bool([None])True>>> bool([None, 0])True>>> bool([])False>>>

3.4.2 數字

  • int 帶符號整數 **python只有一種整數類型**
  • float 雙精度浮點數
  • complex 復數
>>> type(3.75)<type 'float'>>>> type(0377)<type 'int'>>>> type(0xE8C6)<type 'int'>>>> type(2+2j)<type 'complex'>

3.4.2.1 數字運算符

  • + - *
  • / floor division 經典除法(整數相除結果取整,浮點相除結果取浮點)
  • // true division 真正的除法 (統統取整數結果)
  • % 取模
  • ** 指數運算
  • & | ~ ^ >> << &= <<=

關于 / //

In [8]: 1/2Out[8]: 0In [9]: 1.0/2Out[9]: 0.5In [10]: 1.0/2.0Out[10]: 0.5In [11]: 1/2.0Out[11]: 0.5In [12]: 1//2Out[12]: 0In [13]: 1.0//2Out[13]: 0.0In [14]: 1.0//2.0Out[14]: 0.0In [15]: 1//2.0Out[15]: 0.0In [16]: type(1//2.0)Out[16]: floatIn [17]: type(1//2)Out[17]: int

3.4.2.2 內置數字工廠函數/類型轉換

>>> int('123')123>>> int(45.67)45>>> round(1.15, 1)1.1>>> float(10)10.0>>> divmod(15, 6)(2, 3)>>> ord('a')97>>> chr(65)'A'>>>

3.4.3 序列和迭代

序列類型類似其他語言中的數組,不同的是:

  1. 數組是定長的,而序列長度可以伸縮
  2. 數組有相似的對象組合,可以包含不同類型的對象

常見的序列有:

  1. 列表 list [1, 2, 3] [123, 'foo', 3.14]
  2. 字符串 string 'python' '/n' '%s is number %d'
  3. 元組 tuple (45, 2.71) () ('need a comma even with just 1 item',)

像數組一樣, 序列可以直接索引:

>>> s = 'Python'>>> s[0]'P'>>> s[4]'o'>>> s[-1]'n'

還可以一次索引多個元素,在這里成為序列切片

>>> s[1:4]'yth'>>> s[3:]'hon'>>> s[3:-1]'ho'>>> s[:]'Python'>>> str(s)'Python'

切片語法適用于所有的序列,包括字符串、元組、列表

其他的序列操作符還有連接, 復制, 檢查是否是成員

>>> 'Python and ' + 'Django are cool''Python and Django are cool'>>> 'Python and ' 'Django are cool''Python and Django are cool'>>> '-'*40'----------------------------------------'>>> 'an' in 'Django'True>>> 'xyz' in 'Django'False
建避免在序列上使用 + 操作符,因為其效率不高
>>> 'foo'+'bar''foobar'#建議使用下面兩種方式>>> '%s%s' % ('foo', 'bar')'foobar'>>> s=''>>> s.join(['foo', 'bar'])'foobar'

3.4.4 列表

>>> book=['python', 'develop', 8]>>> book.append(2008)>>> book.insert(1, 'web')>>> book['python', 'web', 'develop', 8, 2008]>>> book[:3]['python', 'web', 'develop']>>> 'django' in bookFalse>>> book.remove(8)>>> book.pop(-1)2008>>> book['python', 'web', 'develop']>>> book*2['python', 'web', 'develop', 'python', 'web', 'develop']>>> book.extend(['with', 'django'])>>> book['python', 'web', 'develop', 'with', 'django']>>> book.extend([])>>> book.extend(['end'])>>> book['python', 'web', 'develop', 'with', 'django', 'end']>>> book.sort()>>> book['develop', 'django', 'end', 'python', 'web', 'with']

這里注意一點跟string字符串的區別,列表的內置函數如sort, append, insert都是直接對對象進行修改,而沒有返回值;字符串比如用upper方法則是返回了一個字符串。
這是因為字符串是不可改變的,而列表可變
python2.4以上版本提供了sorted和reversed方法可以接受一個列表作為參數并返回一個處理過的拷貝

>>> book=['c','b',4,1,'a',2,3]>>> sbook = sorted(book)>>> sbook[1, 2, 3, 4, 'a', 'b', 'c']

列表推導式[ ] and 生成器表達式( )

>>> data = [x for x in range(10) if x%2 ==0]>>> data[0, 2, 4, 6, 8]>>> data = (x for x in range(100) if x%2 ==0)>>> data<generator object <genexpr> at 0x00DCE710>

如果你的輸入序列很大,最好用生成器表達式,節省內存

3.4.5 字符串

字符串不能修改,大小也不能改變
任何沒有一個能修改現有的對象的方法,只是返回一個修改了的拷貝
到目前為止,已經有超過37個字符串方法

>>> s = 'Django is cool'>>> words = s.split()>>> words['Django', 'is', 'cool']>>> ' '.join(words)'Django is cool'>>> '::'.join(words)'Django::is::cool'>>> s.upper()'DJANGO IS COOL'>>> s'Django is cool'>>> s.upper().isupper()True>>> s.title()'Django Is Cool'>>> s.capitalize()'Django is cool'>>> s.count('o')3>>> s.find('go')4>>> s.find('xxxx')-1>>> s.startswith('Python')False>>> s.startswith('Django')True>>> s.replace('Django', 'Python')'Python is cool'>>>

字符串指示符 u r

>>> mystr = u'This is Unicode'>>> mystru'This is Unicode'>>> print mystrThis is Unicode>>> filename = 'C:/temp/newfolder'>>> filename'C:/temp/newfolder'>>> print filenameC:      empewfolder>>> filename = r'C:/temp/newfolder'>>> print filenameC:/temp/newfolder#為了保持一致,所有的正則表達式都要用raw指示符>>> regex = "/w+@/w+/./w+">>> print regex/w+@/w+/./w+>>> regex = r"/w+@/w+/./w+">>> print regex/w+@/w+/./w+

Unicode指示符

通常Python字符串都只含有很少字符,不足以顯示更多的非英文字符。而Unicode是新型的字符集,擁有大量的編碼方式,不存在這個顯示。

>>> str = "中國">>> str'/xd6/xd0/xb9/xfa'>>> str = u"中國">>> stru'/u4e2d/u56fd'>>> str = r"中國">>> str'/xd6/xd0/xb9/xfa'>>> print str中國>>> str = u"中國">>> print str中國>>> str = "中國">>> print str中國

字符串格式化操作符 adn 三引號操作符

>>> s = 'Django is cool'>>> '%s is number %d' % (s[:6], 1)'Django is number 1'>>> hi = '''hi... there'''>>> hi'hi/nthere'>>> print hihithere

展示一個高級應用的實例

>>> xml = '''... <?xml version="1.0"?>... <request version="%.1f">...    <Data>...        <Payload>%s</Payload>...    </Data>... </request>... '''>>> VERSION = 1.2>>> payload = 'super top-secret info'>>> print (xml %(VERSION, payload))<?xml version="1.0"?><request version="1.2">   <Data>       <Payload>super top-secret info</Payload>   </Data></request>

3.4.6 元組

表明上元組和列表只是用什么括號() []的區別,深層次的區別則要說道Python的對象模型。

列表允許改變值,元組不可以!(像字符串)所以元組沒有方法。

但是元組也不單單是一個只讀列表,元組的主要作用是作為參數傳遞給函數調用,或是從函數調用那里獲取參數時, 保護其內容不被外部接口修改。

所以元組在前臺的用武之地不大,但是在后臺卻很頻繁使用,例如Django的配置文件中的admin選項、URLconf規則、settings.py配置。

!!! 單個元素的元組要求在最后“必須”跟一個逗號,元組是逗號決定的,而不是小括號。

>>> a = ("one", "two")>>> a('one', 'two')>>> type(a)<type 'tuple'>>>> a[0]'one'>>> a = ('just-one')>>> a'just-one'>>> type(a)<type 'str'>>>> c = ('just-one',)>>> c('just-one',)>>> type(c)<type 'tuple'>>>> d = "just-one",>>> d('just-one',)>>> type(d)<type 'tuple'>

內置序列函數和工廠函數

  • str
  • list
  • tuple
  • len
  • max
  • min
  • range(1,10)
  • sorted
  • sum
  • any
  • zip
>>> a=("one","two")>>> type(a)<type 'tuple'>>>> a('one', 'two')>>> len(a)2>>> max(a)'two'>>> sorted(a)['one', 'two']>>> sum(a)Traceback (most recent call last):  File "<stdin>", line 1, in <module>TypeError: unsupported Operand type(s) for +: 'int' and 'str'>>> any(a)True>>> zip(a, a)[('one', 'one'), ('two', 'two')]>>> b=list(a)>>> b['one', 'two']>>> c=str(a)>>> c"('one', 'two')">>> sum(b)Traceback (most recent call last):  File "<stdin>", line 1, in <module>TypeError: unsupported operand type(s) for +: 'int' and 'str'

3.4.7 字典

字典是Python中唯一的映射類型,可變的,無序的,大小可變的鍵值映射;別名散列表(hashes) 關聯數組

雖然語法跟序列相似,但是用而不是下標來訪問元素;而且定義的話使用的花括號{ }

字典的操作、方法和映射函數

  • keys
  • values
  • items
  • get
  • pop
  • update
>>> book = {'title':'Python Web Dev', 'year':2008}>>> book{'year': 2008, 'title': 'Python Web Dev'}>>> type(book)<type 'dict'>>>> 'year' in bookTrue>>> book.get('pub')>>> book.get('pub', 'N/A')'N/A'>>> book['pub']Traceback (most recent call last):  File "<stdin>", line 1, in <module>KeyError: 'pub'>>> book['pub']='Addision Wesley'>>> book['pub']'Addision Wesley'>>> book.get('pub', 'N/A')'Addision Wesley'>>> for key in book:... print key, ':', book[key]  File "<stdin>", line 2    print key, ':', book[key]        ^IndentationError: expected an indented block>>> for key in book:...     print key, ':', book[key]...year : 2008pub : Addision Wesleytitle : Python Web Dev>>> book.setdefault('price', 100.00)100.0>>> book{'price': 100.0, 'year': 2008, 'pub': 'Addision Wesley', 'title': 'Python Web Dev'}>>> del book['price']>>> book{'year': 2008, 'pub': 'Addision Wesley', 'title': 'Python Web Dev'}>>> book['title']='Python Web Dev with Django'>>> book{'year': 2008, 'pub': 'Addision Wesley', 'title': 'Python Web Dev with Django'}>>> len(book)3

Django 中類似字典的數據類型,Request對象和Response對象

總結:列表list和字典dict是應用的最頻繁的數據類型

3.5. Python流程控制

3.5.1 判斷if elif else

data = raw_input("Enter y or n :")if data[0] == 'y':    print "you enter y"elif data[0] == 'n' :    print "you enter n"else    print "invalid"

3.5.2 循環 常用 for

>>> i = 0>>> while i < 5:...     print i...     i += 1...01234

更常用的是for循環,這個for循環更像是shell中的foreach,讓你專注于問題本身而不擔心計數變量。

for line in open('/tmp/some_file.txt')    if 'error' in line:        print line

還記得列表推導式嗎?
data = [x for x in range(10) if x%2 ==0]

當然如果你還是要在循環的同時計數的話,可以使用內置函數enumerate(for循環自身沒辦法計數)

>>> for i, value in data:...     print i...Traceback (most recent call last):  File "<stdin>", line 1, in <module>TypeError: 'int' object is not iterable>>> for i, value in data:...     print value...Traceback (most recent call last):  File "<stdin>", line 1, in <module>TypeError: 'int' object is not iterable>>> for value in data:...     print value...123abc3.14
>>> data = (123, 'abc', 3.14)>>> for i, value in enumerate(data):...     print i, value...0 1231 abc2 3.14>>>

在Django的Model中使用 enumerate

特別是在用到choices參數的地方

STATUS_CHOICES = enumerate(("solid", "liquid"))class IceCream(models.Model):    falvor = models.CharField(max_length = 50)    status = models.ItergerField(choices = STAUTS_CHOICES)

數據庫里, 你的IceCream的status值被保存為整數(0, 1, 2), 但是在Django的admin界面中顯示的確實是文字標簽。

這樣利用數據庫存儲的效率高,而且???當出現字符無法按照預想順序排序的時候也比較方便。

3.6. Python異常處理

Python的try-except語句跟其他語言的try-catch結構相似;

運行時發生異常的話, 解釋器會找相應的處理語句handler;
要是在當前函數沒有找到,會將異常傳遞到上層函數;
如果到最外層全局main還是沒有找到,解釋器會退出,同時打印traceback以便讓用戶找出錯誤。
異常處理可以處理從簡單的單個異常到一系列的多個不同的異常類型。

try:    f = open(filename, 'r')except IOError, e:    return False, str(e)

同一段處理語句也可以處理多個異常類型,只要放在一個元組中即可

try:    process_some_data()except (TypeError, ValueError), e:    print "Error: you provide invalid data", e

或者為多個異常創建多個處理語句:(有點像swithc case break)

try:    process_some_data()except (TypeError, ValueError), e:    print "ERROR: invalid data", eexcept ArithmeticError, e:    print "ERROR: some math error", eexcept Exceptioin, e:    print "ERROR: invalid data", e

finally子句

Python還提供了一個 finally自居,無論錯誤是不是發生,這些代碼都必須運行,比如關閉文件,釋放鎖, 把數據庫連接返回給連接池。

try:    get_mutex()    do_some_stuff()finally:    free_mutex()

自Python2.5之后,try-finally 可以跟 except 一起使用。

try:    get_mutex()    do_some_stuff()except (IndexError, KeyError, AttributeError), e:    log("ERORR:...")finally    free_mutex()

用raise拋出異常

def foo(must_be_positive_int)    if not isinstance(must_be_positive_int)        raise TypeError("ERROR foo(): must pass in an integer")    if must_be_positive_int < 1:        raise ValueError("ERROR foo(): ...")

常見異常類型

  • AssertionError
  • AttributeError
  • IOError
  • ImportError
  • IndentationError
  • IndexError
  • KeyError
  • Keyboardinterrupt
  • NameError
  • SyntaxError
  • TypeError
  • UnboundLocalError
  • ValueError

more refert to : https://docs.python.org/2.7/library/exceptions.html

3.7. 文件

>>> f = open('test.txt', 'w')>>> f.write('foo/n')>>> f.write('bar/n')>>> f.close()>>> dir<built-in function dir>>>> f = open('test.txt', 'r')>>> for line in f:...     print line.rstrip()...foobar>>> f = open('test.txt', 'r')>>> for line in f:...     print line...foobar

除了read 和 write 方法還有 readlines 和 writelines 方法,讓文件跟列表list打交道

>>> f = open('test.txt', 'r')>>> f.read()'foo/nbar/n'>>> f = open('test.txt', 'r')>>> f.readlines()['foo/n', 'bar/n']>>> f = open('test.txt', 'w')>>> f.writelines(['foo', 'bar'])>>> f = open('test.txt', 'r')>>> f.read()'foobar'

3.8. 函數(重點

  • 聲明和調用函數
  • (函數調用里的)關鍵字參數
  • (函數簽名里的)默認參數
  • 函數式first-class的對象
  • 匿名函數和lambda
  • (函數調用里的)參數容器
  • (函數簽名里的)變長參數
  • 裝飾器

3.8.1 聲明和調用函數

>>> def foo(x):...     print x...>>> foo(123)123>>> import httplib>>> def check_web_server(host, port, path):...     h = httplib.HTTPConnection(host, port)...     h.request('GET', path)...     resp = h.getresponse()...     print 'HTTP Response:'...     print '    status = ', resp.status...     print '    reason = ', resp.reason...     print 'HTTP Headers: '...     for hdr in resp.getheaders():...         print '    %s: %s' %hdr...>>> check_web_server('www.python.org', 80, '/')HTTP Response:    status =  301    reason =  Moved PermanentlyHTTP Headers:    content-length: 0    via: 1.1 varnish    x-cache: MISS    accept-ranges: bytes    strict-transport-security: max-age=63072000; includeSubDomains    server: Varnish    retry-after: 0    connection: close    x-served-by: cache-ty67-TYO    x-cache-hits: 0    location: https://www.python.org/    date: Wed, 24 Sep 2014 06:38:42 GMT>>> check_web_server('www.baidu.com', 80, '/')HTTP Response:    status =  200    reason =  OKHTTP Headers:    content-length: 14613    bdqid: 0xa15e849b0000a0cc    set-cookie: BAIDUID=C888FD3659C854691DC8B775D3D3C55E:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com, BDSVRTM=0; path=/    accept-ranges: bytes    vary: Accept-Encoding    bduserid: 0    server: BWS/1.1    last-modified: Wed, 03 Sep 2014 02:48:32 GMT    connection: Keep-Alive    pragma: no-cache    cache-control: no-cache    date: Wed, 24 Sep 2014 06:39:17 GMT    p3p: CP=" OTI DSP COR IVA OUR IND COM "    content-type: text/html    bdpagetype: 1>>>

3.8.2 (函數調用里的)關鍵字參數

調用的時候,我們需要記得函數定義中的參數順序:host, port, path
那如果沒有記得呢,可以用關鍵字參數,也是ok的

>>> check_web_server(path='/', port=80, host='www.baidu.com')

3.8.3 (函數簽名里的)默認參數

定義函數的時候,Python同樣支持默認參數的定義

>>> def check_web_server(host, port=80, path='/')

注意, 所有必須提供 的參數必須出現在可選參數之前,下面就是錯誤的

>>> def check_web_server(path, port=80, host) #INVALID

將列表和字典作為默認參數很危險

因為列表和字典是可變的,當他們持續穿過多個函數調用時

>>> def func(arg=[]):...     arg.append(1)...     print arg...>>> func()[1]>>> func()[1, 1]>>> func()[1, 1, 1]>>> func()[1, 1, 1, 1]

3.8.4 函數是First-Class的對象

對象引用
在Python里面,你可把函數和方法當做和其他對象一樣的使用

只有當我們要調用函數的時候才會加上小括號(), 在把它當做變量或者對象傳來傳去的時候,只需要用函數的名字就好。

這將引用bar和調用bar()區分開來

>>> def bar():...     print "bar"...>>> bar()bar>>> baz = bar>>> baz()bar>>>>>>>>> function_list = [bar, baz]>>> for function in function_list:...     function()...barbar

Django里的First-Class函數

常見的例子是 URLconf 文件中設置 Django View

from django.conf.urls.defaults import *from myproject.myapp.views import listviewurlpatterns = patterns('',    url(r'^list/', listview))

這里的 listview 作為了一個包含了函數對象被直接使用,而不是一個包含了函數名字的字符串

另一個利用函數對象的地方時 model field 里的默認參數。

import datetimeclass DiaryEntry(models.Model):    entry = models.TextField()    date = models.DateField(default = datetime.date.today)

這里的 datetime.date.today后面沒有() , 所以Django會在創建實例的時候才會調用函數而如果加上 (), 那么函數會在model定義的時候就調用,非我所想。

http://m.survivalescaperooms.com/ganiks

3.8.5 匿名函數和lambda

表達式和語句 expression & statement

python 代碼由 表達式和語句構成,并由python解釋器負責自行。

表達式是一個值,他的結果一定是一個python對象

lambda args:表達式

舉個例子,對比下3個不同的處理方式:
這里有一個代表人物的復雜對象列表,希望按照姓氏排序

>>> list_of_people = [{'name':'ganiks', 'last_name':'liu'}, {'name':'henry', 'last_name':'ge'}]>>> list_of_people[{'last_name': 'liu', 'name': 'ganiks'}, {'last_name': 'ge', 'name': 'henry'}]>>> sorted(list_of_people, key = lambda person: person['last_name'])[{'last_name': 'ge', 'name': 'henry'}, {'last_name': 'liu', 'name': 'ganiks'}]
#key期望的是一個函數對象,而lambda返回的正好是一個匿名函數#這個例子簡潔,目的明確sorted(list_of_people, key = lambda person: person.last_name)#這樣也是等價的#這個方便重復使用函數def get_last_name(person):    return person.last_namesorted(list_of_people, key = get_last_name)#不建議使用這種,我們希望lambda是一次性的函數定義#不過,這進一步闡述了Python函數的First-Class的特性get_last_name = lambda person: person.last_namesorted(list_of_people, key = get_last_name)

Django里面的匿名lambda函數

Django里面用到匿名函數的地方不多,但有個地方非常合適,即“認證裝飾器” authentication decorator,確認用戶是否有足夠權限訪問頁面;

將一個代表已登錄用戶的User對象傳遞給一個函數

@user_passes_test(lambda u: u.is_allowed_to_vote)def vote(request):    """ Process a user's vote"""

這個例子中調用了一個函數user_passes_test,接受了參數lambda u:u.is_allowed_to_vote之后返回 另一個“裝飾器”;也就是說裝飾器是 user_passes_test(lambda u:u.is_allowed_to_vote)

*args && **kwargs

無論是函數調用或者聲明, *都代表元組(或者列表)出現, **代表字典出現。

3.8.6 (函數調用里的)參數容器

函數調用里的 * ** 讓參數容器列表、元組、字典更優雅

def check_web_server(host, port, path)

check_web_server('localhost', 8000, '/damin/')

host_info = ('www.python.org', 80, '/')

checck_web_server(host_info[0], host_info[1], host_info[2])

*讓代碼干凈和優雅
check_web_server(*host_info)

host_info = {'host': 'www.python.org', 'port': 80, 'path': '/'}

check_web_server(**host_info)

3.8.7 (函數簽名里的)變長參數

函數簽名里的 * ** 支持邊長參數 varargs

在函數定義里使用變長參數時,參數的順序是要求的;先是必須出現的參數,然后是由默認值的參數,最后才是變長參數

def check_web_server(host, port, path, *args, **args)

這個函數必須至少接受初始的三個參數,但是也能接受隨后任何數目的參數或是關鍵字參數

還有一種全部由變長參數組成的所謂通用的Python方法簽名

def f(*args, **kwargs):#正確調用f()f(a, b, c)f(a, b, foo=c, bar=d)

Django QuerySets里的 **kwargs: 動態創建ORM查詢

Django數據庫API查詢經常包含關鍵字參數,比如:

bob_stories = Story.objects.filter(	title_contains = "bob",	subtitle_contains = "bob", 	text_contains = "bob",	byline_contains = "bob")#用變長參數字典來讓參數獨立bobargs = {	'title_contains': "bob",	'subtitle_contains': "bob", 	'text_contains': "bob",	'byline_contain': "bob"}bob_stories = Story.objects.filter(**bobargs)#動態創建字典bobargs = dict((f + '__contains', 'bob') for f in ('title', 'subtitle', 'text', 'byline'))bob_stories = Story.objects.filter(**bobargs)

3.8.8 裝飾器

裝飾器是一種讓你能改變或者說“裝飾” 函數行為的機制,能讓函數執行一些和原本設計不同,或是在原有基礎上額外的操作。

裝飾器也可以說是對函數的一個包裝,這些額外的任務包括寫日志、計時、過濾

python 里的一個被包裹或者被裝飾的函數(對象)通常會被重新賦值給原來的名字

@decodef foo():    pass

等價于

foo = deco(foo)

再舉個例子記錄下函數調用的發生:

>>> def log(func):...     def wrappedFunc():...          print "**** %s() called" % func.__name__...          return func()...     return wrappedFunc...>>> @log... def foo():...     print "inside foo()"...>>> foo()**** foo() calledinside foo()

再看看之前的一個例子
將一個代表已登錄用戶的User對象傳遞給一個函數

@user_passes_test(lambda u: u.is_allowed_to_vote)def vote(request):    """ Process a user's vote"""

這個例子中調用了一個函數user_passes_test,接受了參數lambda u:u.is_allowed_to_vote之后返回 另一個“裝飾器”;也就是說裝飾器是 user_passes_test(lambda u:u.is_allowed_to_vote)

它的邏輯是這樣的:

@decomaker(deco_args)def foo():    pass

等價于

foo = decomaker(deco_args)(foo)

再比如應用多個裝飾器:

@deco1(deco_args@)@deco2def foo():    pass

為什么要用裝飾器呢?
本質就是包裹函數,接受對象,修改并重新賦值給原來的變量;

3.9. 面向對象編程

OOP的主要目標是在代碼和顯示問題之間提供一個合乎邏輯的映射關系,并且鼓勵代碼的重用和共享。

3.9.1 類的定義

class AddressBookEntry(object):	version = 0.1	def __init__(self, name, phone):		self.name = name		self.phone = phone	def update_phone(self, phone):	   self.phone = phone
  • version這樣的靜態成員屬于整個類的變了,可以再所有的實例之間共享
  • 方法的定義和函數的一點區別,每個方法都必須帶上一個額外的self對象
  • python沒有構造函數和析構函數,也沒有 new free關鍵字

3.9.3 實例化

john = AddressBookEntry('Jone Doe', '400999999')jane = AddressBookEntry('Jane Dey', '300293202')>>> john.phone'400999999'>>> john.tattoo = 'Mom'

python中實例化不需要像其他語言一樣new對象,而是可以直接調用函數一樣即可

python用的是初始化程序initializer而不是構造函數 constructor,所以名字也是
__init__

在實例化一個對象的時候,不用傳入self對象,python會自動為你傳入self對象

PS: python還支持直接創造沒有在類定義中聲明的對象,比如上面例子中的tattoo

3.9.3 繼承

class EmployeeAddressBookEntry(AddressBookEntry):	def __init(self, name, phone, id, social): 		AddressBookEntry.__init__(self, name, phone)		self.empid = id		self.ssn = social

3.9.4 嵌套類

嵌套類的概念類似于創建裝飾器的“嵌套函數”,即在類的內部定義類

class MyClass(object):	class InnerClass:		pass

Django中的嵌套類應用實例--Django Model

form django.db import modelsfrom django.contrib import adminclass BlogPost(models.Model):	title = models.CharField(max_length = 150)	body = models.TextField()	timestamp = models.DateTimeField()class Meta:	ordering = ('-timestamp',)

Django的數據model是從Django內置類 django.db.models.Model 繼承而來的子類

3.10. 正則表達式

re.search 返回一個匹配對象Match,隨后可以用這個對象的 group 或者 groups
方法獲取匹配的模式;匹配失敗時,返回的是None

額,這里用“匹配”有點不準確,確切的說是“搜索”,而“匹配”指的是整個字符串都要符合模式的描述

>>> import re>>> m = re.search(r'foo', 'seafood')>>> print m<_sre.SRE_Match object at 0x00DAE4B8>>>> m.group<built-in method group of _sre.SRE_Match object at 0x00DAE4B8>>>> m.group()'foo'>>> m = re.search(r'bar', 'seafood')>>> print mNone>>>>>>>>> import re>>> m = re.match(r'foo', 'seafood')>>> if m is not None: print m.group()...>>> print mNone>>> if m is not None: print m.groups()...>>> print mNone>>> m = re.search(r'foo', 'seafood')>>> if m is not None: print m.group()...foo>>> if m is not None: print m.groups()...()>>> if m is not None: print m.group()...foo

3.11. 常見錯誤

3.11.1 單元素的元組

  • ()
  • (123, 'xyz', 3.14)
  • (1)
  • (1,)

3.11.2 模塊

import randomprint random.choice(range(10))from random import choiceprint choice(range(10))
  • 第一種方法將模塊的名字設置為一個隱含的名字空間里的全局變量,這樣可以像訪問全局屬性一樣訪問choice函數
  • 第二種方法直接把choice引入到全局名字控件,因此不再需要把這個屬性當成是模塊的成員,實際上我們也只擁有這個屬性而已
  • 但是并不是說,第二種方式只引入了一個函數,而沒有導入整個模塊,其實是導入了整個模塊的!!!所以沒有性能的差異

3.11.3 能否重復導入模塊??

python有導入模塊和加載模塊之分,一個模塊可以被導入N次,但是只會被加載一次,無需擔心額外消耗內存的問題。

3.11.4 Package

package是Python在文件系統上發布一組模塊的一種方式,通過 __init__.py 實現

Phone/	__init__.py	util.py	Voicedata/		__init__.py		posts.py		Isdn.py	Fax		__init__.py		G3.py	Mobile		__init__.py		Anolog.py		Digital.py

__init.__.py告訴Python解釋器這些目錄下的文件應該被當做是一個子package而不是普通文件,一般它們都是空文件,當然也可以做一些初始化的工作。

import Phone.Mobile.AnalogPhone.Mobile.Anolog.dial()import Phone.Mobile.Analog as pmapma.dial()

3.11.5 可改變性,到底Python是傳引用 還是 傳值?

在Python中跟一般不這么說,而是說 對象時可變或者不可變 mutable or immutable

對象有 類型,標示符,值 三個屬性, 如果值 是可變的,那么這個對象就是可變的;

前面語法其實已經介紹過了,標量scalar類型(整數浮點數復數)、str、unicode字符串、元組是不可變的;其他的列表、字典、類、類實例都是可變的。

可變性是Python中重要的概念,這也解釋了為什么Python要提供兩種列表, list 和 tuple

可改變性如何影響方法調用

如果你調用的函數有任何修改一個可變對象的行為的話,通常它都是直接修改的,即直接修改數據結構而不是返回一個拷貝(返回None)

比如 list.sort, list.reverse, list.extend, dict.update都是直接修改

復制對象和可改變性

深拷貝和淺拷貝 deep copy & shallow copy

>>> from copy import deepcopy>>> mylist2 = deepcopy(mylist)>>> mylist2[1, 'a', ['foo', 'bar']]>>> mylist2[0] = 2>>> mylist2[2][0] = 'biz'>>> mylist2[2, 'a', ['biz', 'bar']]>>> mylist[1, 'a', ['foo', 'bar']]>>> mylist2 = list(mylist)>>> mylist2[0] = 2>>> mylist2[2][0] = 'biz'>>> mylist[1, 'a', ['biz', 'bar']]>>> mylist2[2, 'a', ['biz', 'bar']]

上面的例子中分別是一個深拷貝和淺拷貝的例子,先看看淺拷貝:

mylist中前兩個對象時整數和字符串,所以mylist2會得到2個全新的整數和字符串對象,所以1=>2
但是mylist的第三個對象時列表,列表時可變的,所以mylist2得到的只是一個引用,所以
‘foo'=>'biz'影響到了mylist本身

而深拷貝就不會了, 1=>2 'foo'=>'biz' 都不會影響mylist

深拷貝通常是地柜的(如果循環引用會有問題),而且不是所有的對象都是可以深拷貝的。

3.11.6 構造函數 vs 初始化程序

雖然Python是OOP的語言,但是沒有顯式的構造函數的概念,沒有 new 關鍵字,沒有
真的實例化你的類。

python會為你創建實例并調用初始化程序,在你的對象創造出來之后,Python將它返回給你之前調用的第一個方法__init__

>>> from time import ctime>>> class MyClass(object):...     def __init__(self, date):...         print "instance created at: ", date...>>> m = MyClass(ctime())instance created at:  Sat Sep 27 10:31:22 2014>>>

另外python也沒有析構函數來銷毀對象,只要讓它離開作用域就行了,會被自動垃圾回收。

不過,你可以在 python對象中定義一個 __del__方法來當做析構函數,可以用 del my_object來顯式的銷毀對象。

動態實例屬性

Python的另一個重要的特性是動態實例屬性 dynamic instance attribute

實例的屬性可以動態分配,
即使在類定義已經完成甚至是已經創建里實例,還是可以給你的實例添加一個之前沒有提到過的屬性

3.12. 代碼風格

  • 四格對齊
  • 使用空格而非Tab
  • 不要像標題一樣把一組代碼放在同一行里
  • 創建文檔字符串(docstring)

    C:/Documents and Settings/ganiks.liu/Desktop>vim foo.py"""foo.py --sample module demostrating documentation strings """class Foo(object):	""" Foo() - empty class ... tobe developed """def bar(x):	"""bar(x) - function docstring for bart, prints out its arg 'x'"""	print xC:/Documents and Settings/ganiks.liu/Desktop>pythonPython 2.7.5 (default, May 15 2013, 22:43:36) [MSC v.1500 32 bit (Intel)] on win32Type "help", "copyright", "credits" or "license" for more information.>>> import foo>>> foo.__doc__'foo.py --sample module demostrating documentation strings '>>> foo.Foo.__doc__' Foo() - empty class ... tobe developed '>>> foo.bar.__doc__"bar(x) - function docstring for bart, prints out its arg 'x'">>> help(foo)Help on module foo:NAME    foo - foo.py --sample module demostrating documentation stringsFILE    c:/documents and settings/ganiks.liu/desktop/foo.pyCLASSES    __builtin__.object        Foo    class Foo(__builtin__.object)     |  Foo() - empty class ... tobe developed     |     |  Data descriptors defined here:     |     |  __dict__     |      dictionary for instance variables (if defined)     |     |  __weakref__     |      list of weak references to the object (if defined)FUNCTIONS    bar(x)        bar(x) - function docstring for bart, prints out its arg 'x'

3.13. 總結


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 佛冈县| 山西省| 涟水县| 班戈县| 南木林县| 崇州市| 原阳县| 乌鲁木齐市| 南京市| 吉首市| 托克逊县| 湘阴县| 伊吾县| 吴桥县| 新巴尔虎左旗| 临泽县| 华宁县| 靖远县| 大悟县| 沿河| 南涧| 泽州县| 历史| 灵山县| 利辛县| 新竹市| 新巴尔虎左旗| 青海省| 湖北省| 伽师县| 南澳县| 渝北区| 南昌市| 青河县| 肇州县| 四平市| 灵丘县| 获嘉县| 台东市| 乐安县| 高雄县|