Python如何实现链式调用

发布时间:2023-05-16 11:25:00 作者:iii
来源:亿速云 阅读:155

本篇内容介绍了“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 <- mtcars[which(mtcars$cyl==4), ]  cyl6 <- mtcars[which(mtcars$cyl==6), ]  cyl8 <- mtcars[which(mtcars$cyl==8), ]  data <- data.frame(    ccyl = c(4, 6, 8),    meanOfdisp = c(mean(cyl4$disp), mean(cyl6$disp), mean(cyl8$disp))  )  graph <- ggplot(datadata=data, aes(x=factor(cyl), y=meanOfdisp,                                  fill = as.factor(seq(1,3))))   graph <- graph + geom_bar(stat = 'identity') + guides(fill=F)  graph

如果不使用管道操作符,那么我将会进行不必要的赋值,并且覆盖原有的数据对象,但其实当中产生的cyl#、data 其实最后都只是为graph 这一张图片所服务的,因此导致的问题就是代码会变得冗余。

链式调用在极大程度简洁代码的同时,也提高了代码的可读性,能够很快速地了解到每一步都是在做什么。这种方式对于做数据分析或处理数据时是十分有用,减少创建不必要的变量时,能够以快速、简单的方式进行探索。

你能在很多地方见到链式调用或者管道操作的身影,这里我举除了 R 语言以外的两个典型例子。

一个是 Shell 语句:

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 个字段:

Python如何实现链式调用

字段信息

但在使用这部分数据之前,我们还需要对这部分数据进行初步的清洗,这里我主要选取了以下字段:

1、数据清洗

各字段对应的值如下所示:

Python如何实现链式调用

字段值

从数据中我们可以看到:

  1. title 字段前面都会带有「华农兄弟」四个字,如果对标题字数进行统计时需要预先去除;

  2. created 上传日期似乎显示成了一长串的数值,但其实是从 1970 至今的时间戳,我们需要处理成可读懂的年月日形式;

  3. 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:

2.created和created_date:

3.length 和video_length:

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 为底作对数化。最后需要得到以下结果:

Python如何实现链式调用

统计表格

写法一:一般写法

Python如何实现链式调用

一般写法

这种写法就是基于tidy_data拷贝后进行操作,操作得到的结果会不断地覆盖原有的数据对象

写法二:链式调用写法

Python如何实现链式调用

链式调用写法

可以看到,链式调用的写法相比于一般写法而言会快上一点,不过由于数据量比较小,因此二者时间的差异并不大;但链式调用由于不需要额外的中间变量已经覆盖写入步骤,在内存开销上会少一些。

结尾:链式调用的优劣

从本文的只言片语中,你能领略到链式调用使得代码在可读性上大大的增强,同时以尽肯能少的代码量去实现更多操作。

当然,链式调用并不算是完美的,它也存在着一定缺陷。比如说当链式调用的方法超过 10 步以上时,那么出错的几率就会大幅度提高,从而造成调试或 Debug 的困难。比如这样:

(data    .method1(...)    .method2(...)    .method3(...)    .method4(...)    .method5(...)    .method6(...)    .method7(...) # Something Error    .method8(...)    .method9(...)    .method10(...)    .method11(...)  )

“Python如何实现链式调用”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!

推荐阅读:
  1. 如何实现jQuery插件链式调用
  2. 如何实现JavaScript链式调用

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

python

上一篇:基于Python如何实现合并多张图片转成mp4视频

下一篇:Python如何在字典中查找元素

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》