python程序设计实验6:函数式编程(代码片段)

上山打老虎D 上山打老虎D     2022-12-15     370

关键词:

1. 函数的参数传递

定义一个简单的函数 sum 如下

def sum(a, b, c):
print("a=%d, b=%d, c=%d"%(a,b,c)) 
print(a+b+c)

以下哪些语句是合法的,哪些是不合法的?分别输出什么?解释原因。
a) sum(*(1, 2, 3))
答:
语句合法。
输出如下:

三个参数均通过*param形式实现了可变数量参数,并作为a,b,c三个参数调用函数进行运算。

b) sum(1, *(2, 3))
答:
语句合法。
输出如下:

第一个参数a直接传参,后两个参数通过*param形式实现了可变数量参数,并作为b,c两个参数调用函数进行运算。

c) sum(*(1,),b=2, 3)
答:语句非法。并报错:
SyntaxError: positional argument follows keyword argument。即关键字参数必须跟随在位置参数后面。由于如果使用关键字赋值就需要都使用,这里只使用了一个关键字参数赋值,因此报错。

d) sum(*(1,),b=2, c=3)
语句合法。
输出如下:

具体同上。如果使用了关键字参数赋值,则都需进行赋值。代码中都对关键字进行了赋值。因此语句合法。

e) sum(*(1, 2),c=3)
语句合法。
输出如下:

同c题,本题中只是多了一个可变数量参数,少了一个关键字赋值。仍然满足“如果使用了关键字参数赋值,则都需进行赋值”的原则,故语句合法。

f) sum(a=1, *(2, 3))
语句非法。并报错:
TypeError: sum() got multiple values for argument ‘a’。即参数‘a’被多次赋值。这是由于首先通过关键字赋值对a进行了赋值后,又通过可变数量参数进行了赋值从而导致错误发生。

g) sum(b=1, *(2, 3))
语句非法。并报错:
TypeError: sum() got multiple values for argument ‘b’。原因同上。即参数‘b’被多次赋值。这是由于首先通过关键字赋值对b进行了赋值后,又通过可变数量参数进行了赋值从而导致错误发生。

h) sum(c=1, *(2, 3))
语句合法。
输出如下:

与f题,g题原因相同。首先利用关键字赋值对变量c进行了赋值。其次通过可变数量参数对‘a’和‘b’进行了赋值,三个变量都被赋值且未被重复赋值,故语句合法。

2. Lambda

思考以下句子的输出,解释每句话意思,并通过实际测试验证自己想法。

2.1 (lambda val: val ** 2)(5)

①输出结果: 25
②代码分析: 求输入值的平方。根据Lambda表达式,可以看出,该表达式的值为输入数据的2次方
③进行测试:
a)输入-4:输出16
b)输入0:输出0
c)输入9:输出81
结合数据测试以及理论分析,可以得出,该Lambda表达式的意思为求一个数的平方。

2.2 (lambda x, y: x * y)(3, 8)

①输出结果: 24
②代码分析: 求输入两数之积。根据Lambda表达式,可以看出,该表达式的值为输入两个数字的乘积。
③进行测试:
a)输入-4,-6:输出24
b)输入9,0:输出0
c)输入9,5:输出45
结合数据测试以及理论分析,可以得出,该Lambda表达式的意思为求一个数的平方。

2.3 (lambda s: s.strip().lower()[:2])(’ PyTHon’)

①输出结果: py
②代码分析: 求输入字符串中前两个非空格非换行小写字母(如原来为大写,则转换为对应小写字母)
首先通过string.strip()函数从头部丢弃空格以及换行符。再利用string.lower()函数将对应大写字母转为小写后利用切片得到前两个字符
③进行测试:
a)输入 I love :输出i (i后有一空格)
b)输入 456:输出45
c)输入 @aa:输出@a
结合数据测试以及理论分析,可以得出,该Lambda表达式的值为第一个非非空格非换行(大写对应)小写字母,以及其后的一个(大写对应)小写字母或其他字符。

3. Map

使用 map 语句将以下输入,分别转化为指定的输出。

3.1 [‘12’, ‘-2’, ‘0’] --> [12, -2, 0]

①大致思路:
使用map将对应字符串型转换为整型即可。

②编写代码:

print(list(map(lambda x: int(x), ['12','-2','0'])))

此处借助了Lambda表达式,将字符型转成整形,并借助list完成输出。

③运行测试:

3.2 [‘hello’, ‘world’] --> [5, 5]

①大致思路:
使用map获得每个字符串的对应长度即可。
②编写代码:

print(list(map(lambda x: len(x), ['hello', 'world'])))

③运行测试:

3.3 [‘hello’, ‘world’]` --> [‘olleh’, ‘dlrow’]

①大致思路:
使用map将字符串翻转即可。

②编写代码:

print(list(map(lambda x: x[::-1], ['hello', 'world'])))

此处借助了Lambda表达式并利用字符串切片获取反向字符串,并借助list完成输出。

③运行测试:

3.4 range(2, 6) --> [(2, 4, 8), (3, 9, 27), (4, 16, 64), (5, 25, 125)]

①大致思路:
使用map依次求出给定数字的一次方,二次方,以及三次方。

②编写代码:

print(list(map(lambda x: (x,x**2,x**3), range(2,6))))

此处借助了Lambda表达式,利用range获得范围并获取一次方,二次方,三次方的数值,并借助list完成输出。
③运行测试:

3.5 zip(range(2, 5), range(3, 9, 2)) --> [6, 15, 28]

①大致思路:
通过zip收集后即为[(2, 3), (3, 5), (4, 7)],因此函数的大意为求两个数字的乘积。由于zip返回的是元组打包成的列表,因此要对元组进行操作,而不能对两个数字进行操作。

②编写代码:

print(list(map(lambda x: x[0]*x[1], zip(range(2, 5), range(3, 9, 2)))))

此处首先借助Lambda表达式,并利用zip收集两个range获得范围。由于zip返回的是由元组构成的列表,因此Lambda中的变量为元组,故返回元组第一个值与第二个值的乘积即可。
③运行测试:

4. Filter

使用 filter 语句将以下输入,分别转化为指定的输出。

4.1 [‘12’, ‘-2’, ‘0’] --> [‘12’, ‘0’]

①大致思路:
观察题目,可以知道,filter保留下转成整型后大于等于零的字符串。因此使用filter并借助Lambda表达式可以比较简单又有效的完成这个任务。

②编写代码:

print(list(filter(lambda x: int(x)>=0 , ['12','-2','0'])))

利用Lambda作为函数,对给定列表中每个元素进行转成0后是否大于等于0进行判断并过滤。
③运行测试:

4.2 [‘hello’, ‘world’] --> [‘world’]

①大致思路:
观察题目,可以知道,filter保留下转成首字母为w的字符串。因此使用filter并借助Lambda表达式可以比较简单又有效的完成这个任务。

②编写代码:

print(list(filter(lambda x: x[0]=='w' , ['hello', 'world'])))

③运行测试:

4.3 [‘technology’, ‘method’, ‘technique’] --> [‘technology’, ‘technique’]

①大致思路:
观察题目,可以知道,filter保留下转成首字母为t的字符串。因此使用filter并借助Lambda表达式可以比较简单又有效的完成这个任务。

②编写代码:

print(list(filter(lambda x: x[0]=='t' , ['technology', 'method', 'technique'])))

通过借助Lambda表达式对字符串第一个字符直接访问并判断是否为t从而进行过滤。

③运行测试:

4.4 range(20) --> [0, 3, 5, 6, 9, 10, 12, 15, 18]

①大致思路:
观察题目,可以知道,filter保留三或五的倍数。因此使用filter并借助Lambda表达式对数字进行取余判断余数是否为零以完成这个任务。

②编写代码:

print(list(filter(lambda x: x%3==0 or x%5==0 , range(20))))

③运行测试:

5. Reduce

使用 reduce 语句编写函数 lcm(*nums),计算任意数量个正整数的最小公倍数,要求只写一句 python 语句 (提示:可使用 math 模块的 gcd 函数先求出最大公约数)。
例子:

lcm(3, 5) # 15
lcm(41, 106, 12) # 26076
lcm(1, 2, 6, 24, 120, 720) # 720
lcm(3) # 3
lcm() # 如果没有向函数提供数字,可以返回值1。

①大致思路:
最小公倍数等于两数乘积除以最大公约数。因此可以借助Lambda表达式进行运算。此处需要注意,必须要给函数赋初始值1,否则当函数的输入参数个数为零时,将报错。

②编写代码:

def lcm(*nums):
    return int(reduce(lambda x, y: x*y/math.gcd(int(x), int(y)), nums, 1))

使用Lambda表达式,将每两个元素的返回值设置为两数之积与两数最大公约数的商。在reduce内,以Lambda作为函数,以nums作为范围,并设置默认函数返回值1。需要注意的是,此处必须设置返回值为1,否则当nums中参数个数为0时,将报错。
③运行测试:
使用几个数字进行测试结果如下:
a)参数全部缺省:

b)参数缺省一个:

c)拥有两个参数

d)拥有很多参数

6. Iterator

运行以下代码,观察输出并解释输出的原因。

it = iter(range(100))
67 in it
print(next(it))
print(37 in it)
print(next(it))

①运行代码:

即print(next(it))输出了68,print(37 in it)输出了False。print(next(it))发生了StopIteration迭代结束异常。

②分析原因:
首先,定义了it为从0到100范围内的迭代器。第二行即查找67是否在迭代器中,此时迭代器位置在67处。然后第三行将迭代器后移一个并输出,因此此时应输出68。
第四行查查37是否在迭代器中,由于此时迭代器位置在68且迭代器不能向前移动,故迭代器将一直移动到末尾,并返回False。
由于第四行中对37的查找使迭代器移动到迭代对象末尾,因此再调用next函数对迭代器进行后移时,将报错StopIteration。

7. Generator

7.1 编写一个生成器 generate_triangles(),连续地产生三角数 1,3,6,10,… 三角数通过连续的正整数相加来生成(如 1=1,3=1+2,6=1+2+3,10=1+2+3+4,…)。

例子:
g=generate_triangles()
for _ in range(5):
print(next(g)) #输出 1,3,6,10,15

①大致思路:
由于三角数每一个数都等于前一个数加上第几个数。因此可以借助生成器实现快速生成。即在yield中定义,每一个数都等于前面的数字加上计数器再加一即可。

②编写代码:

# 定义生成器
def generate_triangles():
    a,  n = 1, 1
    while True:
        yield a
        # 每一个元素都等于上一个元素加第几个元素再加一
        a += n+1
        n += 1


# 进行测试
it = generate_triangles()
for _ in range(5):
    print(next(it))

首先定义生成器,由于每一个数都等于前面的数字加上计数器再加一。因此只需定义当前值与计数器,首先,将当前值加上计数器再加一。然后将计数器加一即可。

③运行测试:

7.2 使用生成器 generate_triangles(),编写函数generate_triangles_under (n),返回小于 n 的所有三角数。

①大致思路:
使用生成器进行迭代生成,并依次进行判断,如果小于n则加入到结果列表中,否则直接返回即可。

②编写代码:

# 定义生成器
def generate_triangles():
    a,  n = 1, 1
    while True:
        yield a
        # 每一个元素都等于上一个元素加第几个元素再加一
        a += n+1
        n += 1


# 定义小于n的三角数函数
def generate_triangles_under(n):
    res = []
    it = generate_triangles()
    temp = next(it)
    # 如果大于则直接退出循环
    while temp < n:
        # 如果小于则加入到列表中
        res.append(temp)
        temp = next(it)
    return res


print(generate_triangles_under(10))

调用生成器生成每一个值,并依次对每个值进行判断,如果生成的值小于n,则加入到结果列表中,否则直接返回。

③运行测试:

实验结论

本次实验主要是对函数式编程的理解以及使用。分别学习了函数的传参,Lambda表达式,Map,Filter,Reduce,迭代器和生成器的使用。通过这些连续,我初步掌握了这些函数式编程技巧的使用。
本次实验还算比较顺利,仅有一些地方遇到了困难,在查阅资料后也都得到解决。

  1. 在可变数量参数函数中,需要注意函数的初始值。在本实验中,lcm函数求最小公倍数时,就必须注意给函数赋初始值,否则如果参数个数为0,则将报错。
  2. Lambda可以减少代码量并提高可读性:在本实验进行过程中,很多代码都是使用Lambda表达式进行完成,最后编写的代码不仅比较短,而且可读性都比较高。因此,在进行函数式编程时,可以采用Lambda表达式来减少代码量并提高可读性。
  3. 定义生成器时,务必要搞清楚生成数值的过程。本实验中,生成器一部分是相对耗时比较长的,究其原因是不能正确理解生成器生成对应数据时的过程。因此,搞清楚生成数据的过程,才能进行实验。

python-函数与函数式编程(代码片段)

一、函数定义1、函数的定义格式在Python中,函数的定义使用def语句、函数名、括号、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值可以使用return进行返回。例子:  defmy_abs(x):  print(x)  return0 说... 查看详情

第六章函数和宏定义实验(代码片段)

C程序设计实验报告实验项目:6.4.2、模块化程序设计利用复化梯形公式计算定积分计算Ackerman函数6.4.3函数的递归调用编程计算x的y次幂的递归函数getpower(intx,inty),并在主程序中实现输入输出编写计算学生年龄的递归函数编写递... 查看详情

笔记效率之门——python中的函数式编程技巧(代码片段)

文章目录Python函数式编程1.数据2.推导式3.函数式编程3.1.Lambda函数3.2.python内置函数3.3.高阶函数4.函数式编程的应用Python函数式编程我的AIStudio项目:【笔记】LearnDL第三课:Python高级编程——抽象与封装-飞桨AIStudio(baidu.com)p... 查看详情

函数式编程(代码片段)

...任务分解成简单的任务.这种分解可以称之为面向过程的程序设计.函数就是面向过程的程序设计的基本单元. 在计算机的层次上,CPU执行的是加减乘除的指令代码,以及各种条件判断和跳转指令.所以,汇编语言是最贴近计算机的... 查看详情

12-函数式编程(代码片段)

Python语言的高级特性函数是编程(FunctionalProgramming)基于lambda演算的一种编程方式程序中只有函数函数可以作为参数,同样可以作为返回值纯函数式变成语言:LISP,HaskellPython函数式编程只是借鉴函数式编程的一些特点,可以理... 查看详情

python基础--函数式编程(代码片段)

#面向过程#函数式编程:函数式=编程语言定义的函数+数学意义上的函数#面向对象#高阶函数:1.函数接受的参数是一个函数名2.返回值中包含函数#deffoo(n):#n=bar#print(n)##defbar(name):#print(‘mynameis%s‘%name)###foo(bar)#把函数当做参数传给另... 查看详情

python函数式编程以及高阶函数(代码片段)

...ng.com)一、什么是函数式编程首先要知道的是,函数是python内建的一种封装方法,可以通过把指定段落的代码拆解成函数,通过一层一 查看详情

头歌实验一python初体验——helloworld(代码片段)

文章目录>>>第1关:HelloPython,我来了!任务描述相关知识Python交互式编程模式Python脚本式编程模式Print内置函数编程要求测试说明参考答案>>>第2关:我想看世界任务描述相关知识input()函数print()函数... 查看详情

python精简笔记——函数式编程(代码片段)

...0c;这种纯函数我们称之为没有副作用。而允许使用变量的程序设计语言,由于函数内部的变量状态不确定,同样的输入,可能得到不同的输出,因此,这种函数是有副作用的。函数式编程的一个特点就是,... 查看详情

函数式编程(代码片段)

《Python从小白到大牛》第10章函数式编程定义函数函数参数使用关键字参数调用函数参数默认值可变参数函数返回值无返回值函数多返回值函数函数变量作用域生成器嵌套函数函数式编程基础函数类型上述代码第①行重构了calcula... 查看详情

函数式编程—高阶函数(代码片段)

...任务分解成简单的任务,这种分解可以称之为面向过程的程序设计。函数就是面向过程的程序设计的基本单元就是越低级的语言,越贴近计算机,抽象程度低,执行效率高,比如C语言;越高级的语言,越贴近计算,抽象程度高... 查看详情

函数式编程(模块基础)(代码片段)

...相对较少,很多编程语言都采用这种组织代码的方式。在Python中,一个.py文件就称之为一个模块(Module)。使用模块有什么好处?最大的好处是大大提高了代码的可维护性。其次,编写代码不必从零开始。当 查看详情

头歌实验一python初体验——helloworld(代码片段)

文章目录>>>第1关:HelloPython,我来了!任务描述相关知识Python交互式编程模式Python脚本式编程模式Print内置函数编程要求测试说明参考答案>>>第2关:我想看世界任务描述相关知识input()函数print()函数... 查看详情

函数式编程简介-附入门方法(代码片段)

WHAT?什么是函数式编程?函数式编程是一种编程范式。编程范式又是什么?编程范式是一种解决问题的思路。我们熟悉的命令式编程把程序看作一系列改变状态的指令;而函数式编程把程序看作一系列数学函数映射的组合。编程... 查看详情

函数式编程(代码片段)

...的函数+数学意义上的函数(先想到一个数学模型,再用python上的功能实现这个逻辑) y=x+1defcat():returnx+1  特性:1.不用变量保存状态,意思就是不赋值,而且不修改变量2.第一类对象:函数即变量高阶函数1。函数接收... 查看详情

前端学习之函数式编程—函数式编程概念+头等函数(代码片段)

什么是函数式编程函数式编程(functionprogrammingFP)FP是编程范式之一,我们常听说的还有,面向过程编程,面向对象编程函数式编程的思维方式把现实世界的事物和事物之间的联系抽象到程序世界(对运算... 查看详情

python中函数与函数式编程(代码片段)

...表示参数是可选的"optionaldocumentationstring"function_suitePython中实用的内建函数函数说明 查看详情

函数式编程(代码片段)

《Python从小白到大牛》第10章函数式编程定义函数函数参数使用关键字参数调用函数参数默认值可变参数函数返回值无返回值函数多返回值函数函数变量作用域生成器嵌套函数函数式编程基础函数类型上述代码第①行重构了calcula... 查看详情