精华内容
下载资源
问答
  • 用过jquery的一般都知道在jquery中可以链式调用,代码简洁优雅。比如$(“a”).addClass(“test”).show().html(“foo”);。在redis-py中的pipeline中也可以链式调用,比如pipe.set(‘foo‘, ‘bar‘).sadd(‘faz‘, ...

    用过jquery的一般都知道在jquery中可以链式调用,代码简洁优雅。比如$(“a”).addClass(“test”).show().html(“foo”);。

    在redis-py中的pipeline中也可以链式调用,比如pipe.set(‘foo‘, ‘bar‘).sadd(‘faz‘, ‘baz‘).incr(‘auto_number‘).execute() 。

    那么究竟怎么实现的呢?

    很简单,返回对象自己就行了,即return self.

    废话不多说,上代码。

    class Person:

    def name(self, name):

    self.name = name

    return self

    def age(self, age):

    self.age = age

    return self

    def show(self):

    print "My name is", self.name, "and I am", self.age, "years old."

    p = Person()

    p.name("Li Lei").age(15).show()

    原文:http://blog.csdn.net/handsomekang/article/details/39832651

    展开全文
  • 如果你是有打算从事有关数据分析或者数据挖掘的等数据科学领域的工作,或者和我一样目前就是从事相关领域的工作,那么「链式调用」对我们而言是一门必修课。为什么是链式调用链式调用,或者也可以称为方法链...

    如果你是有打算从事有关数据分析或者数据挖掘的等数据科学领域的工作,或者和我一样目前就是从事相关领域的工作,那么「链式调用」对我们而言是一门必修课。

    为什么是链式调用?

    链式调用,或者也可以称为方法链(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 

    cyl6 

    cyl8 

    data 

    ccyl= c(4, 6, 8),

    meanOfdisp=c(mean(cyl4$disp), mean(cyl6$disp), mean(cyl8$disp))

    )

    graph 

    fill=as.factor(seq(1,3))))

    graph 

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

    字段信息

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

    aid:视频对应的 av 号

    comment:评论数

    play:播放量

    title:标题

    video_review:弹幕数

    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=lambdadf: df['title'].str.replace("华农兄弟:", ""),

    title_count=lambdadf: df['title'].apply(word_count),

    created=lambdadf: df['created'].pipe(pd.to_datetime,unit='s'),

    created_date=lambdadf: df['created'].dt.date,

    length=lambdadf: "00:" + df['length'],

    video_length=lambdadf: 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(...)

    )

    你只能从链式调用方法体中「从尾倒头」一步一步地去重现发生问题的地方在哪。

    因此使用链式调用时,一定必须要考虑以下问题:

    是否需要中间变量

    操作数据中的步骤是否需要分解

    每次操作后的结果是否仍为 DataFrame 类型

    如果不需要中间变量、步骤不需要分解且保证最后返回的就是 DataFrame 类型,那么就愉快地使用链式调用方法来完成你的数据流程吧!

    【责任编辑:庞桂玉 TEL:(010)68476606】

    点赞 0

    展开全文
  • 一日一技:在Python里面实现链式调用我们在使用Django的models查询数据库时,可以看到有这种写法:form app.models import XXXquery = XXX.objects.all()query = query.filter(name=123, age=456).filter(salary=999...

    一日一技:在Python里面实现链式调用

    我们在使用Django的models查询数据库时,可以看到有这种写法:

    form app.models import XXX

    query = XXX.objects.all()

    query = query.filter(name=123, age=456).filter(salary=999)

    在这种写法里面,query对象有一个 filter方法,这个方法的返回数据还可以继续调用 filter方法,可以这样无限制地调用下去。

    这种写法是怎么实现的呢?

    如果我们直接写一个类的方法,看看能不能这样调用:

    class Query:

    def filter(self):

    pass

    query = Query()

    query.filter().filter()

    直接对 query.filter()返回的结果再调用一次 filter,就会导致报错了。这是因为在没有显式写return语句的时候,方法会返回 None,而None对象是没有所谓的 filter方法的。

    那么什么东西有 filter方法呢?显然我们的query对象有 filter方法。那么如何让这个方法返回自身这个对象呢?

    这个时候,我们就要看看我们在定义类方法的时候,总会写的的第一个参数 self了。几乎每个类方法里面都会有它。大家只知道在类里面调用类方法的时候可以用 self.xxx(),在调用类属性的时候可以用 self.yy,那么有没有思考过,这个东西如果单独使用会怎么样呢?

    实际上, self指的就是这个类实例化成一个对象以后,这个对象自身。而这个对象显然是有 filter方法的。所以我们修改一下 filter方法,让它返回 self:

    class Query:

    def filter(self):

    return self

    query = Query()

    query.filter().filter()

    从图中可以看出,现在已经不会报错了。那么回到最开始的问题,Django里面的链式调用传入查询参数是如何实现的呢?

    实际上这里涉及到一个 惰性查询的问题。

    当我们不停调用 .filter()方法的时候,Django会把这些查询条件全部缓存起来,只有当我们需要获取结果,或者查询满足条件的数据有多少条时,它才会真正地连接数据库去查询。

    所以我们这里要模拟这个环境,把查询条件缓存起来。

    那么为了获取调用方法时传入的参数名,我们就要使用 **kwargs参数。这个参数可以接受所有的key=value形式的参数:

    class Query():

    def __init__(self):

    self.query_condition = {}

    def filter(self, **kwargs):

    self.query_condition.update(kwargs)

    return self

    query = Query()

    a = query.filter(name='kingname').filter(age__gt=15, address='yyyyyy').filter(salary=99999)

    print(query.query_condition)

    运行效果如下图所示:

    在真正需要输出结果的时候,再使用这些缓存的条件,去数据库中查询结果即可。

    kingname

    攒钱给产品经理买房。

    展开全文
  • 答案在标题,链式调用。我们仿照C#LINQ的链式接口。直接上代码,这分代码是我自己写的,很简单。有兴趣可以自己研究。里面封装了我觉得比较重要的几个高阶函数。如果不够的话也可以简单地再封装一下。如下,#文件...

    上一篇文章中我们发现我们的代码越来越长了,而且都挤在一行,代码越长,越不易读。括号一层嵌一层,真的容易绕晕。我一直觉得代码要写给人看,一直追求代码即注释这种程度的简单。

    那有什么办法来简化这个问题?答案在标题,链式调用。我们仿照C#LINQ的链式接口。直接上代码,这分代码是我自己写的,很简单。有兴趣可以自己研究。里面封装了我觉得比较重要的几个高阶函数。如果不够的话也可以简单地再封装一下。如下,

    #文件名FT.py

    from functools import reduce

    from collections import Iterator

    from itertools import chain,groupby,product

    class From:

    src=None

    def __init__(self,src):

    self.src=src

    def toList(self):

    return list(self.src)

    def toSet(self):

    return set(self.src)

    def toTuple(self):

    return tuple(self.src)

    def getSource(self):

    return self.src

    def map(self,func):

    return From(map(func,self.src))

    def filter(self,predicate):

    return From(filter(predicate,self.src))

    def reduce(self,func,identity=None):

    if identity is None:

    return reduce(func,self.src)

    else:

    return reduce(func,self.src,identity)

    def chain(self):

    return From(chain.from_iterable(self.src))

    def groupby(self,func=None):

    return From(map(lambda it:(it[0],list(it[1])),groupby(self.src,func)))

    def product(self,tag):

    return From(product(self.src,tag))

    def all(self,predicate):

    return all(map(lambda it:predicate(it),self.src))

    def any(self,predicate):

    return any(map(lambda it:predicate(it),self.src))

    def first(self,predicate=None):

    if predicate is None:

    if isinstance(self.src,Iterator):

    return next(self.src)

    return next(iter(self.src))

    else :

    return next(filter(predicate,self.src))

    def firstOrNone(self,predicate=None):

    try:

    if predicate is None:

    if isinstance(self.src,Iterator):

    return next(self.src)

    return next(iter(self.src))

    else :

    return next(filter(predicate,self.src))

    except StopIteration:

    return None

    以上代码我写了一个From类,后面的代码会反反复复地用到这个类。

    复习map/filter/reduce

    例子1 ,过滤出列表中的偶数,再乘2

    from FT import From

    print(From((1,2,3,4))

    .filter(lambda it:it % 2==0)

    .map(lambda it:it*2).toList())

    '''

    结果:

    [4,8]

    '''

    例子2,过滤出列表中地偶数,结果乘2,最后再求和。

    from FT import From

    print(From((1,2,3,4))

    .filter(lambda it:it % 2==0)

    .map(lambda it:it*2).reduce(lambda acc,it:acc+it))

    #加幺元

    print(From((1,2,3,4))

    .filter(lambda it:it % 2==0)

    .map(lambda it:it*2).reduce(lambda acc,it:acc+it))

    '''

    结果:

    12

    12

    '''

    对比上篇文章,有没有觉得清晰很多,清晰地看到数据流一步一步地往下一个函数流。这个也是函数式地特点之一。python本不提供这个流式接口,没关系,我们自己造一个,而且没有花几行代码。居然全部代码都能在一篇文章中显示出来,不过这个跟python自己动态语言有关,若换成静态语言的话那应该要花多不少功夫。下次找机会我用C++实现一遍。

    下面我们学多几个高阶函数,丰富我们的武器库。

    groupby

    分组是一个很常见的需求,需要的代码其实也不少,封装成高阶函数后那方便太多了。请看下面的例子

    testgroupdata=[{"id":1,"name":"wwb"},{"id":1,"name":"wxa"},{"id":1,"name":"wxb"},{"id":2,"name":"wxc"},{"id":2,"name":"wxd"}]

    这个是数据集。是我随便造的,没什么特殊意义。

    例子1,根据id分组,显示分组

    print(From(testgroupdata).groupby(lambda it:it['id']).toList())

    '''

    结果:

    [

    (

    1,

    [

    {

    'id': 1,

    'name': 'wwb'

    },

    {

    'id': 1,

    'name': 'wxa'

    },

    {

    'id': 1,

    'name': 'wxb'

    }

    ]

    ),

    (

    2,

    [

    {

    'id': 2,

    'name': 'wxc'

    },

    {

    'id': 2,

    'name': 'wxd'

    }

    ]

    )

    ]

    '''

    当然groupby后可以自己接其他高阶函数,如下例子

    例子2,根据id分组后,过滤出分组的KEY为偶数的数据,也就是id为偶数的数据

    print(From(testgroupdata).groupby(lambda it:it['id']).filter(lambda it:it[0]%2==0).toList())

    '''

    结果:

    [

    (

    2,

    [

    {

    'id': 2,

    'name': 'wxc'

    },

    {

    'id': 2,

    'name': 'wxd'

    }

    ]

    )

    ]

    '''

    笛卡尔积

    笛卡儿积太重要了,数据库两种表连接或join都可以解释为笛卡儿积,看下面的例子。

    例子1,观察执行结果

    print(From((1,2,3)).product(('a','b','c')).toList())

    现在我们考虑一个图书馆管理系统,先观察以下数据集

    students = [

    {

    "name":"wwb",

    "book":[1,2,5]

    },

    {

    "name":"wxa",

    "book":[1,2,3]

    },

    {

    "name":"wxb",

    "book":[2,3,4]

    }

    ]

    books = [

    {

    "id":1,

    "name":"C++ Primer"

    },

    {

    "id":2,

    "name":"Effecitve C++"

    },

    {

    "id":3,

    "name":"语文"

    },{

    "id":4,

    "name":"数学"

    },

    {

    "id":5,

    "name":"英语"

    }

    ]

    students是图书馆借了数的同学,一个人可以借多本书,其中book记录的是图书的id;books是图书馆里面的书。现在可以看例子了。

    例子2,求学生具体借了什么书

    print(From(students).map(lambda s:

    {

    "name":s["name"],

    "book":From(s["book"]).product(books).filter(lambda it:it[0]==it[1]["id"])

    .map(lambda it:it[1]["name"]).toList()

    }).toList())

    '''

    结果:

    [

    {

    'name': 'wwb',

    'book': [

    'C++ Primer',

    'Effecitve C++',

    '英语'

    ]

    },

    {

    'name': 'wxa',

    'book': [

    'C++ Primer',

    'Effecitve C++',

    '语文'

    ]

    },

    {

    'name': 'wxb',

    'book': [

    'Effecitve C++',

    '语文',

    '数学'

    ]

    }

    ]

    '''

    first/firstOrNone

    这两个函数简单,就是找出符合条件的第一条数据。我常常需要这样的需求。直接看例子

    #找出名字为wwb的同学,找不到的话则会抛出异常

    print(From(students).first(lambda it:it["name"]=="wwb"))

    #找出名字为wxx的同学,找不到的话返回None

    print(From(students).firstOrNone(lambda it:it["name"]=="wxx"))

    '''

    结果:

    {'name': 'wwb', 'book': [1, 2, 5]}

    None

    '''

    first当找不到满足条件的数据会抛异常,而firstOrNone则会返回None。很简单。

    chain

    今天解释最后一个函数,chain。这个是一个非常重要的函数。我自己经常叫它扁平,用来变平数据。如

    ((a,b,c),(d,e,f),(g,h,i)) => (a,b,c,d,e,f,g,h,i)经过chain后,你会发现括号少了一层,原来'尖'的数据现在变'平'了,因为少了一层括号。看例子

    print(From(((1,2,3),(4,5,6),(1,2))).chain().toList())

    '''

    结果:

    [1, 2, 3, 4, 5, 6, 1, 2]

    '''

    回到上一篇文章统计选修数学的同学的平均分。数据集如下

    students = [

    {

    "name":"wwb",

    "sex":"1",

    "course":[

    {

    "name":"Math",

    "score":90

    },

    {

    "name":"English",

    "score":80

    }

    ]

    },

    {

    "name":"wxa",

    "sex":"1",

    "course":[

    {

    "name":"Music",

    "score":90

    },

    {

    "name":"English",

    "score":80

    }

    ]

    },

    {

    "name":"wxb",

    "sex":"1",

    "course":[

    {

    "name":"Math",

    "score":92

    },

    {

    "name":"Music",

    "score":80

    }

    ]

    },

    ]

    求选修数学同学的平均分

    studentmaths = From(students).map(lambda s: From(s["course"]).map(lambda c:

    {

    "name":s["name"],

    "sex":s["sex"],

    "course":c["name"],

    "score":c["score"]

    }).toList()).chain().filter(lambda it:it["course"]=="Math").toList()

    #先打印出来看看

    print(From(studentmaths).reduce(lambda acc,s:acc+s["score"],0)/len(studentmaths))

    '''

    结果:

    [{'score': 90, 'name': 'wwb', 'sex': '1', 'course': 'Math'}, {'score': 92, 'name': 'wxb', 'sex': '1', 'course': 'Math'}]

    91.0

    '''

    总结

    高阶函数和链式调用终于讲完了,有没有发现这些例子都好简洁,基本上多复杂的需求都只用一条链子,一直连击。而且不失可读性。高阶函数需要练习才会熟悉,像sql语句一样,既简单又复杂。预告下篇文章讲组合,就用我一年前写的玩具模板引擎为例子,200行左右。

    测试代码

    同样我自己把测试代码贴出来吧,当然需要和文章开篇的FT.py放在一起才可以执行。

    from FT import From

    print(From((1,2,3,4))

    .filter(lambda it:it % 2==0)

    .map(lambda it:it*2).toList())

    print(From((1,2,3,4))

    .filter(lambda it:it % 2==0)

    .map(lambda it:it*2).reduce(lambda acc,it:acc+it))

    print(From((1,2,3,4))

    .filter(lambda it:it % 2==0)

    .map(lambda it:it*2).reduce(lambda acc,it:acc+it,0))

    testgroupdata=[{"id":1,"name":"wwb"},{"id":1,"name":"wxa"},{"id":1,"name":"wxb"},{"id":2,"name":"wxc"},{"id":2,"name":"wxd"}]

    print(From(testgroupdata).groupby(lambda it:it['id']).toList())

    print(From(testgroupdata).groupby(lambda it:it['id']).filter(lambda it:it[0]%2==0).toList())

    #笛卡尔积

    print(From((1,2,3)).product(('a','b','c')).toList())

    students = [

    {

    "name":"wwb",

    "book":[1,2,5]

    },

    {

    "name":"wxa",

    "book":[1,2,3]

    },

    {

    "name":"wxb",

    "book":[2,3,4]

    }

    ]

    books = [

    {

    "id":1,

    "name":"C++ Primer"

    },

    {

    "id":2,

    "name":"Effecitve C++"

    },

    {

    "id":3,

    "name":"语文"

    },{

    "id":4,

    "name":"数学"

    },

    {

    "id":5,

    "name":"英语"

    }

    ]

    print(From(students).map(lambda s:

    {

    "name":s["name"],

    "book":From(s["book"]).product(books).filter(lambda it:it[0]==it[1]["id"])

    .map(lambda it:it[1]["name"]).toList()

    }).toList())

    #只找一个

    print(From(students).first(lambda it:it["name"]=="wwb"))

    print(From(students).firstOrNone(lambda it:it["name"]=="wxx"))

    #chain是一个很重要的函数

    # 目的 ((a,b,c),(d,e,f),(g,h,i)) => (a,b,c,d,e,f,g,h,i),去掉一层括号

    print(From(((1,2,3),(4,5,6),(1,2))).chain().toList())

    #回到上次的例子

    students = [

    {

    "name":"wwb",

    "sex":"1",

    "course":[

    {

    "name":"Math",

    "score":90

    },

    {

    "name":"English",

    "score":80

    }

    ]

    },

    {

    "name":"wxa",

    "sex":"1",

    "course":[

    {

    "name":"Music",

    "score":90

    },

    {

    "name":"English",

    "score":80

    }

    ]

    },

    {

    "name":"wxb",

    "sex":"1",

    "course":[

    {

    "name":"Math",

    "score":92

    },

    {

    "name":"Music",

    "score":80

    }

    ]

    },

    ]

    #求选修数学同学的平均分

    print(From(students).map(lambda s: From(s["course"]).map(lambda c:

    {

    "name":s["name"],

    "sex":s["sex"],

    "course":c["name"],

    "score":c["score"]

    }).toList()).chain().toList())

    studentmaths = From(students).map(lambda s: From(s["course"]).map(lambda c:

    {

    "name":s["name"],

    "sex":s["sex"],

    "course":c["name"],

    "score":c["score"]

    }).toList()).chain().filter(lambda it:it["course"]=="Math").toList()

    print(studentmaths)

    print(From(studentmaths).reduce(lambda acc,s:acc+s["score"],0)/len(studentmaths))

    展开全文
  • 关于jQuery的链式调用真正有意义的链式调用也就是方法链(method chaining)。方法链这个词是有的,而且使用的很广泛。其实很多人口中的“链式调用”实际上就是指方法链。但是“链式调用”这个词语还可以描述函数调用...
  • 先下个结论,链式调用的原理是type(self) = type(self.feed('data')) = type(self.conv(3, 3, 64, 1, 1, name='conv1_1')),即类的实例化访问类属性后返回值依然是类的实例化,从而可以继续访问返回值的类属性,...
  • Python

    2018-08-30 13:19:51
    1. 交换变量值 2. 将列表中的所有元素组合成字符串 3. 查找列表中频率最高的值 ...9. 链式函数调用 10. 复制列表 11. 字典 get 方法 12. 通过「键」排序字典元素 13. For Else...
  • 生成器中的send方法-- 给当前停止的yield发生信息-- 内部调用__next__()取到下一个yield的返回值2.递归:函数的(直接,间接)自调用-- 回溯 与 递推-- 重点:出口 | 递归的条件3.匿名函数-- lambda 参数列表: ...
  • python2

    2019-10-18 16:50:19
    文章目录pandas小技巧交换变量值将列表中的所有元素组合成字符串查找列表中频率最高的值检查两个字符串是不是由相同字母不同顺序组成反转字符串反转列表转置二维数组链式比较链式函数调用复制列表字典 get 方法移除...
  • Python Cookbook

    2013-07-31 22:33:26
    17.8 从Python调用的C函数中返回None 611 17.9 用gdb调试动态载入的C扩展 613 17.10 调试内存问题 614 第18章 算法 616 引言 616 18.1 消除序列中的重复 619 18.2 在保留序列顺序的前提下消除其中的重复 ...
  • 交换值:从列表的所有元素中连接为一个字符串:找到列表中出现最频繁的值:检查两个英语单词是否为回文,即字母顺序互相颠倒:反转字符串:反转列表:转置2维数组:链式比较(Chained Comparison):链式函数调用...
  • 交换值:从列表的所有元素中连接为一个字符串:找到列表中出现最频繁的值:检查两个英语单词是否为回文,即字母顺序互相颠倒:反转字符串:反转列表:转置2维数组:链式比较(Chained Comparison):链式函数调用...
  • 1.栈 操作受限的线性表,只能在...#python实现顺序栈 class ArrayStack: def __init__(self,n): self.stack = [] self.limit = n self.count = 0 def push(self,item): if self.count == self.limit: return
  • 交换值:从列表的所有元素中连接为一个字符串:找到列表中出现最频繁的值:检查两个英语单词是否为回文,即字母顺序互相颠倒:反转字符串:反转列表:转置2维数组:链式比较(Chained Comparison):链式函数调用...
  • 交换值:从列表的所有元素中连接为一个字符串:找到列表中出现最频繁的值:检查两个英语单词是否为回文,即字母顺序互相颠倒:反转字符串:反转列表:转置2维数组:链式比较(Chained Comparison):链式函数调用...
  • python基础概念(1)

    2020-11-02 21:45:25
    python基础概念(1)python程序的构成python文件创建和执行通过缩进组织代码块使用注释使用\行连接符对象引用标识符变量和简单赋值语句变量的声明和赋值删除变量和垃圾回收机制链式赋值系列解包赋值常量 python程序...
  • 17个Python小技巧

    2019-02-20 13:59:30
    1. 交换变量值   2. 将列表中的所有元素组合成字符串 3. 查找列表中频率最高的值 ...9. 链式函数调用 10. 复制列表 11. 字典 get 方法 12. 通过「键」排序字典元素 13. For E...
  • Python编程的17个特别实用的技巧trick。... 链式函数调用;复制列表;字典的get方法;通过key排序字典;For else;转换列表为逗号分隔符格式;合并字典;列表中最小和最大的索引;移除列表中的重复元素。
  • 机器学习算法Python实现 目录 机器学习算法Python实现 一、线性回归 1、代价函数 2、梯度下降算法 3、均值归一化 4、最终运行结果 5、使用scikit-learn库中的线性模型实现 二、逻辑回归 1、代价函数 2、...
  • 1、交换变量值 a,b = 2,5 a,b = b,a 2、检查两个字符串是不是由相同字母不同顺序组成 ...4、链式函数调用 def product(a,b): return a * b def add(): return a + b b = True print((pro.
  • image.jpeg队列也可以用数组与链表来实现,用数组实现的队列叫做顺序队列,用链表实现的队列叫做链式队列。队列需要两个指针,一个是head指针,指向队头;一个是tail指针,指向队尾。image.jpeg当调用两次出队操作...
  • 都可以通过顺序结构和链式结构实现 不同点: 栈:【Stack】只能在表的一端进行插入或删除操作的限定表,即在表尾进行操作,用于表达式的转换和求和,函数的递归和调用【函数入栈和出栈】; 队列:【Queue】只能在...
  • 线性表的顺序存储结构和线性表的链式存储结构分别是:4. 单链表中,增加头节点的目的:5. 算法分析的目的:6. n个顶点的强连通图的边数至少为:7. 一颗二叉树有70个叶子节点,80个度为1的节点,则该二叉树共有多少...
  • 调用ActionChains的方法时,不会立即执行,而是将所有的操作,按顺序存放到一个队列中,当调用perform()方法时,队列中的事件会依次执行 链式写法: ActionChains(driver).move_to_element(element).click(element)....
  • 使用函数名来调用的版本只能调用Lua全局函数. "..."代表传递给Lua函数的 可变个数的参数. 这使得你可以指定调用的策略.你可以通过 operator[] 来实现 这个功鞥.你可以同过方括号来指定策略,例如: int ret = call_...

空空如也

空空如也

1 2
收藏数 26
精华内容 10
关键字:

python链式调用顺序

python 订阅