作者:半載流殤
鏈接:https: //zhuanlan.zhihu.com/p/35219750
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。Pythonic,簡言之就是以Python這門語言獨特的方式寫出既簡潔又優美的代碼!筆者精心整理了許多實用的Python tricks,想要提高效率、寫出高質量的Python代碼的話此文必看。 注:請將Python更新到3.6版,方能完美運行本文的所有代碼。字符串格式化字符串在字符串前加f,就可以在里面用大括號嵌入變量了(可以代替format函數) >>> a = 5
>>> b = 10
>>> f
' Five plus ten is {a + b} and not {2 * (a + b)}. '
' Five plus ten is 15 and not 30. '
字符串拼接 >>> text = [
' I ' ,
' Love ' ,
' Python! ' ]
>>>
print (
'' .join(text))
I Love Python!
字符串的contains >>>
' ov ' in ' love '
True
反轉元素 >>>
' Love ' [::-1
]
' evoL '
>>>
for e
in reversed([1,3,5]):
print (e)
5 3 1
去除非法字符串保存文件時,我們必須去除一些非法字符串,此處利用any函數實現def rectify(name): if any(symbol
in name
for symbol
in [
' ? ' ,
' < ' ,
' > ' ,
' | ' ,
' * ' ,
' " ' ,
" : " ]):name =
'' .join([c
for c
in name
if c
not in [
' ? ' ,
' < ' ,
' > ' ,
' | ' ,
' * ' ,
' " ' ,
" : " ]]) return name
HTML轉義 >>>
import html
>>> html.unescape(
' < ' )
' < '
>>> html.escape(
' < ' )
' < '
函數可變參數 *args:任意數量的位置參數,可被打包成元組。**kwargs:任意數量的關鍵詞參數,可被打包成字典。打包def foo(*args, **
kwargs): print (f
" args: {args} " ) print (f
" kwargs: {kwargs} " ) >>> foo(1,2,3,4, a=1,b=2,c=3
)
args: ( 1, 2, 3, 4
)
kwargs: { ' a ' : 1,
' b ' : 2,
' c ' : 3
}
解包def foo(x, y): print (x, y)alist = [1, 2
]
adict = {
' x ' : 1,
' y ' : 2
} >>> foo(*
alist)
1, 2
>>> foo(**
adict)
1, 2
裝飾器裝飾器的主要用途:打印日志、檢測性能、數據庫事務、URL路由它本質上就是一個高階函數,它接收一個函數作為參數,然后,返回一個新函數。想理解裝飾器,就得知道以下兩點: 1. 函數皆對象2. 閉包特性(內函數能捕捉到外函數的環境變量)簡單的日志函數from datetime
import datetime
import functools
def log(f):@functools.wraps(f) def wr(*args, **
kwargs): print (f
' call {f.__name__}() at {datetime.now()} ' ) return f(*args, **
kwargs) return wr@log
def square(x): return x ** 2>>> square(2
)
call square() at 2018-01-24 11:01:19.547516
4
注意到為了讓@deco自適應任何參數定義的函數,我們將可變參數args, *kwargs作為了wr的參數@functools.wraps(f)為了防止wr的函數屬性覆蓋掉原函數的屬性,我們必須利用@functools.wraps(f)來把原函數的所有屬性復制到新函數里
# 不加@functools.wraps(f)的情況下
>>> square.
__name__
' wr '
# 加了@functools.wraps(f)的情況下
>>> square.
__name__
' square '
如果想給裝飾器傳遞參數,那么你必須利用閉包特性再嵌套一層函數,不過這并不常用。函數性能檢測def perf(f):@functools.wraps(f) def wr(*args, **
kwargs):start =
time.time()r = f(*args, **
kwargs)end =
time.time() print (f
' call {f.__name__}() in {end - start} ' ) return r return wr@perf
def test(x):time.sleep( 2
) return x >>> test(5
)
call test() in 2.0007083415985107
5
數據庫的cursordef link_mysql(fun): def wr(*args, **
kwargs):with pymysql.connect(host =host, port=port, user=user, passwd=passwd, db=dbname, charset=
charset) as cur:fun(cur, *args, **
kwargs) return wr@link_mysql
def insert_data(cur, ...): # execute your sql here.
上下文管理器應用文件操作(超常用)、進程互斥鎖和支持上下文的其他對象目的是為了代替try語句和簡化語法以文件操作為例:利用它,文件會自動打開和關閉with open(
' /path/to/file ' ,
' r ' ) as f:handle_f
上下文語句支持嵌套(nested)例如將a文件的源數據寫入b文件里:with open( ' a.txt ' ) as i, open(
' b.txt ' ) as o:o.write(i.read())
實質通過上下文管理協議__enter__和__exit__來實現Python有個庫contextlib利用生成器簡化了這種實現,以下是大體框架from contextlib import contextmanager@contextmanager
def make_context() : # enter try : yield <value>
except Exception as e: # handle_err finally : # exit
with make_context() as <value>
: # handle_value
以下是with語句操作文件的實質由于自定義,函數名用my_open,但功能和open幾乎一樣@contextmanager
def my_open(filename, mode):f =
open(filename, mode) try : yield f except Exception as e: raise e finally :f.close()with my_open( ' /path/to/file ' ,
' r ' ) as f:handle_f
偏函數partial()用于把一個函數的某些參數給固定住(也就是設置默認值),并返回一個新的函數。 def int2(x, base=2
): return int(x, base)
相當于: import functools
int2 = functools.partial(int, base=2
)
數據結構元組元組是一個immutable對象,有以下重要性: - 性能優化- 線程安全- 可以作為dict的key(hashable)- 拆包特性元組拆包a, b = b, a兩個數字交換的原理就是它。以下是利用它來獲取文件名及其擴展名>>>
import os
>>> filename, ext = os.path.splitext(
' patch.exe ' )
>>>
filename
' patch '
>>>
ext
' exe '
更多的解包方式(_代表舍棄, *代表可變長元組)>>> t = (1, 2, 3, 4
)
>>> first, *middle, last =
t
>>>
middle
[ 2, 3
]
>>> _, *rest =
t
>>>
rest
[ 2, 3, 4
]
列表切片如果想要獲取列表的多個元素,就得用到切片list[start:stop:step]
你甚至可以給切片命名,增強復用性和可讀性:s =
slice(start,stop,step)
list[s]
切片的原理是序列協議class Seq: def __getitem__ (self, index): return index >>> s =
Seq()
>>> s[1:5:2
]
slice( 1, 5, 2
)
以上實現的是不可變序列協議,如果可變的話還要添加__setitem__()如果在運行時添加協議的話也行,這叫猴子補丁 >>>
def set_item(self, key, value):self[key] =
value
>>> classname.
__setitem__ =
set_item
列表推導式這是Python最強大的幾個特征之一。格式也很簡單,其中if條件可以省略,for循環可以有多個[i for i
in iterable
if condition]
10-20所有偶數的平方:[i*i
for i
in range(10, 21)
if i % 2 ==
0 ]
一行實現快排def qsort(arr): return arr
if len(arr) <= 1
else qsort([x
for x
in arr[1:]
if x<arr[0]]) + [arr[0]] + qsort([x
for x
in arr[1:]
if x>=
arr[0]])
索引迭代enumerate()可以把一個list變成索引 -元素對。
for i, value
in enumerate([
' A ' ,
' B ' ,
' C ' ]): print (i, value)
0 A 1 B 2
C
zipzip()可以將可迭代的對象作為參數,將對象中對應的元素打包成一個個元組,并返回一個迭代器,常用于同時遍歷兩個可迭代對象。 >>> li1 = [
' Python ' ,
' JavaScript ' ,
' Java ' ]
>>> li2 = [1, 2, 3
]
>>> nl =
zip(li1, li2)
<zip object at memory>
>>>
list(nl)
[( ' Python ' , 1), (
' JavaScript ' , 2), (
' Java ' , 3
)]
配合dict可以生成字典 >>> l1 = [
' A ' ,
' B ' ,
' C ' ]
>>> l2 = [1, 2, 3
]
>>>
dict(zip(l1, l2))
{ ' A ' : 1,
' B ' : 2,
' C ' : 3
}
append和extend >>> x = [1, 2, 3
]
>>> x.extend([4, 5
])
>>>
x
[ 1, 2, 3, 4, 5
]
>>> x.append([6, 7
])
>>>
x
[ 1, 2, 3, 4, 5, [6, 7
]]
集合運算首先將要比較的兩個list轉換為set,再轉回list就行了 >>> l1 = [1, 2, 3, 4
]
>>> l2 = [2, 3, 5, 7
]
>>> list(set(l1) &
set(l2))
[ 2, 3
]
>>> list(set(l1) |
set(l2))
[ 1, 2, 3, 4, 5, 7
]
>>> list(set(l1) ^
set(l2))
[ 1, 4, 5, 7
]
字典本質是鍵值對哈希表get用來獲取某個鍵的值,不存在的話就用設置的default(默認為None) >>> d = dict(a=1, b=2
)
>>> d.get(
' a ' )
1
>>> d.get(
' c ' )
>>> d.get(
' d ' , 2
)
2
合并 >>> d1 = {
' a ' :1,
' b ' :2
}
>>> d2 = {
' c ' :3,
' d ' :4
}
>>> nd = {**d1, **
d2}
>>>
nd
{ ' a ' : 1,
' b ' : 2,
' c ' : 3,
' d ' : 4
}
類似的,列表也可以這樣合并 >>> l1 = [1, 2
]
>>> l2 = [3, 4
]
>>> l3 = [*l1, *
l2]
>>>
l3
[ 1, 2, 3, 4
]
鍵值對反轉 >>> kv = {
' a ' : 1,
' b ' :2 ,
' c ' : 3
}
>>> vk =
zip(kv.values(), kv.keys())
>>>
dict(vk)
{ 1:
' a ' , 2:
' b ' , 3:
' c ' }
>>>
min(vk)
( 1,
' a ' )
>>>
sorted(vk)
[( 1,
' a ' ), (2,
' b ' ), (3,
' c ' )]
鍵值排序 >>> rows =
[{k1: v1, k2: v2 ...}, ...]
>>>
from operator
import itemgetter
# 根據k1排序
>>> sorted(rows, key=
itemgetter(k1))
# 類似的,對于class的對象可以用attrgetter進行排序
集合運算>>> a = {
' a ' : 1,
' b ' : 2,
' c ' : 3
}
>>> b = {
' x ' : 1,
' b ' : 2,
' c ' : 4
}
>>> a.keys() &
b.keys()
{ ' b ' ,
' c ' }
>>> a.keys() -
b.keys()
{ ' a ' }
>>> a.items() &
b.items()
{( ' b ' , 2
)}
其他數據結構具名元組常用于構建簡單的類 >>>
from collections
import namedtuple
>>> Point = namedtuple(
' Point ' , [
' x ' ,
' y ' ])
>>> p = Point(x=11, y=22
)
>>>
p
Point(x =11, y=22
)
>>> p.x +
p.y
33
>>> coord = (33, 44
)
>>> q = Point(*
coord)
>>>
q
Point(x =33, y=44
)
默認值字典常用于統計數目 >>>
from collections
import defaultdict
>>> words = (
' python ' ,
' java ' ,
' ruby ' ,
' python ' ,
' C ' ,
' java ' ,
' C++ ' ,
' C ' )
>>> counts =
defaultdict(int)
>>>
for word
in words:
... counts[word] += 1
>>>
counts
defaultdict( <
class ' int ' >, {
' python ' : 2,
' java ' : 2,
' ruby ' : 1,
' C ' : 2,
' C++ ' : 1
})
雙向隊列 >>>
from collections
import deque
>>> q = deque([
" Eric " ,
" John " ,
" Michael " ])
>>> q.append(
" Terry " )
>>>
q
deque([ ' Eric ' ,
' John ' ,
' Michael ' ,
' Terry ' ])
>>>
q.popleft()
Eric '
>>>
q.pop()
' Terry '
>>>
q
deque([ ' John ' ,
' Michael ' ])
計數器 >>>
from collections
import Counter
>>> c = Counter(
' hello world ' )
>>>
c
Counter({ ' l ' : 3,
' o ' : 2,
' ' : 1,
' e ' : 1,
' d ' : 1,
' h ' : 1,
' r ' : 1,
' w ' : 1
})
>>> c.most_common(2
)
[( ' l ' , 3), (
' o ' , 2
)]
堆 >>>
import heapq
>>> a = [1, 2, 3
]
>>> b = [4, 5, 6
]
>>> c =
list(heapq.merge(a, b))
>>>
c
[ 1, 2, 3, 4, 5, 6
]
>>> heapq.nlargest(3
, c)
[ 6, 5, 4
]
>>> heapq.nsmallest(3
, c)
[ 1, 2, 3
]
OOP只讀屬性可以通過在變量名前加__來使其變成私有變量,外部無法直接訪問,但可以通過類定義的方法來訪問。 class Person(object): def __init__ (self, name):self. __name =
name def get_name(self): return self.
__name def set_name(self, name):self. __name =
name >>> p = Person(
' alphardex ' )
>>>
p.name
Traceback (most recent call last):File " <stdin> " , line 1,
in <module>
AttributeError: ' Person ' object has no attribute
' name '
>>>
p.get_name()
' alphardex '
>>> p.set_name(
' wang ' )
>>>
p.get_name()
' wang '
@property肯定有的人不習慣通過方法來訪問私有變量,那么如何用屬性來訪問私有變量呢?這時就要用到@property了,它可以把一個方法變成屬性調用class Person(object): def __init__ (self, name):self. __name =
name@property def name(self): return self.
__name @name.setter def name(self, value):self. __name =
value >>> p = Person(
' alphardex ' )
>>>
p.name
' alphardex '
>>> p.name =
' wang '
>>>
p.name
' wang '
slots當我們定義了一個class并用其創建了一個實例后,可以動態地給其綁定屬性,如果要限制這一點,可以利用__slots__class Person(object): __slots__ = (
' name ' ,
' age ' ) >>> p = Person(
' wang ' )
>>> p.name =
' wang '
>>> p.age = 21
>>> p.skill =
' Python '
Traceback (most recent call last):File " <stdin> " , line 1,
in <module>
AttributeError: ' Person ' object has no attribute
' skill '
魔術方法魔術方法可以用來定制類的功能。比如__repr__用來調試時打印類的字符串class Person(object): def __init__ (self, name, age):self.name =
nameself.age =
age def __repr__ (self): return f
' <Person {self.name} age: {self.age}> ' >>> p = Person(
' alphardex ' , 21
)
>>>
p
<Person alphardex age: 21>
想了解更多魔術方法請參見官方文檔元類type俗話說道生一,一生二,二生三,三生萬物。在Python里可以這么說:type生元類,元類生類,類生實例。用一個數字變量的創建來說明這一點吧 >>> age = 21
>>> age.
__class__
<
class ' int ' >
>>> age.
__class__ .
__class__
<
class ' type ' >
age可以看作為int類的實例,而int類又可以看做type類的實例。也就是說,type創建了int類,實際上諸如str和bool等類也是由type創建的。 >>>
help(type)
Help on class type
in module builtins: class type(object) |
type(object_or_name, bases, dict) | type(object) -> the object
' s type | type(name, bases, dict) ->
a new type def say_hello(self, name=
' world ' ): print (f
' Hello, {name} ' ) >>> Hello = type(
' Hello ' , (object,), dict(hello=
say_hello))
>>> h =
Hello()
>>>
type(Hello)
<
class ' type ' >
>>>
type(h)
<
class ' __main__.Hello ' >
通過用help查看type,可以發現它確實能動態地創建類:第一個參數是類名name,第二個參數是基類bases,第三個參數是dict,里面包含著類的所有方法。實際上,type是Python的一個內置元類。自定義元類當然,你也可以利用type來定義自己的元類。 class JSArrayMeta(type): def __new__ (cls, name, bases, attrs):attrs[ ' push ' ] =
lambda self, value: self.append(value)attrs[ ' shift ' ] =
lambda self: self.pop(0)attrs[ ' includes ' ] =
lambda self, value: value
in self return type.
__new__ (cls, name, bases, attrs) class JSList(list, metaclass=
JSArrayMeta): def __init__ (self, value):self.extend(value) >>> l = JSList([1, 2, 3
])
>>>
l
[ 1, 2, 3
]
>>> l.push(
' a ' )
>>>
l
[ 1, 2, 3,
' a ' ]
>>>
l.shift()
1
>>>
l
[ 2, 3,
' a ' ]
>>> l.includes(3
)
True
我們首先定制了一個元類,叫JSArrayMetaclass(沒錯就是JS里的數組XD)注意元類的命名規則:結尾一定要有Meta作為識別__new__方法用來創建JSList類,它接受4個參數JSList繼承了list類,同時獲得了元類的所有方法其他加載內置模塊利用 -m參數,我們可以直接加載Python的模塊
# 搭建http服務器
$ python -
m http.server
# 創建虛擬環境
$ python -m venv <name>
# 性能測試
$ python -m cProfile <file.py>
# 查看JSON
$ cat <file.json> | python -
m json.tool
數據序列化import pickle
data = ...
# Some Python object
# 存儲
with open(f
' {file}.pickle ' ,
' wb ' ) as f:pickle.dump(data, f)
# 讀取
with open(f
' {file}.pickle ' ,
' rb ' ) as f:data =
pickle.load(f)
數據分析利用pandas模塊可以對數據進行分析$ pip install pandas
>>>
import pandas as pd
>>> data =
pd.read_csv(...)
# 數據查看
>>> data.columns
# 查看數據結構
>>> data.describe()
# 簡要數據分析
>>> data.sort_values(by=...)
# 對數據排序
# 數據選取
>>> data.head()
# 查看前五條數據
>>> data.iloc[n]
# 選擇位置為n的數據,支持切片
>>> data[data.A > 0]
# 選擇A欄大于0的數據
>>> data[data.B.isin([...])]
# 利用in過濾數據
>>> data[~data.B.isin([...])]
# 上一句的取反,相當于not in
# 缺失值處理
>>> pd.isna(data)
# 獲取缺失值的布爾標記
>>> data.dropna(how=
' any ' )
# 去除所有含有缺失值的欄
>>> data.fillna(value=5)
# 填充所有含有缺失值的欄
# 數據保存(可以相互轉換格式,支持excel、csv和json)
>>> data.to_json(...)
?
作者:半載流殤
鏈接:https://zhuanlan.zhihu.com/p/35219750
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
Pythonic,簡言之就是以Python這門語言獨特的方式寫出既簡潔又優美的代碼!筆者精心整理了許多實用的Python tricks,想要提高效率、寫出高質量的Python代碼的話此文必看。
注:請將Python更新到3.6版,方能完美運行本文的所有代碼。
字符串 格式化字符串 在字符串前加f,就可以在里面用大括號嵌入變量了(可以代替format函數)
>>> a = 5
>>> b = 10
>>> f 'Five plus ten is {a + b} and not {2 * (a + b)}.'
'Five plus ten is 15 and not 30.'
字符串拼接 >>> text = [ 'I' , ' Love ' , 'Python!' ]
>>> print ( '' . join ( text ))
I Love Python !
字符串的contains >>> 'ov' in 'love'
True
反轉元素 >>> 'Love' [:: - 1 ]
'evoL'
>>> for e in reversed ([ 1 , 3 , 5 ]): print ( e )
5 3 1
去除非法字符串 保存文件時,我們必須去除一些非法字符串,此處利用any函數實現
def rectify ( name ): if any ( symbol in name for symbol in [ '?' , '<' , '>' , '|' , '*' , '"' , ":" ]): name = '' . join ([ c for c in name if c not in [ '?' , '<' , '>' , '|' , '*' , '"' , ":" ]]) return name
HTML轉義 >>> import html
>>> html . unescape ( '<' )
'<'
>>> html . escape ( '<' )
'<'
函數 可變參數 *args:任意數量的位置參數,可被打包成元組。 **kwargs:任意數量的關鍵詞參數,可被打包成字典。
打包 def foo ( * args , ** kwargs ): print ( f "args: {args}" ) print ( f "kwargs: {kwargs}" ) >>> foo ( 1 , 2 , 3 , 4 , a = 1 , b = 2 , c = 3 )
args : ( 1 , 2 , 3 , 4 )
kwargs : { 'a' : 1 , 'b' : 2 , 'c' : 3 }
解包 def foo ( x , y ): print ( x , y ) alist = [ 1 , 2 ]
adict = { 'x' : 1 , 'y' : 2 } >>> foo ( * alist )
1 , 2
>>> foo ( ** adict )
1 , 2
裝飾器 裝飾器的主要用途:打印日志、檢測性能、數據庫事務、URL路由 它本質上就是一個高階函數,它接收一個函數作為參數,然后,返回一個新函數。 想理解裝飾器,就得知道以下兩點: 1. 函數皆對象 2. 閉包特性(內函數能捕捉到外函數的環境變量)
簡單的日志函數 from datetime import datetime
import functools
def log ( f ): @functools.wraps ( f ) def wr ( * args , ** kwargs ): print ( f 'call {f.__name__}() at {datetime.now()}' ) return f ( * args , ** kwargs ) return wr @log
def square ( x ): return x ** 2 >>> square ( 2 )
call square () at 2018 - 01 - 24 11 : 01 : 19.547516
4
注意到為了讓@deco自適應任何參數定義的函數,我們將可變參數args, *kwargs作為了wr的參數
@functools.wraps(f) 為了防止wr的函數屬性覆蓋掉原函數的屬性,我們必須利用@functools.wraps(f)來把原函數的所有屬性復制到新函數里
# 不加@functools.wraps(f)的情況下
>>> square . __name__
'wr'
# 加了@functools.wraps(f)的情況下
>>> square . __name__
'square'
如果想給裝飾器傳遞參數,那么你必須利用閉包特性再嵌套一層函數,不過這并不常用。
函數性能檢測 def perf ( f ): @functools.wraps ( f ) def wr ( * args , ** kwargs ): start = time . time () r = f ( * args , ** kwargs ) end = time . time () print ( f 'call {f.__name__}() in {end - start}' ) return r return wr @perf
def test ( x ): time . sleep ( 2 ) return x >>> test ( 5 )
call test () in 2.0007083415985107
5
數據庫的cursor def link_mysql ( fun ): def wr ( * args , ** kwargs ): with pymysql . connect ( host = host , port = port , user = user , passwd = passwd , db = dbname , charset = charset ) as cur : fun ( cur , * args , ** kwargs ) return wr @link_mysql
def insert_data ( cur , ... ): # execute your sql here.
上下文管理器 應用 文件操作(超常用)、進程互斥鎖和支持上下文的其他對象 目的是為了代替try語句和簡化語法 以文件操作為例:利用它,文件會自動打開和關閉
with open ( '/path/to/file' , 'r' ) as f : handle_f
上下文語句支持嵌套(nested) 例如將a文件的源數據寫入b文件里:
with open ( 'a.txt' ) as i , open ( 'b.txt' ) as o : o . write ( i . read ())
實質 通過上下文管理協議__enter__和__exit__來實現 Python有個庫contextlib利用生成器簡化了這種實現,以下是大體框架
from contextlib import contextmanager @contextmanager
def make_context () : # enter try : yield < value > except Exception as e : # handle_err finally : # exit with make_context () as < value > : # handle_value
以下是with語句操作文件的實質 由于自定義,函數名用my_open,但功能和open幾乎一樣
@contextmanager
def my_open ( filename , mode ): f = open ( filename , mode ) try : yield f except Exception as e : raise e finally : f . close () with my_open ( '/path/to/file' , 'r' ) as f : handle_f
偏函數 partial()用于把一個函數的某些參數給固定住(也就是設置默認值),并返回一個新的函數。
def int2 ( x , base = 2 ): return int ( x , base )
相當于:
import functools
int2 = functools . partial ( int , base = 2 )
數據結構 元組 元組是一個immutable對象,有以下重要性: - 性能優化 - 線程安全 - 可以作為dict的key(hashable) - 拆包特性
元組拆包 a, b = b, a 兩個數字交換的原理就是它。 以下是利用它來獲取文件名及其擴展名
>>> import os
>>> filename , ext = os . path . splitext ( 'patch.exe' )
>>> filename
'patch'
>>> ext
'exe'
更多的解包方式(_代表舍棄,*代表可變長元組)
>>> t = ( 1 , 2 , 3 , 4 )
>>> first , * middle , last = t
>>> middle
[ 2 , 3 ]
>>> _ , * rest = t
>>> rest
[ 2 , 3 , 4 ]
列表 切片 如果想要獲取列表的多個元素,就得用到切片
list [ start : stop : step ]
你甚至可以給切片命名,增強復用性和可讀性:
s = slice ( start , stop , step )
list [ s ]
切片的原理是序列協議
class Seq : def __getitem__ ( self , index ): return index >>> s = Seq ()
>>> s [ 1 : 5 : 2 ]
slice ( 1 , 5 , 2 )
以上實現的是不可變序列協議,如果可變的話還要添加__setitem__() 如果在運行時添加協議 的話也行,這叫猴子補丁
>>> def set_item ( self , key , value ): self [ key ] = value
>>> classname . __setitem__ = set_item
列表推導式 這是Python最強大的幾個特征之一。 格式也很簡單,其中if條件可以省略,for循環可以有多個
[ i for i in iterable if condition ]
10-20所有偶數的平方:
[ i * i for i in range ( 10 , 21 ) if i % 2 == 0 ]
一行實現快排
def qsort ( arr ): return arr if len ( arr ) <= 1 else qsort ([ x for x in arr [ 1 :] if x < arr [ 0 ]]) + [ arr [ 0 ]] + qsort ([ x for x in arr [ 1 :] if x >= arr [ 0 ]])
索引迭代 enumerate()可以把一個list變成索引-元素對。
for i , value in enumerate ([ 'A' , 'B' , 'C' ]): print ( i , value )
0 A 1 B 2 C
zip zip()可以將可迭代的對象作為參數,將對象中對應的元素打包成一個個元組,并返回一個迭代器,常用于同時遍歷兩個可迭代對象。
>>> li1 = [ 'Python' , 'JavaScript' , 'Java' ]
>>> li2 = [ 1 , 2 , 3 ]
>>> nl = zip ( li1 , li2 )
< zip object at memory >
>>> list ( nl )
[( 'Python' , 1 ), ( 'JavaScript' , 2 ), ( 'Java' , 3 )]
配合dict可以生成字典
>>> l1 = [ 'A' , 'B' , 'C' ]
>>> l2 = [ 1 , 2 , 3 ]
>>> dict ( zip ( l1 , l2 ))
{ 'A' : 1 , 'B' : 2 , 'C' : 3 }
append和extend >>> x = [ 1 , 2 , 3 ]
>>> x . extend ([ 4 , 5 ])
>>> x
[ 1 , 2 , 3 , 4 , 5 ]
>>> x . append ([ 6 , 7 ])
>>> x
[ 1 , 2 , 3 , 4 , 5 , [ 6 , 7 ]]
集合運算 首先將要比較的兩個list轉換為set,再轉回list就行了
>>> l1 = [ 1 , 2 , 3 , 4 ]
>>> l2 = [ 2 , 3 , 5 , 7 ]
>>> list ( set ( l1 ) & set ( l2 ))
[ 2 , 3 ]
>>> list ( set ( l1 ) | set ( l2 ))
[ 1 , 2 , 3 , 4 , 5 , 7 ]
>>> list ( set ( l1 ) ^ set ( l2 ))
[ 1 , 4 , 5 , 7 ]
字典 本質是鍵值對哈希表
get 用來獲取某個鍵的值,不存在的話就用設置的default(默認為None)
>>> d = dict ( a = 1 , b = 2 )
>>> d . get ( 'a' )
1
>>> d . get ( 'c' )
>>> d . get ( 'd' , 2 )
2
合并 >>> d1 = { 'a' : 1 , 'b' : 2 }
>>> d2 = { 'c' : 3 , 'd' : 4 }
>>> nd = { ** d1 , ** d2 }
>>> nd
{ 'a' : 1 , 'b' : 2 , 'c' : 3 , 'd' : 4 }
類似的,列表也可以這樣合并
>>> l1 = [ 1 , 2 ]
>>> l2 = [ 3 , 4 ]
>>> l3 = [ * l1 , * l2 ]
>>> l3
[ 1 , 2 , 3 , 4 ]
鍵值對反轉 >>> kv = { 'a' : 1 , 'b' : 2 , 'c' : 3 }
>>> vk = zip ( kv . values (), kv . keys ())
>>> dict ( vk )
{ 1 : 'a' , 2 : 'b' , 3 : 'c' }
>>> min ( vk )
( 1 , 'a' )
>>> sorted ( vk )
[( 1 , 'a' ), ( 2 , 'b' ), ( 3 , 'c' )]
鍵值排序 >>> rows = [{ k1 : v1 , k2 : v2 ... }, ... ]
>>> from operator import itemgetter
# 根據k1排序
>>> sorted ( rows , key = itemgetter ( k1 ))
# 類似的,對于class的對象可以用attrgetter進行排序
集合運算 >>> a = { 'a' : 1 , 'b' : 2 , 'c' : 3 }
>>> b = { 'x' : 1 , 'b' : 2 , 'c' : 4 }
>>> a . keys () & b . keys ()
{ 'b' , 'c' }
>>> a . keys () - b . keys ()
{ 'a' }
>>> a . items () & b . items ()
{( 'b' , 2 )}
其他數據結構 具名元組 常用于構建簡單的類
>>> from collections import namedtuple
>>> Point = namedtuple ( 'Point' , [ 'x' , 'y' ])
>>> p = Point ( x = 11 , y = 22 )
>>> p
Point ( x = 11 , y = 22 )
>>> p . x + p . y
33
>>> coord = ( 33 , 44 )
>>> q = Point ( * coord )
>>> q
Point ( x = 33 , y = 44 )
默認值字典 常用于統計數目
>>> from collections import defaultdict
>>> words = ( 'python' , 'java' , 'ruby' , 'python' , 'C' , 'java' , 'C++' , 'C' )
>>> counts = defaultdict ( int )
>>> for word in words :
... counts [ word ] += 1
>>> counts
defaultdict ( < class ' int '>, {' python ': 2, ' java ': 2, ' ruby ': 1, ' C ': 2, ' C ++ ': 1})
雙向隊列 >>> from collections import deque
>>> q = deque ([ "Eric" , "John" , "Michael" ])
>>> q . append ( "Terry" )
>>> q
deque ([ 'Eric' , 'John' , 'Michael' , 'Terry' ])
>>> q . popleft ()
Eric '
>>> q . pop ()
'Terry'
>>> q
deque ([ 'John' , 'Michael' ])
計數器 >>> from collections import Counter
>>> c = Counter ( 'hello world' )
>>> c
Counter ({ 'l' : 3 , 'o' : 2 , ' ' : 1 , 'e' : 1 , 'd' : 1 , 'h' : 1 , 'r' : 1 , 'w' : 1 })
>>> c . most_common ( 2 )
[( 'l' , 3 ), ( 'o' , 2 )]
堆 >>> import heapq
>>> a = [ 1 , 2 , 3 ]
>>> b = [ 4 , 5 , 6 ]
>>> c = list ( heapq . merge ( a , b ))
>>> c
[ 1 , 2 , 3 , 4 , 5 , 6 ]
>>> heapq . nlargest ( 3 , c )
[ 6 , 5 , 4 ]
>>> heapq . nsmallest ( 3 , c )
[ 1 , 2 , 3 ]
OOP 只讀屬性 可以通過在變量名前加__來使其變成私有變量,外部無法直接訪問,但可以通過類定義的方法來訪問。
class Person ( object ): def __init__ ( self , name ): self . __name = name def get_name ( self ): return self . __name def set_name ( self , name ): self . __name = name >>> p = Person ( 'alphardex' )
>>> p . name
Traceback ( most recent call last ): File "<stdin>" , line 1 , in < module >
AttributeError : 'Person' object has no attribute 'name'
>>> p . get_name ()
'alphardex'
>>> p . set_name ( 'wang' )
>>> p . get_name ()
'wang'
@property 肯定有的人不習慣通過方法來訪問私有變量,那么如何用屬性來訪問私有變量呢?這時就要用到@property了,它可以把一個方法變成屬性調用
class Person ( object ): def __init__ ( self , name ): self . __name = name @property def name ( self ): return self . __name @name.setter def name ( self , value ): self . __name = value >>> p = Person ( 'alphardex' )
>>> p . name
'alphardex'
>>> p . name = 'wang'
>>> p . name
'wang'
slots 當我們定義了一個class并用其創建了一個實例后,可以動態地給其綁定屬性,如果要限制這一點,可以利用__slots__
class Person ( object ): __slots__ = ( 'name' , 'age' ) >>> p = Person ( 'wang' )
>>> p . name = 'wang'
>>> p . age = 21
>>> p . skill = 'Python'
Traceback ( most recent call last ): File "<stdin>" , line 1 , in < module >
AttributeError : 'Person' object has no attribute 'skill'
魔術方法 魔術方法可以用來定制類的功能。 比如__repr__用來調試時打印類的字符串
class Person ( object ): def __init__ ( self , name , age ): self . name = name self . age = age def __repr__ ( self ): return f '<Person {self.name} age: {self.age}>' >>> p = Person ( 'alphardex' , 21 )
>>> p
< Person alphardex age : 21 >
想了解更多魔術方法請參見官方文檔
元類 type 俗話說道生一,一生二,二生三,三生萬物。 在Python里可以這么說:type生元類,元類生類,類生實例。 用一個數字變量的創建來說明這一點吧
>>> age = 21
>>> age . __class__
< class ' int '>
>>> age . __class__ . __class__
< class ' type '>
age可以看作為int類的實例,而int類又可以看做type類的實例。 也就是說,type創建了int類,實際上諸如str和bool等類也是由type創建的。
>>> help ( type )
Help on class type in module builtins : class type ( object ) | type ( object_or_name , bases , dict ) | type ( object ) -> the object 's type | type ( name , bases , dict ) -> a new type def say_hello ( self , name = 'world' ): print ( f 'Hello, {name}' ) >>> Hello = type ( 'Hello' , ( object ,), dict ( hello = say_hello ))
>>> h = Hello ()
>>> type ( Hello )
< class ' type '>
>>> type ( h )
< class ' __main__ . Hello '>
通過用help查看type,可以發現它確實能動態地創建類:第一個參數是類名name,第二個參數是基類bases,第三個參數是dict,里面包含著類的所有方法。 實際上,type是Python的一個內置元類。
自定義元類 當然,你也可以利用type來定義自己的元類。
class JSArrayMeta ( type ): def __new__ ( cls , name , bases , attrs ): attrs [ 'push' ] = lambda self , value : self . append ( value ) attrs [ 'shift' ] = lambda self : self . pop ( 0 ) attrs [ 'includes' ] = lambda self , value : value in self return type . __new__ ( cls , name , bases , attrs ) class JSList ( list , metaclass = JSArrayMeta ): def __init__ ( self , value ): self . extend ( value ) >>> l = JSList ([ 1 , 2 , 3 ])
>>> l
[ 1 , 2 , 3 ]
>>> l . push ( 'a' )
>>> l
[ 1 , 2 , 3 , 'a' ]
>>> l . shift ()
1
>>> l
[ 2 , 3 , 'a' ]
>>> l . includes ( 3 )
True
?
我們首先定制了一個元類,叫JSArrayMetaclass(沒錯就是JS里的數組XD) 注意元類的命名規則:結尾一定要有Meta作為識別 __new__方法用來創建JSList類,它接受4個參數 JSList繼承了list類,同時獲得了元類的所有方法 其他 加載內置模塊 利用-m參數,我們可以直接加載Python的模塊
# 搭建http服務器
$ python -m http.server
# 創建虛擬環境
$ python -m venv <name>
# 性能測試
$ python -m cProfile <file.py>
# 查看JSON
$ cat <file.json> | python -m json.tool
數據序列化 import pickle
data = ... # Some Python object
# 存儲
with open ( f '{file}.pickle' , 'wb' ) as f : pickle . dump ( data , f )
# 讀取
with open ( f '{file}.pickle' , 'rb' ) as f : data = pickle . load ( f )
數據分析 利用pandas模塊可以對數據進行分析
$ pip install pandas
>>> import pandas as pd
>>>
data = pd.read_csv
( ...
)
# 數據查看
>>> data.columns
# 查看數據結構
>>> data.describe
() # 簡要數據分析
>>> data.sort_values
( by = ...
) # 對數據排序
# 數據選取
>>> data.head
() # 查看前五條數據
>>> data.iloc
[ n
] # 選擇位置為n的數據,支持切片
>>> data
[ data.A > 0
] # 選擇A欄大于0的數據
>>> data
[ data.B.isin
([ ...
])] # 利用in過濾數據
>>> data
[ ~data.B.isin
([ ...
])] # 上一句的取反,相當于not in
# 缺失值處理
>>> pd.isna
( data
) # 獲取缺失值的布爾標記
>>> data.dropna
( how = 'any' ) # 去除所有含有缺失值的欄
>>> data.fillna
( value = 5
) # 填充所有含有缺失值的欄
# 數據保存(可以相互轉換格式,支持excel、csv和json)
>>> data.to_json
( ...
)
轉載于:https://www.cnblogs.com/yezefei/p/8709039.html
總結
以上是生活随笔 為你收集整理的Pythonic---------详细讲解 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。