59個Python使用技巧,從此你的Python與眾不同(四)

2021-03-02 愛數據原統計網

- 點擊上方「中國統計網」訂閱我吧!-

有很多老的Python排序代碼,它們在你創建一個自定義的排序時花費你的時間,但在運行時確實能加速執行排序過程。元素排序的最好方法是儘可能使用鍵(key)和默認的sort()排序方法。例如,考慮下面的代碼:

import operatorsomelist = [(1, 5, 8), (6, 2, 4), (9, 7, 5)]somelist.sort(key=operator.itemgetter(0))somelist#Output = [(1, 5, 8), (6, 2, 4), (9, 7, 5)]
somelist.sort(key=operator.itemgetter(1))somelist#Output = [(6, 2, 4), (1, 5, 8), (9, 7, 5)]
somelist.sort(key=operator.itemgetter(2))somelist

每一個實例中,根據你選擇的作為key參數部分的索引,數組進行了排序。類似於利用數字進行排序,這種方法同樣適用於利用字符串排序。

每種程式語言都會強調需要優化循環。當使用Python的時候,你可以依靠大量的技巧使得循環運行得更快。然而,開發者經常漏掉的一個方法是:避免在一個循環中使用點操作。例如,考慮下面的代碼:

lowerlist = ['this', 'is', 'lowercase']upper = str.upperupperlist = []append = upperlist.appendfor word in lowerlist:append(upper(word))print(upperlist)#Output = ['THIS', 'IS', 'LOWERCASE']

每一次你調用方法str.upper,Python都會求該方法的值。然而,如果你用一個變量代替求得的值,值就變成了已知的,Python就可以更快地執行任務。優化循環的關鍵,是要減少Python在循環內部執行的工作量,因為Python原生的解釋器在那種情況下,真的會減緩執行的速度。

(注意:優化循環的方法有很多,這只是其中的一個。例如,許多程式設計師都會說,列表推導是在循環中提高執行速度的最好方式。這裡的關鍵是,優化循環是程序取得更高的執行速度的更好方式之一。)

如果每次你創建一個應用程式都是用相同的編碼方法,幾乎肯定會導致一些你的應用程式比它能夠達到的運行效率慢的情況。作為分析過程的一部分,你可以嘗試一些實驗。例如,在一個字典中管理一些元素,你可以採用安全的方法確定元素是否已經存在並更新,或者你可以直接添加元素,然後作為異常處理該元素不存在情況。考慮第一個編碼的例子:

n = 16myDict = {}for i in range(0, n):char = 'abcd'[i%4]if char not in myDict:myDict[char] = 0myDict[char] += 1print(myDict)

這段代碼通常會在myDict開始為空時運行得更快。然而,當mydict通常被數據填充(或者至少大部分被充填)時,另一種方法效果更好。

n = 16myDict = {}for i in range(0, n):char = 'abcd'[i%4]try:myDict[char] += 1except KeyError:myDict[char] = 1print(myDict)

兩種情況下具有相同的輸出:{『d』: 4, 『c』: 4, 『b』: 4, 『a』: 4}。唯一的不同是這個輸出是如何得到的。跳出固定的思維模式,創造新的編碼技巧,能夠幫助你利用你的應用程式獲得更快的結果。

一個列表推導式包含以下幾個部分:

num = [1, 4, -5, 10, -7, 2, 3, -1]filtered_and_squared = []
for number in num:if number > 0:filtered_and_squared.append(number ** 2)print filtered_and_squared
# [1, 16, 100, 4, 9]

而如果使用filter、lambda和map函數,則能夠將代碼大大簡化:

num = [1, 4, -5, 10, -7, 2, 3, -1]filtered_and_squared = map(lambda x: x ** 2, filter(lambda x: x > 0, num))print filtered_and_squared



num = [1, 4, -5, 10, -7, 2, 3, -1]filtered_and_squared = [ x**2 for x in num if x > 0]print filtered_and_squared

列表推導也可能會有一些負面效應,那就是整個列表必須一次性加載於內存之中,這對上面舉的例子而言不是問題,甚至擴大若干倍之後也都不是問題。但是總會達到極限,內存總會被用完。

針對上面的問題,生成器(Generator)能夠很好的解決。生成器表達式不會一次將整個列表加載到內存之中,而是生成一個生成器對象(Generator objector),所以一次只加載一個列表元素。

生成器表達式同列表推導式有著幾乎相同的語法結構,區別在於生成器表達式是被圓括號包圍,而不是方括號:

num = [1, 4, -5, 10, -7, 2, 3, -1]filtered_and_squared = ( x**2 for x in num if x > 0 )print filtered_and_squared


for item in filtered_and_squared:print item

這比列表推導效率稍微提高一些,讓我們再一次改造一下代碼:

num = [1, 4, -5, 10, -7, 2, 3, -1]
def square_generator(optional_parameter):return (x ** 2 for x in num if x > optional_parameter)
print square_generator(0)


for k in square_generator(0):print k


g = list(square_generator(0))print g

除非特殊的原因,應該經常在代碼中使用生成器表達式。但除非是面對非常大的列表,否則是不會看出明顯區別的。再來看一個通過兩階列表推導式遍歷目錄的例子:

import osdef tree(top):for path, names, fnames in os.walk(top):for fname in fnames:yield os.path.join(path, fname)
for name in tree('C:\Users\XXX\Downloads\Test'):print name

裝飾器為我們提供了一個增加已有函數或類的功能的有效方法。聽起來是不是很像Java中的面向切面編程(Aspect-Oriented Programming)概念?兩者都很簡單,並且裝飾器有著更為強大的功能。舉個例子,假定你希望在一個函數的入口和退出點做一些特別的操作(比如一些安全、追蹤以及鎖定等操作)就可以使用裝飾器。

裝飾器是一個包裝了另一個函數的特殊函數:主函數被調用,並且其返回值將會被傳給裝飾器,接下來裝飾器將返回一個包裝了主函數的替代函數,程序的其他部分看到的將是這個包裝函數。

import timefrom functools import wraps
def timethis(func):''' Decorator that reports the execution time. '''@wraps(func)def wrapper(*args, **kwargs):start = time.time()result = func(*args, **kwargs)end = time.time()print(func.__name__, end-start)return resultreturn wrapper
@timethisdef countdown(n):while n > 0:n -= 1
countdown(100000)

contextlib模塊包含了與上下文管理器和with聲明相關的工具。通常如果你想寫一個上下文管理器,則你需要定義一個類包含__enter__方法以及__exit__方法,例如:

import timeclass demo:def __init__(self, label):self.label = label
def __enter__(self):self.start = time.time()
def __exit__(self, exc_ty, exc_val, exc_tb):end = time.time()print('{}: {}'.format(self.label, end - self.start))

完整的例子在此:

import time
class demo:def __init__(self, label):self.label = label
def __enter__(self):self.start = time.time()
def __exit__(self, exc_ty, exc_val, exc_tb):end = time.time()print('{}: {}'.format(self.label, end - self.start))
with demo('counting'):n = 10000000while n > 0:n -= 1

上下文管理器被with聲明所激活,這個API涉及到兩個方法。

1. __enter__方法,當執行流進入with代碼塊時,__enter__方法將執行。並且它將返回一個可供上下文使用的對象。

2. 當執行流離開with代碼塊時,__exit__方法被調用,它將清理被使用的資源。

利用@contextmanager裝飾器改寫上面那個例子:

from contextlib import contextmanagerimport time
@contextmanagerdef demo(label):start = time.time()try:yieldfinally:end = time.time()print('{}: {}'.format(label, end - start))
with demo('counting'):n = 10000000while n > 0:n -= 1

看上面這個例子,函數中yield之前的所有代碼都類似於上下文管理器中__enter__方法的內容。而yield之後的所有代碼都如__exit__方法的內容。如果執行過程中發生了異常,則會在yield語句觸發。

描述器決定了對象屬性是如何被訪問的。描述器的作用是定製當你想引用一個屬性時所發生的操作。

構建描述器的方法是至少定義以下三個方法中的一個。需要注意,下文中的instance是包含被訪問屬性的對象實例,而owner則是被描述器修辭的類。

get(self, instance, owner) – 這個方法是當屬性被通過(value = obj.attr)的方式獲取時調用,這個方法的返回值將被賦給請求此屬性值的代碼部分。set(self, instance, value) – 這個方法是當希望設置屬性的值(obj.attr = 『value』)時被調用,該方法不會返回任何值。delete(self, instance) – 當從一個對象中刪除一個屬性時(del obj.attr),調用此方法。譯者註:對於instance和owner的理解,考慮以下代碼:

class Celsius(object):def __init__(self, value=0.0):self.value = float(value)def __get__(self, instance, owner):return self.valuedef __set__(self, instance, value):self.value = float(value)
class Temperature(object):celsius = Celsius()
temp=Temperature()temp.celsius

38. Zipping and unzipping lists and iterables
>>> a = [1, 2, 3]>>> b = ['a', 'b', 'c']>>> z = zip(a, b)>>> z[(1, 'a'), (2, 'b'), (3, 'c')]>>> zip(*z)[(1, 2, 3), ('a', 'b', 'c')]

39. Grouping adjacent list items using zip
>>> a = [1, 2, 3, 4, 5, 6]
>>>
>>> group_adjacent = lambda a, k: zip(*([iter(a)] * k))>>> group_adjacent(a, 3)[(1, 2, 3), (4, 5, 6)]>>> group_adjacent(a, 2)[(1, 2), (3, 4), (5, 6)]>>> group_adjacent(a, 1)[(1,), (2,), (3,), (4,), (5,), (6,)]

>>>
>>> from itertools import islice>>> group_adjacent = lambda a, k: zip(*(islice(a, i, None, k) for i in range(k)))>>> group_adjacent(a, 3)[(1, 2, 3), (4, 5, 6)]>>> group_adjacent(a, 2)[(1, 2), (3, 4), (5, 6)]>>> group_adjacent(a, 1)[(1,), (2,), (3,), (4,), (5,), (6,)]

40. Sliding windows (n-grams) using zip and iterators
>>> from itertools import islice>>> def n_grams(a, n):... z = (islice(a, i, None) for i in range(n))... return zip(*z)...>>> a = [1, 2, 3, 4, 5, 6]>>> n_grams(a, 3)[(1, 2, 3), (2, 3, 4), (3, 4, 5), (4, 5, 6)]>>> n_grams(a, 2)[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]>>> n_grams(a, 4)[(1, 2, 3, 4), (2, 3, 4, 5), (3, 4, 5, 6)]

深圳線下·愛數據社區

課程主題:「如何面試數據分析崗位」

本次活動時間:1月18日 星期六 13:00-17:00

講師介紹:王老師,網際網路公司高級數據分析師,多年數據分析業務經驗,具有豐富的經營分析、用戶消費行為分析等項目經歷。

點擊原文,就分你一個小魚乾

相關焦點

  • Python2 已終結,入手Python 3,你需要這30個技巧
    這篇教程有 30 個你會喜歡的方法。勤勞的程式設計師們,這裡有 30 條使用 Python 時實用的建議和小技巧。你可以把讀這篇文章當做工作間隙的小憩,而且我保證你學到的東西會跟工作時一樣多。1.它的工作機制是這樣的這種方式在返回值的數量很少時是可以的,但是如果返回值超過 3 個,那它們就該被放到一個(數據)類中了。7. 使用數據類Python 從 3.7 開始提供數據類功能。
  • 10 個 Python 字符串處理技巧
    那麼可以通過這個字符串處理入門教程,來了解一下利用Python處理字符串的一些基本操作。當前,自然語言處理和文本分析是研究和應用的熱點領域。這些領域包括各種具體的技能和概念,在深入具體實踐之前需要對它們有徹底的理解,為此,必須掌握一些基本的字符串操作和處理技巧。在我看來,必須掌握兩種字符串處理技巧:首先是正則表達式,一種基於模式的文本匹配方法。
  • 零基礎學python,你需要掌握這8個技巧!
    作為這幾年火爆的python,想要零基礎起步學習,興趣愛好是首要的,什麼語言都是入門簡單,精通難。相比java,c等語言來說python極其容易入門,但是簡單的語法也正是它的缺點,靈活導致很多bug在運行過程中才能發現,導致多人協同上很難保證統一的風格。
  • 掌握這10個python技巧,讓你代碼工作如魚得水!
    福布斯最新發布的一篇報告指出,python的使用量在去年增長了456%。Netfix、IBM以及其它數以百計的公司都在使用python。包括Dropbox也是由python創建的。Dice的研究表明,python是世界上最熱門的技巧之一,根據程式語言的流行度指數來看,python同時也是最受歡迎的程式語言。Python為何有如此大的魅力呢?
  • 零基礎學Python--你應知道的30個小技巧
    可以說Python的技巧是非常的令人愉悅的,比如說,如下這種賦值方式。大家可以猜測一下結果是什麼,然後實際去運行一下。a,*b,c=[1,2,3,4,5]四、列表中負的下標索引方式。這種方式給我們的編程真的是給了諸多便利,和C語言的負的下標不一樣,Python將列表的首尾連接起來了,而C語言的負數下標則是按照內存的地址的偏移。
  • 讓所有程式設計師絕不能錯過的59個Python庫總結!
    Python有以下三個特點:易用性和靈活性全行業高接受度:Python無疑是業界最流行的數據科學語言用於數據科學的Python庫的豐富數量優勢本文介紹了python人最常用的59個python庫。一起來看看吧~用於數據收集的Python庫1.
  • 【Python 第51課】 and-or技巧
  • Python安裝教程和使用技巧
    window系統中,python有多種開發工具,例如1.直接在cmd命令窗口執行,但此種僅能單條語句執行,不能運行完整的程序。2.python自帶的集成開發環境,可通過開始——所有程序——python3.3——IDLE(Python GUI)啟動。3.其他集成開發環境,如PythonWin等,有編輯和調試能力,還實現了MFC類庫存的包裝。使用python自帶的開發環境。
  • 【Python基礎】python使用python-docx操作word
    1、python-docx庫介紹該模塊兒可以創建、修改Word(.docx)文件;python-docx使用官網:python-docx官網我們在安裝此模塊兒使用的是pip install python-docx,但是在導入的時候是import docx;2、Python讀取Word文檔內容注意:每進行一個操作,必須保存一下,否則等於白做;1)word文檔結構介紹在這裡插入圖片描述2)python-docx
  • Python安裝篇
    【畫朵玫瑰花送給TA】在某一天,送給TA一朵與眾不同的玫瑰花,從此以後你就可以盡情虐狗了!向青春致敬、向愛情致敬,向Python致敬!你可以通過終端窗口輸入 "python" 命令來查看本地是否已經安裝Python以及Python的安裝版本。Unix (Solaris, Linux, FreeBSD, AIX, HP/UX, SunOS, IRIX, 等等。)
  • 5年 Python 功力,總結了 10 個開發技巧
    如果你想自己控制這個上下文,可以加個 from 關鍵字(from 語法會有個限制,就是第二個表達式必須是另一個異常類或實例。)來表明你的新異常是直接由哪個異常引起的。不管你在哪個地方導致程序崩潰,都會執行那些你註冊過的函數。示例如下:如果clean()函數有參數,那麼你可以不用裝飾器,而是直接調用atexit.register(clean_1, 參數1, 參數2, 參數3='xxx')。可能你有其他方法可以處理這種需求,但肯定比上不使用 atexit 來得優雅,來得方便,並且它很容易擴展。
  • 秘籍:10個Python字符串處理技巧(附代碼)
    首先,應了解最基本的基礎知識,下面,來了解一下這些初學者的技巧。注意,有實際意義的文本分析遠遠超出字符串處理的範疇,那些更先進的核心技術可能不需要你頻繁的親自對文本進行操作。然而,對於一個成功的文本分析項目來說,文本數據預處理是非常重要而耗時的環節,所以,本文涵蓋的字符串處理技能將很有價值。在基礎層面上理解文本的計算處理對於理解更為先進的文本分析技術同樣重要。
  • 5個助你效率提升的python小技巧
    使用交互模式使用python -i xxxx.py可以直接進入python的交互模式,可以很方便的調用xxxx.py中定義的方法和函數,特別適合調試沒有main()方法的文件,強力推薦。使用pdb進行調試很多從c++/java轉到python的同學可能對python沒有斷點功能相當失望。
  • python+ pycharm 環境安裝 + pycharm使用
    >①一定要勾選「Add Python to Path」,要不然要手動添加環境變量②點擊「Customize installation」7.然後就一直點擊下一步,進入選擇安裝路徑,這裡我們最好不要安裝在C盤,你開心就好8.確認python是否安裝成功:在cmd中輸入
  • 獨家 | 秘籍:10個Python字符串處理技巧(附代碼)
    首先,應了解最基本的基礎知識,下面,來了解一下這些初學者的技巧。注意,有實際意義的文本分析遠遠超出字符串處理的範疇,那些更先進的核心技術可能不需要你頻繁的親自對文本進行操作。然而,對於一個成功的文本分析項目來說,文本數據預處理是非常重要而耗時的環節,所以,本文涵蓋的字符串處理技能將很有價值。在基礎層面上理解文本的計算處理對於理解更為先進的文本分析技術同樣重要。
  • 每個python人都離不開的12個python庫
    如果說python能取得今天的成就,一方面是它簡介的語法,更重要的一方面就是它豐富的第三方庫,可以毫不誇張的說,只要你能想到的任何一個功能模塊,都有對應的python庫,可以說正是因為有了豐富的python庫,python才發展得如此迅速,下面我們來看看python人最常用的20個python
  • Python代碼技巧,你值得擁有!
    第一個命令pydoc sys.exit查看sys模塊的exit函數文檔信息,第二個命令pydoc sorted查看了內建函數sorted的文檔信息。如何將python代碼打包成獨立的二進位文件需要編譯的python代碼如下:#!/usr/bin/env python# -*- coding: utf-8 -*-print 'hello, world!'將python代碼打包成獨立的二進位文件步驟:
  • 一步步教你開始使用Python開發Web應用
    對於初學者,Python 2和Python 3最大的不同很可能就是Python 2使用print不需要加括號,而Python 3需要,但就這麼多。  1. Codecademy python課程  Codecademy做了一項偉大的工作,將python的課程放在了一起,這對於初學者快速入門Python非常有用。
  • python那些實用且不為人知的技巧
    python技巧同步滾動:開    雖然使用python很多年,但是有些方法,還是沒有掌握;最近仔細閱讀了一本書
  • 利用 Python,四步掌握機器學習
    相對於R 只用於處理數據,使用例如機器學習、統計算法和漂亮的繪圖分析數據, Pthon 的優勢在於它適用於許多其他的問題。因為 Python 擁有更廣闊的分布(使用 Jango 託管網站,自然語言處理 NLP,訪問 Twitter、Linkedin 等網站的 API),同時類似於更多的傳統語言,比如 C python 就比較流行。