Python怎麼實現鍊式調用
為什麼是鍊式呼叫?
鍊式調用,或者也可以稱為方法鏈(Method Chaining),從字面意思上來說就是將一些列的操作或函數方法像鍊子一樣穿起來的 Code 方式。
我最開始感知鍊式呼叫的「美」,還要從使用 R 語言的管道操作符開始。
library(tidyverse) mtcars %>% group_by(cyl) %>% summarise(meanmeanOfdisp = mean(disp)) %>% ggplot(aes(x=as.factor(cyl), y=meanOfdisp, fill=as.factor(seq(1,3))))+ geom_bar(stat = 'identity') + guides(fill=F)
對 R user 來說,對這一段程式碼很快就能明白整個流程步驟是怎麼樣的。這一切都是透過符號%>%(管道操作符)談起。
透過管道操作符,我們可以將左邊事物傳遞給下一個事物。這裡我將mtcars資料集傳遞到group_by 函數中,然後將得到後的結果再傳遞到summarize函數,最後傳遞到ggplot函數中進行視覺化繪製。
如果我沒有學會鍊式調用,那麼最開始學習R 語言的我一定是這樣寫:
library(tidyverse) cyl4 <p>如果不使用管道操作符,那麼我將會進行不必要的賦值,並且覆蓋原有的資料對象,但其實當中產生的cyl#、data 其實最後都只是為graph 這一張圖片所服務的,因此導致的問題就是程式碼會變得冗餘。 </p><p>鍊式呼叫在極大程度簡潔程式碼的同時,也提高了程式碼的可讀性,能夠很快速地了解到每一步都是在做什麼。這種方式對於做資料分析或處理資料時是十分有用,減少創建不必要的變數時,能夠以快速、簡單的方式進行探索。 </p><p>你能在很多地方看到鍊式呼叫或管道操作的身影,這裡我舉除了 R 語言以外的兩個典型例子。 </p><p>一個是Shell 語句:</p><pre class="brush:php;toolbar:false">echo "`seq 1 100`" | grep -e "^[3-4].*" | tr "3" "*"
在shell 語句中使用「|」管道操作符能夠快速地實現鍊式調用,這裡我首先是列印1-100的所有整數,然後將其傳入到grep方法中,提取由3 或4 開頭的所有部分,然後將這部分傳入到tr 方法中,並對數字包含3 的部分用星號替換。結果如下:
另外一個是Scala 語言:
object Test { def main(args: Array[String]): Unit = { val numOfseq = (1 to 100).toList val chain = numOfseq.filter(_%2==0) .map(_*2) .take(10) } }
在這段範例中,首先numOfseq 這個變數包含了從1-100 的所有整數,然後從chain部分開始,我首先在numOfseq的基礎上呼叫了filter 方法,用以篩選這些數字中為偶數的部分,其次在呼叫map 方法,將這些被篩選出來的數乘以2,最後使用take 方法從新構成的數字中取出前10個數,這些數共同賦值給了chain 變數。
透過以上的敘述,相信你能對鍊式調用有一個初步的印象,但是一旦你掌握了鍊式調用,那麼除了會讓你的程式碼風格有所改變以外,你的程式設計思維也會有不一樣的提升。
Python 中的鍊式呼叫
在Python 中實作一個簡單的鍊式呼叫就是透過建構類別方法並傳回物件本身或傳回歸屬類別(@classmethod )
class Chain: def __init__(self, name): self.name = name def introduce(self): print("hello, my name is %s" % self.name) return self def talk(self): print("Can we make a friend?") return self def greet(self): print("Hey! How are you?") return self if __name__ == '__main__': chain = Chain(name = "jobs") chain.introduce() print("-"*20) chain.introduce().talk() print("-"*20) chain.introduce().talk().greet()
在這裡我們建立一個Chain 類,需要傳遞一個name 字串參數進行實例物件的創建;當中這個類別裡有三個方法,分別是introduce、talk以及greet。
由於每次回傳的是self 自身,那麼我們就可以源源不斷地呼叫物件歸屬類別中的方法,結果如下:
hello, my name is jobs -------------------- hello, my name is jobs Can we make a friend? -------------------- hello, my name is jobs Can we make a friend? Hey! How are you?
在Pandas 中使用鍊式調用
前面鋪墊了這麼多終於談到有關於Pandas 鍊式呼叫部分
Pandas 中的大部分方法都很適合使用鍊式方法進行操作,因為經過API 處理後返回的往往還是Series 類型或DataFrame 類型,所以我們可以直接就調用相應的方法,這裡我以我在今年2 月份左右給別人做案例演示時爬取到的華農兄弟B 站視頻數據為例。可以透過連結進行取得。
數據欄位資訊如下所示,裡面有300 條數據,並且20 個欄位:
欄位資訊
但在使用在這部分資料之前,我們還需要對這部分資料進行初步的清洗,這裡我主要選取了以下欄位:
aid:影片對應的av 號
comment:評論數
play:播放量
title:標題
- created:上傳日期
- length:影片長度##### #####1、資料清洗#########各欄位對應的值如下所示:################欄位值#######從資料中我們可以看到:############ title 欄位前面都會帶有「華農兄弟」四個字,如果對標題字數進行統計時需要預先移除;##### ####### created 上傳日期似乎顯示成了一長串的數值,但其實是從1970 至今的時間戳,我們需要處理成可讀懂的年月日形式;###
length 播放量长度只显示了分秒,但是小时并未用「00」来进行补全,因此这里我们一方面需要将其补全,另一方面要将其转换成对应的时间格式
链式调用操作如下:
import re import pandas as pd # 定义字数统计函数 def word_count(text): return len(re.findall(r"[\u4e00-\u9fa5]", text)) tidy_data = ( pd.read_csv('~/Desktop/huanong.csv') .loc[:, ['aid', 'title', 'created', 'length', 'play', 'comment', 'video_review']] .assign(title = lambda df: df['title'].str.replace("华农兄弟:", ""), title_count = lambda df: df['title'].apply(word_count), created = lambda df: df['created'].pipe(pd.to_datetime, unit='s'), created_date = lambda df: df['created'].dt.date, length = lambda df: "00:" + df['length'], video_length = lambda df: df['length'].pipe(pd.to_timedelta).dt.seconds ) )
这里首先是通过loc方法挑出其中的列,然后调用assign方法来创建新的字段,新的字段其字段名如果和原来的字段相一致,那么就会进行覆盖,从assign中我们可以很清楚地看到当中字段的产生过程,同lambda 表达式进行交互:
1.title 和title_count:
原有的title字段因为属于字符串类型,可以直接很方便的调用str.* 方法来进行处理,这里我就直接调用当中的replace方法将「华农兄弟:」字符进行清洗
基于清洗好的title 字段,再对该字段使用apply方法,该方法传递我们前面实现定义好的字数统计的函数,对每一条记录的标题中,对属于\u4e00到\u9fa5这一区间内的所有 Unicode 中文字符进行提取,并进行长度计算
2.created和created_date:
对原有的created 字段调用一个pipe方法,该方法会将created 字段传递进pd.to_datetime 参数中,这里需要将unit时间单位设置成s秒才能显示出正确的时间,否则仍以 Unix 时间错的样式显示
基于处理好的created 字段,我们可以通过其属于datetime64 的性质来获取其对应的时间,这里 Pandas 给我们提供了一个很方便的 API 方法,通过dt.*来拿到当中的属性值
3.length 和video_length:
原有的length 字段我们直接让字符串00:和该字段进行直接拼接,用以做下一步转换
基于完整的length时间字符串,我们再次调用pipe方法将该字段作为参数隐式传递到pd.to_timedelta方法中转化,然后同理和create_date字段一样获取到相应的属性值,这里我取的是秒数。
2、播放量趋势图
基于前面稍作清洗后得到的tidy_data数据,我们可以快速地做一个播放量走势的探索。这里我们需要用到created这个属于datetime64的字段为 X 轴,播放量play 字段为 Y 轴做可视化展示。
# 播放量走势 %matplotlib inline %config InlineBackend.figure_format = 'retina' import matplotlib.pyplot as plt (tidy_data[['created', 'play']] .set_index('created') .resample('1M') .sum() .plot( kind='line', figsize=(16, 8), title='Video Play Prend(2018-2020)', grid=True, legend=False ) ) plt.xlabel("") plt.ylabel('The Number Of Playing')
这里我们将上传日期和播放量两个选出来后,需要先将created设定为索引,才能接着使用resample重采样的方法进行聚合操作,这里我们以月为统计颗粒度,对每个月播放量进行加总,之后再调用plot 接口实现可视化。
链式调用的一个小技巧就是,可以利用括号作用域连续的特性使整个链式调用的操作不会报错,当然如果不喜欢这种方式也可以手动在每条操作后面追加一个\符号,所以上面的整个操作就会变成这样:
tidy_data[['created', 'play']] \ .set_index('created') \ .resample('1M') .sum() .plot( \ kind='line', \ figsize=(16, 8), \ title='Video Play Prend(2018-2020)', \ grid=True, \ legend=False \ )
但是相比于追加一对括号来说,这种尾部追加\符号的方式并不推荐,也不优雅。
但是如果既没有在括号作用域或未追加\ 符号,那么在运行时 Python 解释器就会报错。
3、链式调用性能
通过前两个案例我们可以看出链式调用可以说是比较优雅且快速地能实现一套数据操作的流程,但是链式调用也会因为不同的写法而存在性能上的差异。
这里我们继续基于前面的tidy_data操作,这里我们基于created_date 来对play、comment和video_review进行求和后的数值进一步以 10 为底作对数化。最后需要得到以下结果:
统计表格
写法一:一般写法
一般写法
这种写法就是基于tidy_data拷贝后进行操作,操作得到的结果会不断地覆盖原有的数据对象
写法二:链式调用写法
链式调用写法
可以看到,链式调用的写法相比于一般写法而言会快上一点,不过由于数据量比较小,因此二者时间的差异并不大;但链式调用由于不需要额外的中间变量已经覆盖写入步骤,在内存开销上会少一些。
结尾:链式调用的优劣
从本文的只言片语中,你能领略到链式调用使得代码在可读性上大大的增强,同时以尽肯能少的代码量去实现更多操作。
当然,链式调用并不算是完美的,它也存在着一定缺陷。比如说当链式调用的方法超过 10 步以上时,那么出错的几率就会大幅度提高,从而造成调试或 Debug 的困难。比如这样:
(data .method1(...) .method2(...) .method3(...) .method4(...) .method5(...) .method6(...) .method7(...) # Something Error .method8(...) .method9(...) .method10(...) .method11(...) )
以上是Python怎麼實現鍊式調用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

MySQL 有免費的社區版和收費的企業版。社區版可免費使用和修改,但支持有限,適合穩定性要求不高、技術能力強的應用。企業版提供全面商業支持,適合需要穩定可靠、高性能數據庫且願意為支持買單的應用。選擇版本時考慮的因素包括應用關鍵性、預算和技術技能。沒有完美的選項,只有最合適的方案,需根據具體情況謹慎選擇。

HadiDB:輕量級、高水平可擴展的Python數據庫HadiDB(hadidb)是一個用Python編寫的輕量級數據庫,具備高度水平的可擴展性。安裝HadiDB使用pip安裝:pipinstallhadidb用戶管理創建用戶:createuser()方法創建一個新用戶。 authentication()方法驗證用戶身份。 fromhadidb.operationimportuseruser_obj=user("admin","admin")user_obj.

直接通過 Navicat 查看 MongoDB 密碼是不可能的,因為它以哈希值形式存儲。取回丟失密碼的方法:1. 重置密碼;2. 檢查配置文件(可能包含哈希值);3. 檢查代碼(可能硬編碼密碼)。

Python在web開發、數據科學、機器學習、自動化和腳本編寫等領域有廣泛應用。 1)在web開發中,Django和Flask框架簡化了開發過程。 2)數據科學和機器學習領域,NumPy、Pandas、Scikit-learn和TensorFlow庫提供了強大支持。 3)自動化和腳本編寫方面,Python適用於自動化測試和系統管理等任務。

MySQL數據庫性能優化指南在資源密集型應用中,MySQL數據庫扮演著至關重要的角色,負責管理海量事務。然而,隨著應用規模的擴大,數據庫性能瓶頸往往成為製約因素。本文將探討一系列行之有效的MySQL性能優化策略,確保您的應用在高負載下依然保持高效響應。我們將結合實際案例,深入講解索引、查詢優化、數據庫設計以及緩存等關鍵技術。 1.數據庫架構設計優化合理的數據庫架構是MySQL性能優化的基石。以下是一些核心原則:選擇合適的數據類型選擇最小的、符合需求的數據類型,既能節省存儲空間,又能提升數據處理速度

2小時內可以學會Python的基本編程概念和技能。 1.學習變量和數據類型,2.掌握控制流(條件語句和循環),3.理解函數的定義和使用,4.通過簡單示例和代碼片段快速上手Python編程。

作為數據專業人員,您需要處理來自各種來源的大量數據。這可能會給數據管理和分析帶來挑戰。幸運的是,兩項 AWS 服務可以提供幫助:AWS Glue 和 Amazon Athena。

否,MySQL 無法直接連接到 SQL Server。但可以使用以下方法實現數據交互:使用中間件:將數據從 MySQL 導出到中間格式,然後通過中間件導入到 SQL Server。使用數據庫鏈接器:商業工具可提供更友好的界面和高級功能,本質上仍通過中間件方式實現。
