Pythonic---------詳細講解

作者:半載流殤
鏈接: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('&lt')
'<'
>>> html.escape('<')
'&lt;'
函數可變參數*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 rreturn 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() :# entertry:yield <value>except Exception as e:# handle_errfinally:# exit

with make_context() as <value>:# handle_value
以下是with語句操作文件的實質由于自定義,函數名用my_open,但功能和open幾乎一樣@contextmanager
def my_open(filename, mode):f = open(filename, mode)try:yield fexcept Exception as e:raise efinally: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 = namedef get_name(self):return self.__namedef 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@propertydef name(self):return self.__name@name.setterdef 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 = agedef __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 typedef 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 selfreturn 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('&lt')
'<'
>>> html.escape('<')
'&lt;'

函數

可變參數

*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 rreturn 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() :# entertry:yield <value>except Exception as e:# handle_errfinally:# exitwith make_context() as <value>:# handle_value

以下是with語句操作文件的實質
由于自定義,函數名用my_open,但功能和open幾乎一樣

@contextmanager
def my_open(filename, mode):f = open(filename, mode)try:yield fexcept Exception as e:raise efinally: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 = namedef get_name(self):return self.__namedef 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@propertydef name(self):return self.__name@name.setterdef 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 = agedef __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 typedef 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 selfreturn 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

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/389923.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/389923.shtml
英文地址,請注明出處:http://en.pswp.cn/news/389923.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

大數據ab 測試_在真實數據上進行AB測試應用程序

大數據ab 測試Hello Everyone!大家好&#xff01; I am back with another article about Data Science. In this article, I will write about what is A-B testing and how to use it on real life data-set to compare two advertisement methods.我回來了另一篇有關數據科…

492. 構造矩形

492. 構造矩形 作為一位web開發者&#xff0c; 懂得怎樣去規劃一個頁面的尺寸是很重要的。 現給定一個具體的矩形頁面面積&#xff0c;你的任務是設計一個長度為 L 和寬度為 W 且滿足以下要求的矩形的頁面。要求&#xff1a; 你設計的矩形頁面必須等于給定的目標面積。 寬度 …

node:爬蟲爬取網頁圖片

前言 周末自己在家閑著沒事&#xff0c;刷著微信&#xff0c;玩著手機&#xff0c;發現自己的微信頭像該換了&#xff0c;就去網上找了一下頭像&#xff0c;看著圖片&#xff0c;自己就想著作為一個碼農&#xff0c;可以把這些圖片都爬取下來做成一個微信小程序&#xff0c;說干…

如何更好的掌握一個知識點_如何成為一個更好的講故事的人3個關鍵點

如何更好的掌握一個知識點You’re launching a digital transformation initiative in the middle of the ongoing pandemic. You are pretty excited about this big-ticket investment, which has the potential to solve remote-work challenges that your organization fac…

centos 搭建jenkins+git+maven

gitmavenjenkins持續集成搭建發布人:[李源] 2017-12-08 04:33:37 一、搭建說明 系統&#xff1a;centos 6.5 jdk&#xff1a;1.8.0_144 jenkins&#xff1a;jenkins-2.93-1.1 git&#xff1a;git-2.9.0 maven&#xff1a;Maven 3.3.9 二、部署 2.1、jdk安裝 1&#xff09;下…

638. 大禮包

638. 大禮包 在 LeetCode 商店中&#xff0c; 有 n 件在售的物品。每件物品都有對應的價格。然而&#xff0c;也有一些大禮包&#xff0c;每個大禮包以優惠的價格捆綁銷售一組物品。 給你一個整數數組 price 表示物品價格&#xff0c;其中 price[i] 是第 i 件物品的價格。另有…

記錄一次spark連接mysql遇到的問題

在使用spark連接mysql的過程中報錯了&#xff0c;錯誤如下 08:51:32.495 [main] ERROR - Error loading factory org.apache.calcite.jdbc.CalciteJdbc41Factory java.lang.NoClassDefFoundError: org/apache/calcite/linq4j/QueryProviderat java.lang.ClassLoader.defineCla…

什么事數據科學_如果您想進入數據科學,則必須知道的7件事

什么事數據科學No way. No freaking way to enter data science any time soon…That is exactly what I thought a year back.沒門。 很快就不會出現進入數據科學的怪異方式 ……這正是我一年前的想法。 A little bit about my data science story: I am a complete beginner…

python基礎03——數據類型string

1. 字符串介紹 在python中&#xff0c;引號中加了引號的字符都被認為是字符串。 1 namejim 2 address"beijing" 3 msg My name is Jim, I am 22 years old! 那單引號、雙引號、多引號有什么區別呢&#xff1f; 1) 單雙引號木有任何區別&#xff0c;部分情況 需要考慮…

Java基礎-基本數據類型

Java中常見的轉義字符: 某些字符前面加上\代表了一些特殊含義: \r :return 表示把光標定位到本行行首. \n :next 表示把光標定位到下一行同樣的位置. 單獨使用在某些平臺上會產生不同的效果.通常這兩個一起使用,即:\r\n. 表示換行. \t :tab鍵,長度上相當于四個或者是八個空格 …

季節性時間序列數據分析_如何指導時間序列數據的探索性數據分析

季節性時間序列數據分析為什么要進行探索性數據分析&#xff1f; (Why Exploratory Data Analysis?) You might have heard that before proceeding with a machine learning problem it is good to do en end-to-end analysis of the data by carrying a proper exploratory …

TortoiseGit上傳項目到GitHub

1. 簡介 gitHub是一個面向開源及私有軟件項目的托管平臺&#xff0c;因為只支持git 作為唯一的版本庫格式進行托管&#xff0c;故名gitHub。 2. 準備 2.1 安裝git&#xff1a;https://git-scm.com/downloads。無腦安裝 2.2 安裝TortoiseGit(小烏龜)&#xff1a;https://torto…

496. 下一個更大元素 I

496. 下一個更大元素 I 給你兩個 沒有重復元素 的數組 nums1 和 nums2 &#xff0c;其中nums1 是 nums2 的子集。 請你找出 nums1 中每個元素在 nums2 中的下一個比其大的值。 nums1 中數字 x 的下一個更大元素是指 x 在 nums2 中對應位置的右邊的第一個比 x 大的元素。如果…

利用PHP擴展Taint找出網站的潛在安全漏洞實踐

一、背景 筆者從接觸計算機后就對網絡安全一直比較感興趣&#xff0c;在做PHP開發后對WEB安全一直比較關注&#xff0c;2016時無意中發現Taint這個擴展&#xff0c;體驗之后發現確實好用&#xff1b;不過當時在查詢相關資料時候發現關注此擴展的人數并不多&#xff1b;最近因為…

美團騎手檢測出虛假定位_在虛假信息活動中檢測協調

美團騎手檢測出虛假定位Coordination is one of the central features of information operations and disinformation campaigns, which can be defined as concerted efforts to target people with false or misleading information, often with some strategic objective (…

869. 重新排序得到 2 的冪

869. 重新排序得到 2 的冪 給定正整數 N &#xff0c;我們按任何順序&#xff08;包括原始順序&#xff09;將數字重新排序&#xff0c;注意其前導數字不能為零。 如果我們可以通過上述方式得到 2 的冪&#xff0c;返回 true&#xff1b;否則&#xff0c;返回 false。 示例 …

org.apache.maven.archiver.MavenArchiver.getManifest

eclipse導入新的maven項目時&#xff0c;pom.xml第一行報錯&#xff1a; org.apache.maven.archiver.MavenArchiver.getManifest(org.apache.maven.project.MavenProject, org.apache.maven.archiver.MavenArchiveConfiguration) 解決辦法&#xff1a; help -> Install New…

殺進程常用命令

殺進程命令pkill 進程名killall 進程名 # 平緩kill -HUP pid # 平緩kill -USR2 pidkill pid &#xff08;-9 不要使用&#xff09;轉載于:https://www.cnblogs.com/jmaly/p/9492406.html

CertUtil.exe被利用來下載惡意軟件

1、前言 經過國外文章信息&#xff0c;CertUtil.exe下載惡意軟件的樣本。 2、實現原理 Windows有一個名為CertUtil的內置程序&#xff0c;可用于在Windows中管理證書。使用此程序可以在Windows中安裝&#xff0c;備份&#xff0c;刪除&#xff0c;管理和執行與證書和證書存儲相…

335. 路徑交叉

335. 路徑交叉 給你一個整數數組 distance 。 從 X-Y 平面上的點 (0,0) 開始&#xff0c;先向北移動 distance[0] 米&#xff0c;然后向西移動 distance[1] 米&#xff0c;向南移動 distance[2] 米&#xff0c;向東移動 distance[3] 米&#xff0c;持續移動。也就是說&#x…