本帖最后由 lightninng 于 2015-5-29 22:59 编辑
今天早上终于答辩完了,晚上玩了两个checkio,放一个出来:Minand Max
在这个任务中,你应该自己写出PY3中实现的内建函数 min 和 max。 一些内建函数在这里是不能用的:import,eval,exec,globals。 别忘了,你需要在你的代码中实现两个函数。 max(iterable, *[, key]) 或者 min(iterable, *[, key])
max(arg1, arg2, *args[, key]) 或者 min(arg1, arg2, *args[, key]) 返回迭代中的最大(最小)项中或者返回根据所提供参数的最大(最小)值 。 如果有一个参数时,它应该是一个迭代器。返回在迭代器的最大(最小)的项。如果提供两个或更多的参数,返回参数中的最大(最小)的项。 可选的唯一关键字是一个用于从每个列表元素提取一个用于比较的参数的函数。(例如,key=str.lower.lower) 如果有多个值同是最大(最小)的,函数返回所遇到的第一个最大值。
-- Python 文档 (内建函数)
输入:一个参数作为一个迭代器或两个以上的参数。 一个函数作为可选关键字参数。 输出:"max" 函数输出最大的项 "min" 函数输出最小的项。 范例: max(3, 2) == 3min(3, 2) == 2max([1, 2, 0, 3, 4]) == 4min("hello") == "e"max(2.2, 5.6, 5.9, key=int) == 5.6min([[1,2], [3, 4], [9, 0]], key=lambda x: x[1]) == [9, 0如何使用: 此任务将帮助你了解一些内置的功能是如何在更精确的水平上工作的。 前提: 所有的测试用例都是正确的并且函数不会引发异常。 def min(*args, **kwargs):
key = kwargs.get("key", lambda x: x)
iterative_object = args if len(args) > 1 else list(args[0])
flag_index, flag_data = 0, iterative_object[0]
for index, each in enumerate(iterative_object):
if key(each) < key(flag_data):
flag_data = key(each)
flag_index = index
return iterative_object[flag_index]
def max(*args, **kwargs):
key = kwargs.get("key", lambda x: x)
iterative_object = args if len(args) > 1 else list(args[0])
flag_index, flag_data = 0, iterative_object[0]
for index, each in enumerate(iterative_object):
if key(each) > key(flag_data):
flag_data = key(each)
flag_index = index
return iterative_object[flag_index]
写的第一版,发现除了if语句中的比较以外都是重复的,学编程的都知道"don't repeat yourself"吧~~,于是改进一下def func_select(func):
if func.__name__ == "min":
compare = lambda *min_args: min_args[0] < min_args[1]
else:
compare = lambda *max_args: max_args[0] > max_args[1]
def min_or_max(*args, **kwargs):
key = kwargs.get("key", lambda x: x)
iterative_object = args if len(args) > 1 else list(args[0])
flag_index, flag_data = 0, iterative_object[0]
for index, each in enumerate(iterative_object):
if compare(key(each), key(flag_data)):
flag_data = key(each)
flag_index = index
return iterative_object[flag_index]
return min_or_max
@func_select
def min(*args, **kwargs):
pass
@func_select
def max(*args, **kwargs):
pass
这里用到的python的装饰器,不明白的鱼油请看这个贴子http://www.liaoxuefeng.com/wiki/ ... b18034f0254bf355000用用装饰器的原因是,根据函数名的不同,在函数体内只有if的判断语句不同,所以只要将判断语句抽象成函数,然后根据函数名不同在if语句处调用不不同的函数即可一次完成两个函数,compare函数即为我们构造的比较函数,根据不同的情况(即函数名为"min"和"max"时),将不同的lambda表达式赋于compare,放在if语句处即可。
成功的用了装饰器很高兴~~
看看第一名的函数def get_first_from_sorted(args, key, reverse):
if len(args) == 1:
args = iter(args[0])
return sorted(args, key=key, reverse=reverse)[0]
def min(*args, key=None):
return get_first_from_sorted(args, key, False)
def max(*args, key=None):
return get_first_from_sorted(args, key, True)
只能说自叹不如,1.用内置函数sorted完成对它的排序,然后取第一个,这个想法我也有过(可惜把key=key弄丢了~~)
2.自己在用排序时,仅仅取第一个为最小,最后一个为最大,当最大值有多个时,取的是最后面那个不符合题目要求,但是用reserve参数完美解决这个问题,这也说明python内置的sort方法和sorted函数均为稳定的排序方法(即排序结束后,相同大小的两个值的相对顺序不变),这里我想到之前在网上看到的说python内置的排序算法是用快速排序,但是通过数据结构的学习我们知道快速排序是不稳定的排序算法,所以python到底用的是什么方法,还可以继续讨论~
自己在试验中学习和巩固的知识有:
1、字典的get方法,可以用于实现类似于C语言中的switch语句,当某种情况不存在时,设定get的第二个参数为缺省函数
2、认识到了内置函数的强大,python内置的sort方法和sorted函数的排序速度是很快的,而且可以处理迭代器,列表,元组,字符串等各种可迭代结构,这给编码带来很大的方便,所以实际上上面的第一名的解法中对args[0]可以不使用iter函数转化为生成器
3、对装饰器的用法有了更深的理解,虽然这里其实并不需要,看了别人的代码之后发现,其实只要重新写的函数,然后max和min函数都调用这个函数,然后传入不同的参数即可,不过don't repeat yourself还是要好好记得的~~
4、这里展示了reverse(sorted(test), key=func)与sorted(test,key=func,reverse=True)这两种方法的不同于test = [3.1, 5.6, 5.9]来说前者的结果是[5.9, 5.6, 3.1]后者的结果是[5.6, 5.9, 3.1]
5、在给compare函数赋值的过程中遇到一个奇怪的现象,最开始我的方法是这样的 compare = lambda *min_args: min_args[0] < min_args[1] if func.__name__ == "min" \
else lambda *max_args: max_args[0] > max_args[1]
但是当func.__name__ 不等于"min"时,我得到的compare函数无法正常工作,在idle里试验的结果是这样的>>> compare(1,2)
<function <lambda>.<locals>.<lambda> at 0x00000000033270D0>
借助鱼油的帮助,原因已经找到。我的赋值方式相当于compare = lambda *min_args: ((min_args[0] < min_args[1]) if func.__name__ == "min" \
else (lambda *max_args: max_args[0] > max_args[1]))
正确的写法有两种compare = lambda *args: ( args[0] < args[1] if key == "<" else args[0] > args[1] )
compare = ( lambda *args: args[0] < args[1] ) if key == "<" else ( lambda *args: args[0] > args[1] )
6、最后函数的默认参数的传入方式可以用字典,其中字典中,参数的名字一定要是字符串类型,如我把自己的代码改一下变成这样def func_select_2(func):
def min_or_max(*args, **kwargs):
key = kwargs.get("key", lambda x: x)
sort_args = {"min": {"key": key}, "max": {"key": key, "reverse": True}}
iterative_object = iter(args) if len(args) > 1 else iter(args[0])
return sorted(iterative_object, **sort_args[func.__name__])[0]
return min_or_max
@func_select_2
def min_2(*args, **kwargs):
pass
@func_select_2
def max_2(*args, **kwargs):
pass
2点了,睡觉~~明天继续pyqt5那个贴子最后的俄罗斯方块的钻研,找工作并不顺利,也要劲了,加油!!!!!!!!!!!!!!!!!
|