python学习手册,第四部分练习题

可变参数,在下面的adder.py 文件中,有连个版本的adder函数,这里的难点在于,了解如何把累加器初始值设置为任何传入类型的空值。第一种解法使用了手动类型测试,从而找出整数,以及如果参数不是整数时,采用第一个参数(假设为序列)的空分片(这里使用第一个参数的空分片能够保证对于传入字符串得到空字符串,对于传入列表得到空列表。不过这种空分片的做法并不适用于字典)。第二种解法直接使用第一个参数作为初始值,之后扫描第二个以及之后的元素。很像第18章min函数版本(在最后附上18章min函数版本)
第二个解法更好,这两种解法都假设所有参数为相同的类型,而且都无法用于字典(+无法用在混合类型或字典上)。你也可以加上类型检测和特殊代码从而兼容字典,但那都是额外的加分项了。

def adder1(*args):
    print('adder1', end=' ')
    if type(args[0]) == type(0):
        sumx = 0
    else:
        sumx = args[0][:0]  # use empty slice of arg1
    for arg in args:
        sumx = sumx + arg
    return sumx


def adder2(*args):
    print('adder2', end=' ')
    sumx = args[0]
    for next in args[1:]:
        sumx = sumx + next
    return sumx


for func in (adder1, adder2):
    print(func(2, 3, 4))
    print(func('spam', 'eggs', 'toast'))
    print(func(['a', 'b'], ['c', 'd'], ['e', 'f']))

代码中的args[0][:0]的解释

lst = [1, 2, 3]
print(lst[:0])
s = 'abc'
print(s[:0])

第18章函数min版本
假设你想要编写一个函数,个函数能够计算任意参数和任意对象数据类型集合中的最小值,也就是说,这个函数应该接受零个或多个参数:希望传递多少就可以传递多少。此外,这个函数应该能够使用所有python对象类型:数字、字符串、列表、字典的列表,文件甚至None
第一个要求提供了一个能够充分展示*的特性的实例:我们能够将参数收集到一个元组中,并且可以通过简单的loop一次处理每一个参数。第二部分的问题定义很简单:因为每个对象类型支持对比,没有必要对每种类型都创建一个函数(一个多态的应用)。我们能够不论其类型进行简单的比较。并且让python执行正确的比较。
下面文件介绍了编写这个操作的三种方法
1 第一个函数获取了第一个参数(args是一个元组),并且使用分片去掉第一个得到了剩余的参数(一个对象同自己比较是没有意义的,特别是这个对象是一个较大的结构时)
2.第二个版本让python自动获取第一个参数以及其余参数,因此避免了进行一次索引和分片
3.第三个版本通过对内置函数list的调用让一个元组转换为一个列表,之后调用list内置的sort方法实现比较

  def min1(*args):
    res = args[0]
    for arg in args[1:]:
        if arg < res:
            res = arg
    return res


def min2(first, *rest):
    for arg in rest:
        if arg < first:
            first = arg
    return first


def min3(*args):
    tmp = list(args)
    tmp.sort()
    return tmp[0]


print(min1(3, 4, 1, 2))
print(min2('bb', 'aa'))
print(min3([2, 2], [1, 1], [3, 3]))

上述三种方法都没有传入参数的测试,上述三种方法,在没有参数传入的情况下,python都会抛出异常。当尝试获取元素0时,第一种方案会发生异常;当python检测到参数列表不匹配时,第二种方案会发生异常;在尝试最后返回元素0时,第三种方案会发生异常。
现在,看一个实际中常用的使用特定参数匹配模式的例子:编写一个函数返回了两个序列的公共部分(它挑选出在两个序列中·都出现的元素)。这里是一个能够对任意数目的序列(一个或多个)进行公共部分挑选的函数,通过使用可变参数的匹配形式*args去收集传入的参数。因为参数是作为一个元组传入的。我们能够通过一个简单的for循环对它进行处理。编写一个union函数,来从任意多的参数中收集所有曾经在任意操作对象中出现过的元素。

def intersect(*args):
    res = []
    for x in args[0]:
        for other in args[1:]:
            if x not in other: break
        else:
            res.append(x)
    return res


def union(*args):
    res = []
    for seq in args:
        for x in seq:
            if not x in res:
                res.append(x)
    return res


s1, s2, s3 = 'spam', 'scam', 'slam'
print(intersect(s1, s2), union(s1, s2))

4关键字参数。修改练习题2的adder函数,使其可以接受三个参数,并求其和/合并值:def adder(good,bad,ugly)。现在,为每个参数提供默认值,通过交互模式调用这个函数进行试验。试着传入一个、两个、三个以及四个参数。然后,试着传入关键字参数adder(ugly=1,good=2)这样的调用方式能用吗?为什么?最后,把新的adder再通用化,从而可以接受任意数目的关键字参数,并求其合/合并值。需要遍历字典,而不是元组(dict.keys方法会返回一个列表,你可以用for或while遍历,但是确保再python3.0中将其放入到一个list调用中)。

def adder(good=1,bad=2,ugly=3):
    return good+bad+ugly
print(adder())
print(adder(5))
print(adder(5,6))
print(adder(5,6,7))
print(adder(ugly=7,good=6,bad=5))
def adder1(*args):
    tot=args[0]
    for arg in args[1:]:
        tot +=arg
    return tot
def adder2(**args):
    argskeys=list(args.keys())
    tot=args[argskeys[0]]
    for key in argskeys[1:]:
        tot +=args[key]
    return tot

def adder3(**args):
    args=list(args.values())
    tot=args[0]
    for arg in args[1:]:
        tot +=arg
    return tot

def adder4(**args):
    return adder1(*args.values())
print(adder1(1,2,3),adder1('aa','bb','cc'))
print(adder2(a=1,b=2,c=3),adder2(a='aa',b='bb',c='cc'))
print(adder3(a=1,b=2,c=3),adder3(a='aa',b='bb',c='cc'))
print(adder4(a=1,b=2,c=3),adder4(a='aa',b='bb',c='cc'))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值