日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

Python-技巧

發(fā)布時間:2023/12/4 python 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python-技巧 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

0.推薦的擴(kuò)展

  requests urilib的替代品

  BeautifulSoup4 解析HTML代碼

  rq 任務(wù)隊列

  selenium 自動化測試工具,模擬瀏覽器

1.sys.modules, 根據(jù)已加載的模塊創(chuàng)建對象, 其中 page 為類名

if hasattr(sys.modules[__name__], page):setattr(self, page, getattr(sys.modules[__name__], page)(self))

2.hasattr, setattr, locals(), globals() 動態(tài)創(chuàng)建變量

3.綁定、未綁定

  未綁定的類方法: 沒有self

    通過類來引用方法返回一個未綁定方法對象, 要調(diào)用它, 你必須顯示地提供一個實例作為第一個參數(shù)

  綁定的實例方法: 有self

    通過實例訪問方法返回一個綁定的方法對象, Python自動地給方法綁定一個實例, 所以我們調(diào)用它時不用再傳一個實例參數(shù)

class Test:def func(self,message):print messageobject1 = Test() x = object1.func x('綁定方法對象,實例是隱含的')t=Test.func t(object1,'未綁定的方法對象,需要傳遞一個實例') #t('未綁定的方法對象,需要傳遞一個實例') #錯誤的調(diào)用

  object1 = Test()生成一個實例, object1.func返回一個綁定的方法, 把實例object1和方法func綁定, 而Test.func是用類去引用方法, 我們得到一個未綁定的方法對象, 要調(diào)用它就得傳一個實例參數(shù), 如t(object1,'未綁定的方法對象,需要傳遞一個實例')

class A(object): def f(self): print "f"def ff(): print "ff" a = A() a.f() xf = a.f #xf為綁定的方法, 故不用傳入第一個值 xf() a.f = ff a.f()

4.MRO(method resolution order, 多繼承時判斷調(diào)的屬性的類)

  MRO要先確定一個線性序列, 然后查找路徑由由序列中類的順序決定, 所以MRO的算法就是生成一個線性序列

  Python先后有三種不同的MRO: 經(jīng)典方式、Python2.2 新式算法、Python2.3 新式算法(C3), Python 3中只保留了最后一種, 即C3算法

  經(jīng)典方式: 非常簡單, 深度優(yōu)先, 按定義從左到右

  新式算法: 還是經(jīng)典方式, 但出現(xiàn)重復(fù)的, 只保留最后一個

  C3算法: 最早被提出是用于Lisp的, 應(yīng)用在Python中是為了解決原來基于深度優(yōu)先搜索算法不滿足本地優(yōu)先級, 和單調(diào)性的問題:

    本地優(yōu)先級: 指聲明時父類的順序, 比如C(A, B), 如果訪問C類對象屬性時, 應(yīng)該根據(jù)聲明順序, 優(yōu)先查找A類, 然后再查找B類

    單調(diào)性: 如果在C的解析順序中, A排在B的前面, 那么在C的所有子類里, 也必須滿足這個順序

    class B(A) 這時B的mro序列為[B,A]

    class B(A1,A2,A3 ...)?這時B的mro序列 mro(B) = [B] + merge(mro(A1), mro(A2), mro(A3) ..., [A1,A2,A3])

    merge操作就是C3算法的核心, 遍歷執(zhí)行merge操作的序列, 如果一個序列的第一個元素, 是其他序列中的第一個元素, 或不在其他序列出現(xiàn), 則從所有執(zhí)行merge操作序列中刪除這個元素, 合并到當(dāng)前的mro中, merge操作后的序列, 繼續(xù)執(zhí)行merge操作, 直到merge操作的序列為空, 如果merge操作的序列無法為空, 則說明不合法

class a:pass class b(a):pass class c(a):pass class d(b, c):pass

  比如此菱形繼承結(jié)構(gòu)

    按經(jīng)典方式, d類MRO為dbaca, 缺點是如果c類重寫了a類中得方法, c類的方法將不會被調(diào)用到(即本地優(yōu)先順序問題)

    按新式算法, d類MRO為dbca, 缺點是單調(diào)性,?比如d繼承b、c, 且b在c的前面, 如果f繼承d, 那么f的MRO中也應(yīng)該和d的一樣b在c的前面, 單調(diào)性即繼承時要保持順序, 現(xiàn)在e繼承c、b, 且c在b的前面, f繼承d, e時, bc的順序就沒法決定了, 無論怎樣排都違反了單調(diào)性

class A(O):pass class B(O):pass class C(O):pass class E(A,B):pass class F(B,C):pass class G(E,F):pass

    按C3算法,?A、B、C都繼承至一個基類, 所以mro序列依次為[A,O]、[B,O]、[C,O]
      mro(E) = [E] + merge(mro(A), mro(B), [A,B])
??????         = [E] + merge([A,O], [B,O], [A,B])
      此時需要執(zhí)行merge操作的序列為[A,O]、[B,O]、[A,B]
      A是序列[A,O]中的第一個元素, 在序列[B,O]中不出現(xiàn), 在序列[A,B]中也是第一個元素, 所以從執(zhí)行merge操作的序列([A,O]、[B,O]、[A,B])中刪除A, 合并到當(dāng)前mro, [E]中
        mro(E) = [E,A] + merge([O], [B,O], [B])
      再執(zhí)行merge操作, O是序列[O]中的第一個元素, 但O在序列[B,O]中出現(xiàn)并且不是其中第一個元素, 繼續(xù)查看[B,O]的第一個元素B, B滿足條件, 所以從執(zhí)行merge操作的序列中刪除B, 合并到[E, A]中
        mro(E) = [E,A,B] + merge([O], [O])
??????           = [E,A,B,O]

  實現(xiàn)C3算法的代碼:

#-*- encoding:GBK -*-# def mro_C3(*cls): if len(cls)==1: if not cls[0].__bases__: return cls else: return cls+ mro_C3(*cls[0].__bases__) else: seqs = [list(mro_C3(C)) for C in cls ] +[list(cls)] res = [] while True: non_empty = list(filter(None, seqs)) if not non_empty: return tuple(res) for seq in non_empty: candidate = seq[0] not_head = [s for s in non_empty if candidate in s[1:]] if not_head: candidate = None else: break if not candidate: raise TypeError("inconsistent hierarchy, no C3 MRO is possible") res.append(candidate) for seq in non_empty: if seq[0] == candidate: del seq[0]

  查看一個類的MRO列表, 可以使用 classname.__mro__

5.super 避免多次調(diào)用基類

# -*- coding:utf-8 -*- class D(object): def foo(self): print "class D" class B(D): pass class C(D): def foo(self): print "class C" class A(B, C): pass f = A() f.foo() #A的實例對象f在調(diào)用foo函數(shù)的時候, 根據(jù)廣度優(yōu)先搜索原則, 調(diào)用的是C類里面的foo函數(shù), 上面的代碼輸出class C; 如果定義D類的時候直接class D, 而不是class D(object), 那么上述代碼就該輸出class D了

  1). super并不是一個函數(shù), 是一個類名, 形如super(B, self)事實上調(diào)用了super類的初始化函數(shù)產(chǎn)生了一個super對象;

  2). super類的初始化函數(shù)并沒有做什么特殊的操作, 只是簡單記錄了類類型和具體實例;

  3). super(B, self).func的調(diào)用并不是用于調(diào)用當(dāng)前類的父類的func函數(shù);

  4). Python的多繼承類是通過mro的方式來保證各個父類的函數(shù)被逐一調(diào)用, 而且保證每個父類函數(shù)只調(diào)用一次(如果每個類都使用super);

  5). 混用super類和非綁定的函數(shù)是一個危險行為, 這可能導(dǎo)致應(yīng)該調(diào)用的父類函數(shù)沒有調(diào)用或者一個父類函數(shù)被調(diào)用多次

  6).super并不是像我們想象中一樣直接找到當(dāng)前類的父類, 而是沿著mro順藤摸瓜

  參考:http://blog.csdn.net/johnsonguo/article/details/585193

6.模塊即模塊對象

7.利用 __new__ 實現(xiàn)單例

class Singleton(object):def __new__(cls, *args, **kwargs):# 關(guān)鍵在于這,每一次實例化的時候,我們都只會返回這同一個instance對象if not hasattr(cls, "instance"):cls.instance = super(Singleton, cls).__new__(cls, *args, **kwargs)return cls.instance

8.__new__ 執(zhí)行順序

class A(object):def __new__(cls):Object = super(A, cls).__new__(cls)print "in New"return Object #如果把此行注釋掉, 則不會執(zhí)行 __init__ 方法def __init__(self):print "in init"class B(A):def __init__(self):print "in B's init"B()

9.判斷一個變量是否存在

  1).

'var' in locals().keys()

  2).

try:print var except NameError:print 'var not defined'

  3).

'var' in dir()

10.根據(jù)類名創(chuàng)建實例, 主要是獲得類的 class 對象

  1).類名cls為class類型, 直接 cls() 即可

  2).類名cls為str類型

m = __import__(clsstr所在模塊名) cls = getattr(m, clsstr) cls()

  如果myclass并不在mymodule的自動導(dǎo)出列表中(__all__), 則必須顯式地導(dǎo)入, __import__('mymodule', globals(), locals(), ['myclass'])

11.獲取當(dāng)前模塊名

  locals()/globals().get("__name__")

12.import, reload, __import__

  del sys.modules[modulename] 即可實現(xiàn) unimport

  import 調(diào)用的 __import__, 比如 import sys => sys = __import__("sys")

  reload 對已經(jīng)加載的模塊進(jìn)行重新加載, 一般用于原模塊有變化等特殊情況, reload前該模塊必須已經(jīng)import過, 但原來已經(jīng)使用的實例還是會使用舊的模塊, 新生產(chǎn)的實例會使用新的模塊

import sys #引用sys模塊進(jìn)來,并不是進(jìn)行sys的第一次加載 reload(sys) #重新加載sys sys.setdefaultencoding('utf8') ##調(diào)用setdefaultencoding函數(shù) #如果去掉reload(sys), 會執(zhí)行失敗, 因為這里的import語句其實并不是sys的第一次導(dǎo)入語句, 也就是說這里其實可能是第二、三次進(jìn)行sys模塊的import, 這里只是一個對sys的引用, 只能reload才能進(jìn)行重新加載; 那么為什么要重新加載, 而直接引用過來則不能調(diào)用該函數(shù)呢?因為setdefaultencoding函數(shù)在被系統(tǒng)調(diào)用后被刪除了, 所以通過import引用進(jìn)來時其實已經(jīng)沒有了, 所以必須reload一次sys模塊, 這樣setdefaultencoding才會為可用, 才能在代碼里修改解釋器當(dāng)前的字符編碼

  __import__, 返回模塊實例

__import__(module_name[, globals[, locals[, fromlist]]]) #可選參數(shù)默認(rèn)為globals(),locals(),[] __import__('os') __import__('os',globals(),locals(),['path','pip']) #等價于from os import path, pip

13.迭代器

  基本原理:

    實現(xiàn)了__iter__方法的對象是可迭代的, 實現(xiàn)了next()方法的對象是迭代器(迭代器就是一個有next()方法的對象), 所以iter(實現(xiàn)了__iter__方法的對象)會調(diào)用此對象的__iter__方法, 返回一個實現(xiàn)了next()方法的迭代器對象, 不斷調(diào)用此迭代器對象的next()方法, 實現(xiàn)遍歷,?直到遇到StopIteration異常, 使用迭代器一個顯而易見的好處就是每次只從對象中讀取一條數(shù)據(jù), 不會造成內(nèi)存的過大開銷

  序列、字典、文件中當(dāng)使用for x in y的結(jié)構(gòu)時, 其實質(zhì)就是迭代器, 迭代器是和實際對象綁定在一起的, 所以在使用迭代器時或者上述3者時不能修改可變對象的值, 這會產(chǎn)生錯誤

  迭代器不要求你事先準(zhǔn)備好整個迭代過程中所有的元素, 迭代器僅僅在迭代至某個元素時才計算該元素, 而在這之前或之后, 元素可以不存在或者被銷毀, 這個特點使得它特別適合用于遍歷一些巨大的或是無限的集合, 比如幾個G的文件, 或是斐波那契數(shù)列等等, 這個特點被稱為延遲計算或惰性求值(Lazy evaluation)

  創(chuàng)建迭代器的方法: iter(object)和iter(func, sentinel)兩種, 一種使用的是序列, 另一種使用類來創(chuàng)建, 迭代器更大的功勞是提供了一個統(tǒng)一的訪問集合的接口, 只要是實現(xiàn)了__iter__()方法的對象, 就可以使用迭代器進(jìn)行訪問,?返回一個對象, 這個對象擁有一個next()方法, 這個方法能在恰當(dāng)?shù)臅r候拋出StopIteration異常即可

for i in seq: do_something_to(i)

  實際為:

fetch = iter(seq) while True: try: i = fetch.next() except StopIteration: break do_something_to(i)

  字典中, iterkeys(), itervalues(), iteritems() 比 keys(), values(), items() 更省內(nèi)存

  open("test.txt").readlines() 返回的是列表,?open("test.txt") 返回的是迭代器

14.生成器

  如果一個函數(shù)返回的列表非常大, 僅僅創(chuàng)建這個列表就會用完系統(tǒng)所有內(nèi)存, 因為在我們的觀念中函數(shù)只有一次返回結(jié)果的機會, 因而必須一次返回所有的結(jié)果, 此類問題可以用生成器解決

  生成器是特定的函數(shù), 允許你返回一個值, 然后“暫停”代碼的執(zhí)行, 稍后恢復(fù), 生成器使用了“延遲計算”, 所以在內(nèi)存上面更加有效, 生成器函數(shù)不能有返回值, 因為 yield 的值就是返回值, 生成器就是一類特殊的迭代器

  1).調(diào)用生成器函數(shù)將返回一個生成器

>>> generator = get_0_1_2() >>> generator <generator object get_0_1_2 at 0x00B1C7D8>

  2).第一次調(diào)用生成器的next方法時, 生成器才開始執(zhí)行生成器函數(shù)(而不是構(gòu)建生成器時), 直到遇到y(tǒng)ield時暫停執(zhí)行(掛起), 并且yield的參數(shù)將作為此次next方法的返回值

>>> generator.next() 0

  3).之后每次調(diào)用生成器的next方法, 生成器將從上次暫停執(zhí)行的位置恢復(fù)執(zhí)行生成器函數(shù), 直到再次遇到y(tǒng)ield時暫停, 并且同樣的, yield的參數(shù)將作為next方法的返回值

>>> generator.next() 1 >>> generator.next() 2

  4).如果當(dāng)調(diào)用next方法時生成器函數(shù)結(jié)束(遇到空的return語句或是到達(dá)函數(shù)體末尾), 則這次next方法的調(diào)用將拋出StopIteration異常(即for循環(huán)的終止條件)

>>> generator.next() Traceback (most recent call last):File "<stdin>", line 1, in <module> StopIteration

  5).生成器函數(shù)在每次暫停執(zhí)行時, 函數(shù)體內(nèi)的所有變量都將被封存(freeze)在生成器中, 并將在恢復(fù)執(zhí)行時還原, 并且類似于閉包, 即使是同一個生成器函數(shù)返回的生成器, 封存的變量也是互相獨立的, 我們的小例子中并沒有用到變量, 所以這里另外定義一個生成器來展示這個特點

>>> def fibonacci(): ... a = b = 1 ... yield a ... yield b ... while True: ... a, b = b, a+b ... yield b ... >>> for num in fibonacci(): ... if num > 100: break ... print num, ... 1 1 2 3 5 8 13 21 34 55 89

  看到while True可別太吃驚, 因為生成器可以掛起, 所以是延遲計算的, 無限循環(huán)并沒有關(guān)系, 這個例子中我們定義了一個生成器用于獲取斐波那契數(shù)列

  如果生成器函數(shù)調(diào)用了return, 或者執(zhí)行到函數(shù)的末尾, 會出現(xiàn)一個StopIteration異常

  有一篇好文章:點擊進(jìn)入

15.列表解析器

  也可以直接生成 dict

{x: 1 for x in ["name", "sex"]} #返回 {"name": 1, "sex" 1}

  列表解析一次生成一個列表, 所占內(nèi)存較大

(x+1 for x in lst) #生成器表達(dá)式,返回迭代器。外部的括號可在用于參數(shù)時省略。 [x+1 for x in lst] #列表解析,返回list

  由于返回迭代器時, 并不是在一開始就計算所有的元素, 這樣能得到更多的靈活性并且可以避開很多不必要的計算, 所以除非你明確希望返回列表, 否則應(yīng)該始終使用生成器表達(dá)式

  可以在Python Shell中試一下一下兩個語句的執(zhí)行時間

(for x in range(1000000)) #返回生成器 [for x in range(1000000)] #返回整個列表

  或者提供多條for子句進(jìn)行嵌套循環(huán), 嵌套次序就是for子句的順序:

((x, y) for x in range(3) for y in range(x))

  同樣外部也可以使用 if

(x for x in (y.doSomething() for y in lst) if x>0)

16.在Python里, 函數(shù)的默認(rèn)值實在函數(shù)定義的時候?qū)嵗?/span>, 而不是在調(diào)用的時候, 如果在調(diào)用函數(shù)的時候重寫了默認(rèn)值, 那么這個存儲的值就不會被使用, 當(dāng)你不重寫默認(rèn)值的時候, 那么Python就會讓默認(rèn)值引用存儲的值(這個例子里的numbers)

def abc(numbers = []):numbers.append(9)print numbers

  abc(): [9] #第一次執(zhí)行

  abc(): [9, 9] #第二次執(zhí)行

  abc([1, 2]): [1, 2, 9] #第三次執(zhí)行

  abc(): [9, 9, 9] #第四次執(zhí)行

def print_now(now = time.time()):print now #如果不加參數(shù), 則每次都會返回相同的時間

  默認(rèn)參數(shù)最好指向不變對象

17.當(dāng)def這個聲明執(zhí)行的時候, Python會靜態(tài)地從函數(shù)的局部作用域里獲取信息,?當(dāng)來到 xxx = yyy 這行的時候(不是執(zhí)行到這行代碼, 而是當(dāng)Python解釋器讀到這行代碼的時候), 它會把xxx這個變量加入到函數(shù)的局部變量列表里

18.__builtin__模塊, 在Python啟動后、且沒有執(zhí)行程序員所寫的任何代碼前, Python會首先加載該內(nèi)建模塊到內(nèi)存, 另外, 該內(nèi)建模塊中的功能可以直接使用, 不用在其前添加內(nèi)建模塊前綴, 導(dǎo)入僅僅是讓__builitin__標(biāo)識符在該作用域內(nèi)可見

19.from __future__ import xxx, 必須是模塊或程序的第一個語句, 此外,'__ future__' 模塊中存在的特性最終將成為Python語言標(biāo)準(zhǔn)的一部分, 到那時, 將不再需要使用 '__future__' 模塊

20.序列解包

a, b, c = 1, 2, 3 #賦值 a, b = b, a #轉(zhuǎn)換a, b的值 a = 1, #聲明元組

21.最好了解下二進(jìn)制文件和文本文件的區(qū)別以及編碼問題, ASCII(固定一個字節(jié))->Unicode(固定兩個字節(jié))->UTF-8(變長), 在計算機內(nèi)存中, 統(tǒng)一使用Unicode編碼, 當(dāng)需要保存到硬盤或者需要傳輸?shù)臅r候, 就轉(zhuǎn)換為UTF-8編碼, 用記事本編輯的時候, 從文件讀取的UTF-8字符被轉(zhuǎn)換為Unicode字符到內(nèi)存里, 編輯完成后, 保存的時候再把Unicode轉(zhuǎn)換為UTF-8保存到文件, len()函數(shù)計算的是str(Unicode編碼)的字符數(shù), 如果換成bytes(UTF-8等編碼), len()函數(shù)就計算字節(jié)數(shù):

參考自:廖雪峰Python

22.dict的key必須是不可變對象

23.Python函數(shù)參數(shù)順序

  定義: (arg, kwarg = <value>, *args, **kwargs)

  調(diào)用:

    第一, 按順序把"arg"這種形式的實參給對應(yīng)的形參
    第二, 把"arg=<value>"這種形式的實參賦值給形式kwarg
    第三, 把多出來的"arg"這種形式的實參組成一個tuple給帶一個星號的形參args
    第四, 把多出來的"key=value"這種形式的實參轉(zhuǎn)為一個dictionary給帶兩個星號的形參kwargs

def test(x, y = 5, *a, **b):print x, y, a, b   test(1) ===> 1 5 () {}
  test(1,2) ===> 1 2 () {}
  test(1,2,3)? ===> 1 2 (3,) {}
  test(1,2,3,4) ===> 1 2 (3,4)
  test(x=1)?? ===> 1 5 () {}
  test(x=1,y=1)? ===> 1 1 () {}
  test(x=1,y=1,a=1)?? ===> 1 1 () {'a':1}
  test(x=1,y=1,a=1,b=1)?? ===> 1 1 () {'a':1,'b':1}
  test(1,y=1) ===> 1 1 () {}
  test(1,2,y=1) ===> 出錯, 說y給賦了多個值
  test(1, y = 2, 3, a = 4) ===> 出錯, non-keyword arg after keyword arg
  test(1,2,3,4,a=1) ===> 1 2 (3,4) {'a':1}

24.限制 **kwargs 參數(shù)個數(shù)

#只接收city和job作為關(guān)鍵字參數(shù) def person(name, age, *, city, job):print(name, age, city, job)

25.functools 模塊

  wraps: 用來裝飾返回func的函數(shù), 以同步func與被裝飾的函數(shù)的屬性, 比如__name__等 @functools.wraps(func)

  partial: 變化函數(shù)的參數(shù)創(chuàng)建偏函數(shù), 固定住原函數(shù)的部分參數(shù), 比如 int2 = functools.partial(x, base = 2), 此時 int2 是一個把二進(jìn)制字符串轉(zhuǎn)為十進(jìn)制數(shù)字的函數(shù), int2('10010')

26.一個.py文件稱為一個模塊, 為了避免模塊名沖突, Python按目錄來組織模塊的方法, 稱為包(Package), 包內(nèi)必須有__init__.py, 因為__init__.py本身就是一個模塊, 它的模塊名就是包名(目錄名)

27.第三方庫都會在 Python 官方的 pypi.python.org 網(wǎng)站注冊, 要安裝一個第三方庫, 必須先知道該庫的名稱, 可以在官網(wǎng)或者 pypi 上搜索

28.各種包管理工具區(qū)別:

  distribute是setuptools的取代, pip是easy_install的取代

  distribute被創(chuàng)建是因為setuptools包不再維護(hù)了

29.Python的實例屬性必須在__init__(self) 方法中定義, 直接跟在類名后邊定義的屬性都默認(rèn)是類屬性(類似于c++的static變量), 類的屬性一改, 只要沒有覆蓋此屬性的對象的此屬性都會改

  main.py

#-*- coding: utf-8 -*-class Model():model_path = "online_model"model_dict = {}def __init__(self, path = None):self.reload(path)def reload(self, path = None):if not path:returnself.model_dict.clear()fp = file(path, "r")for line in fp:cols = line.split()self.model_dict[cols[0]] = cols[1]self.model_path = pathdef main():m1 = Model()m2 = Model()m1.reload("aa_model")m2.reload("bb_model")print m1.model_pathprint m2.model_pathprint m1.model_dictprint m2.model_dictreturn 0if __name__ == "__main__":main()

  aa_model

1 a
2 b

  bb_model

x 1 y 2 z 3

  結(jié)果如圖:

  aa_model, bb_model: 由于reload方法中self.model_path = path, 實例重寫了類的model_path屬性(第一次賦值視為變量的定義), 故輸出本實例的model_path

  {‘y': 2, 'x': '1', 'z': '3'},?{‘y': 2, 'x': '1', 'z': '3'}: 由于self.model_dict.clear(), 第一次使用此變量非賦值而是直接使用(類似PHP), 類似函數(shù)中表示使用已有的值, 根據(jù)MRO, 搜索到Model.model_dict, 故兩次會覆蓋同一個變量

30.類的特殊屬性

  C.__name__: 類的名字

  C.__doc__: 類的文檔描述

  C.__bases__: 類的基類組成的元組

  C.__dict__: 類的屬性

  C.__module__: 類所在模塊

  C.__class__: 類的類名

  __getattribute__: 不管屬性是否存在都會調(diào)用

  __getattr__: 如果屬性不存在則調(diào)用, 如果__getattribute__被定義會先被調(diào)用, 然后調(diào)用此方法, 也可以返回函數(shù)

class A(object):def __getattr__(self, attr):if attr == "age":return lambda : 25a = A() a.age()

?

  __setattr__

  __delattr__

  __slots__: 限制實例可以添加到屬性

  hasattr(), getattr(), setattr(), delattr()

31.實例的特殊屬性

  i.__class__: 實例的類名

  i.__dict__: 實例的屬性, __dict__分層存儲屬性, 每一層的__dict__只存儲該層新增的屬性, 子類不需要重復(fù)存儲父類中的屬性

32.property()可以即時生成屬性

33.類中私有屬性__xx, 實現(xiàn)為Python自動為__xx改變變量名

34.當(dāng)我們定義一個class的時候, 我們實際上就定義了一種數(shù)據(jù)類型, 我們定義的數(shù)據(jù)類型和Python自帶的數(shù)據(jù)類型, 比如str、list、dict沒什么兩樣, type(instance), 返回instance對應(yīng)的Class類型, 比如

class A(object):passa = A() b = type(a)() #此時b為A的實例print type(A) #<type 'type'> print type(a) #<class '__main__.A'> print isinstance(b, A) #True

  type()函數(shù)可以查看一個類型或變量的類型, A是一個class(類對象), 它的類型就是type, 而h是一個實例, 它的類型就是class A

  class的定義是運行時動態(tài)創(chuàng)建的, 而創(chuàng)建class的方法就是使用type()函數(shù),?type()函數(shù)既可以返回一個對象的類型, 又可以創(chuàng)建出新的類型, 比如, 我們可以通過type()函數(shù)創(chuàng)建出A類, 而無需通過class A(object)...的定義,?

def fn(self, name = "John"):self.name = nameA = type('A', (object,), dict(hello=fn)) a = A() print type(A) #<type 'type'> print type(a) #<class '__main__.A'>

  type() 創(chuàng)建類對象的參數(shù)如下: 

    class的名稱

    繼承的父類集合, 注意Python支持多重繼承, 如果只有一個父類, 別忘了tuple的單元素寫法

    class的方法名稱與函數(shù)綁定, 這里我們把函數(shù)fn綁定到方法名hello上

  通過type()函數(shù)創(chuàng)建的類和直接寫class是完全一樣的, 因為Python解釋器遇到class定義時, 僅僅是掃描一下class定義的語法, 然后調(diào)用type()函數(shù)創(chuàng)建出class

  除了使用type()動態(tài)創(chuàng)建類對象, 還可以使用元類, 即 metaclass, 流程為先定義metaclass, 就可以創(chuàng)建類, 最后創(chuàng)建實例

# metaclass是創(chuàng)建類,所以必須從`type`類型派生: class ListMetaclass(type):def __new__(cls, name, bases, attrs):attrs['add'] = lambda self, value: self.append(value)return type.__new__(cls, name, bases, attrs)class MyList(list):__metaclass__ = ListMetaclass # 指示使用ListMetaclass來定制類, 表示創(chuàng)建MyList時要通過ListMetaclass.__new__()來創(chuàng)建, 在此, 我們可以修改類的定義, 比如, 加上新的方法, 然后, 返回修改后的定義

  __new__()方法接收到的參數(shù)依次是:當(dāng)前準(zhǔn)備創(chuàng)建的類的對象, 類的名字, 類繼承的父類集合, 類的方法集合

35.types模塊, 可以查看所有的type, type(abs) == types.BuiltinFunctionType

36.把方法變成屬性 @property

class Student(object):#@property 會創(chuàng)建一個另外一個裝飾器 @score.setter, 負(fù)責(zé)把一個方法編程屬性賦值 @propertydef score(self):return self._score@score.setterdef score(self, value):if not isinstance(value, int):raise ValueError('score must be an integer!')if value < 0 or value > 100:raise ValueError('score must between 0 ~ 100!')self._score = values = Student() s.score = 60 s.score = 101 #ValueError: Score must between 0 ~ 100!

37.Linux下用Python實現(xiàn)多進(jìn)程(此處不是講線程), Unix/Linux操作系統(tǒng)提供了一個fork()系統(tǒng)調(diào)用, 它返回兩次, 因為操作系統(tǒng)自動把當(dāng)前進(jìn)程(稱為父進(jìn)程)復(fù)制了一份(稱為子進(jìn)程), 然后, 分別在父進(jìn)程和子進(jìn)程內(nèi)返回, 子進(jìn)程永遠(yuǎn)返回0, 而父進(jìn)程返回子進(jìn)程的ID, 這樣做的理由是, 一個父進(jìn)程可以fork出很多子進(jìn)程, 所以, 父進(jìn)程要記下每個子進(jìn)程的ID, 而子進(jìn)程只需要調(diào)用getppid()就可以拿到父進(jìn)程的ID; Windows系統(tǒng)不支持fork()函數(shù); 有了fork調(diào)用, 一個進(jìn)程在接到新任務(wù)時就可以復(fù)制出一個子進(jìn)程來處理新任務(wù), 常見的Apache服務(wù)器就是由父進(jìn)程監(jiān)聽端口, 每當(dāng)有新的http請求時, 就fork出子進(jìn)程來處理新的http請求

import osprint('Process (%s) start...' % os.getpid()) # Only works on Unix/Linux/Mac: pid = os.fork() if pid == 0:print('I am child process (%s) and my parent is %s.' % (os.getpid(), os.getppid())) else:print('I (%s) just created a child process (%s).' % (os.getpid(), pid))

38.multiprocessing模塊是跨平臺的多進(jìn)程模塊

  創(chuàng)建一個進(jìn)程運行某個函數(shù)

from multiprocessing import Process import os# 子進(jìn)程要執(zhí)行的代碼 def run_proc(name):print('Run child process %s (%s)...' % (name, os.getpid()))if __name__=='__main__':print('Parent process %s.' % os.getpid())p = Process(target=run_proc, args=('test',))print('Child process will start.')p.start()p.join()print('Child process end.')

  結(jié)果為:

Parent process 67416. Child process will start. Run child process test (70388)... Child process end.

  join()方法可以等待子進(jìn)程結(jié)束后再繼續(xù)往下運行, 通常用于進(jìn)程間的同步

39.占位

40.timestamp與時區(qū)毫無關(guān)系, timestamp一旦確定, 其UTC時間就確定了, 轉(zhuǎn)換到任意時區(qū)的時間也是完全確定的, 全球各地的計算機在任意時刻的timestamp都是完全相同的, datetime是有時區(qū)的, 會在timestamp與本地時間之間做轉(zhuǎn)換

>>> from datetime import datetime >>> t = 1429417200.0 >>> print(datetime.fromtimestamp(t)) # 本地時間 2015-04-19 12:20:00 >>> print(datetime.utcfromtimestamp(t)) # UTC時間 2015-04-19 04:20:00

41.struct模塊, 了解c語言的人, 一定會知道struct結(jié)構(gòu)體在c語言中的作用, 它定義了一種結(jié)構(gòu), 里面包含不同類型的數(shù)據(jù)(int, char, bool等等), 方便對某一結(jié)構(gòu)對象進(jìn)行處理, 而在網(wǎng)絡(luò)通信當(dāng)中, 大多傳遞的數(shù)據(jù)是以二進(jìn)制流(binary data)存在的, 當(dāng)傳遞字符串時, 不必?fù)?dān)心太多的問題, 而當(dāng)傳遞諸如int、char之類的基本數(shù)據(jù)的時候, 就需要有一種機制將某些特定的結(jié)構(gòu)體類型打包成二進(jìn)制流的字符串然后再網(wǎng)絡(luò)傳輸, 而接收端也應(yīng)該可以通過某種機制進(jìn)行解包還原出原始的結(jié)構(gòu)體數(shù)據(jù), python中的struct模塊就提供了這樣的機制, 該模塊的主要作用就是對python基本類型值與用python字符串格式表示的C struct類型間的轉(zhuǎn)化.

>>>import struct >>>ss = struct.pack("!H4s2I", 20, "abcd", 6, 7) >>>ss "\x00\x14abcd\x00\x00\x00\x06\x00\x00\x00\x07" #ss是一個字符串 類似c結(jié)構(gòu)體的字節(jié)流(二進(jìn)制)的字符串表示 >>>struct.unpack("!H4s2I", ss) (20, 'abcd', 6, 7)

  H表示 一個unsigned short的id, 4s表示4字節(jié)長的字符串, 2I表示有兩個unsigned int類型的數(shù)據(jù)

  struct中支持的格式如下表

FormatC TypePython字節(jié)數(shù)
xpad byteno value1
ccharstring of length 11
bsigned charinteger1
Bunsigned charinteger1
?_Boolbool1
hshortinteger2
Hunsigned shortinteger2
iintinteger4
Iunsigned intinteger or long4
llonginteger4
Lunsigned longlong4
qlong longlong8
Qunsigned long longlong8
ffloatfloat4
ddoublefloat8
schar[]string1
pchar[]string1
Pvoid *long

  另一方面, 打包的后的字節(jié)順序默認(rèn)上是由操作系統(tǒng)的決定的, 當(dāng)然struct模塊也提供了自定義字節(jié)順序的功能, 可以指定大端存儲、小端存儲等特定的字節(jié)順序, 對于底層通信的字節(jié)順序是十分重要的, 不同的字節(jié)順序和存儲方式也會導(dǎo)致字節(jié)大小的不同; 在format字符串前面加上特定的符號即可以表示不同的字節(jié)順序存儲方式, 例如采用小端存儲 s = struct.Struct(‘<I3sf’)就可以了, 官方api library 也提供了相應(yīng)的對照列表:

CharacterByte orderSize and alignment
@nativenative??????????? 湊夠4個字節(jié)
=nativestandard??????? 按原字節(jié)數(shù)
<little-endianstandard??????? 按原字節(jié)數(shù)
>big-endianstandard?????? 按原字節(jié)數(shù)
!network (= big-endian)

standard?????? 按原字節(jié)數(shù)

  利用struct解析BMP文件頭, 首先找一個bmp文件, 沒有的話用“畫圖”畫一個, 讀入前30個字節(jié)來分析:

>>> s = b'\x42\x4d\x38\x8c\x0a\x00\x00\x00\x00\x00\x36\x00\x00\x00\x28\x00\x00\x00\x80\x02\x00\x00\x68\x01\x00\x00\x01\x00\x18\x00'

  BMP格式采用小端方式存儲數(shù)據(jù),文件頭的結(jié)構(gòu)按順序如下:? 兩個字節(jié):'BM'表示W(wǎng)indows位圖,'BA'表示OS/2位圖; 一個4字節(jié)整數(shù):表示位圖大小; 一個4字節(jié)整數(shù):保留位,始終為0; 一個4字節(jié)整數(shù):實際圖像的偏移量; 一個4字節(jié)整數(shù):Header的字節(jié)數(shù); 一個4字節(jié)整數(shù):圖像寬度; 一個4字節(jié)整數(shù):圖像高度; 一個2字節(jié)整數(shù):始終為1; 一個2字節(jié)整數(shù):顏色數(shù)。? 所以,組合起來用unpack讀取:

>>> struct.unpack('<ccIIIIIIHH', s) (b'B', b'M', 691256, 0, 54, 40, 640, 360, 1, 24)

  結(jié)果顯示,b'B'、b'M'說明是Windows位圖,位圖大小為640x360,顏色數(shù)為24。

42.快速創(chuàng)建字典

  {}.from_keys(list, defaultValue)

  dict((key1, value1), (key2, value2), (key3, value3)...)

  zip([key1, key2, key3...], [value1, value2, value3...])

  dict(name = "John", "age" = 26)

43.判斷字典中鍵名是否存在的兩種方法

#第一種 d.has_key()#第二種 "" in d.keys()

44.判斷對象中屬性/方法是否存在

hasattr(object, attr)
attr in dir(object)

45.動態(tài)調(diào)用方法

def _execute(self, sql, params, isMany):func = "executemany" if isMany else "execute"func = getattr(self._db["cur"], func)return func(sql, params)

46.False, 0, '', (), [], {}都可以視為假

47.列表內(nèi)數(shù)據(jù)唯一(類似PHP中array_unique)

set([1, 2, 1]) -- set([1, 2])

48.根據(jù)一個對象創(chuàng)建另一個對象

obj.__class__(...)

49.collections模塊

  collections.namedtuple 創(chuàng)建可命名的tuple

import collections as cs Point = cs.namedtuple("Point", ["x", "y", "z"]) p = Point(1, 2, 3)print p.x, p.y, p.z

  collections.deque 為了高效實現(xiàn)插入和刪除操作的雙向列表,增刪效率高于 list,也可以使用 deque(maxlen = 10) 來限制列表長度,超出時添加會把頭尾的元素擠出。

import collections as cs q = cs.deque(['a', 'b', 'c']) q.append('x') q.appendleft('y') print q>>>deque(['y', 'a', 'b', 'c', 'x'])

  collections.defaultdict 使用dict時,如果引用的Key不存在,就會拋出KeyError。如果希望key不存在時,返回一個默認(rèn)值,就可以用defaultdict,也可以直接創(chuàng)建多維字典

import collections as cstree = lambda: collections.defaultdict(tree)d = tree() d["names"]["John"] = "ABC"

  collections.OrderedDict 創(chuàng)建按key值遍歷時有序的dict(普通dict無序排列) 使用

50.禁止創(chuàng)建對象屬性字典。每個類都有實例屬性,默認(rèn)用一個字典保存一個對象的實例屬性,允許我們設(shè)置任意屬性,但是可能會浪費很多內(nèi)存。使用__slots__高速Python不要使用字典,而且只給一個固定集合的屬性分配空間。

class MyClass(obj ect) : __slots__ = [ ' name' , ' identifier' ] def __init__(self, name, identifier) : self. name = name self. identifier = identifier self. set_up()

51.文件遍歷

with open("foo.txt", "r") as f:for line in f:# do_something(line)for line in open("foo.txt", "r"):# do_something(line)

52.打印格式化的json

import json print json.dumps({"name": "John"}, indent = 2)

53.格式化輸出字典

print("I'm %(name)s. I'm %(age)d year old" % {'name':'Vamei', 'age':99})
print("I'm {name}.I'm {age} year old").format(name = "John", age = 26)

54.字典和集合也有列表推導(dǎo)式,都使用{}包圍,分別返回字典和集合

#快速兌換字典鍵—值 mca={"a":1, "b":2, "c":3, "d":4} dicts={v:k for k,v in mca.items()} #{1: 'a', 2: 'b', 3: 'c', 4: 'd'}

55.字面量,即 {}, [] 等直接表示。

56.從標(biāo)準(zhǔn)輸入獲取數(shù)據(jù),除了 input、raw_input 也可以使用如下方式

import sys sys.stdin.readline().strip()

57.數(shù)據(jù)庫 IN 查詢的正確姿勢不是如下

id_list = [1, 2, 3] arg_list = ','.join(['%s'] * len(id_list)) cursor.execute('SELECT col1, col2 FROM table1 WHERE id IN (%s)' % arg_list, id_list)

  而是如下(參考資料:http://ju.outofmemory.cn/entry/51481):

id_list = [1, 2, 3] cursor.execute('SELECT col1, col2 FROM table1 WHERE id IN %s', (id_list,))

58.

總結(jié)

以上是生活随笔為你收集整理的Python-技巧的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。