60D4 – list 和 tumple 的 13 个经典使用案例

4. 斐波那契数列

斐波那契数列第一、二个元素都为 1,第三个元素等于前两个元素和,依次类推。

普通实现版本

In [9]: def fibonacci(n):
   ...:     if n <= 1:
   ...:         return [1]
   ...:     fib = [1, 1]
   ...:     while len(fib) < n:
   ...:         fib.append(fib[len(fib) - 1] + fib[len(fib) - 2])
   ...:     return fib

调用 fibonacci:

In [10]: r = fibonacci(5)
    ...: print(r)
[1, 1, 2, 3, 5]

这不是高效的实现,使用生成器更节省内存。

len( )是 Python 3 的内置函数,返回对象的长度(元素个数)。
实参可以是序列(如 string、bytes、tuple、list 或 range 等)或集合(如 dictionary、set 或 frozen set 等)。
len( )并不是字符串类的方法。

生成器版本

使用 Python 的生成器,保证代码简洁的同时,还能节省内存:

In [11]: def fibonacci(n):
    ...:     a, b = 1, 1
    ...:     for _ in range(n):
    ...:         yield a
    ...:         a, b = b, a + b

遇到 yield 返回,下次再进入函数体时,从 yield 的下一句开始执行。

In [12]: list(fibonacci(5))
Out[12]: [1, 1, 2, 3, 5] 

Python3 range( ) 函数返回的是一个可迭代对象(类型是对象),而不是列表类型, 所以打印的时候不会打印列表。
Python3 list( ) 函数是对象迭代器,可以把range()返回的可迭代对象转为一个列表,返回的变量类型为列表。
Python2 range( ) 函数返回的是列表。

关于 yield,会专门有一篇来自 runoob.com 的文章可阅读。稍后会摘录到本站一篇新的文章中。


5. 出镜最多

max 函数是 Python 的内置函数,所以使用它无需 import

max 有一个 key 参数,指定如何进行值得比较。

下面案例,求出现频次最多的元素:

In [13]: def mode(lst):
             if not lst: 
                return None
    ...:     return max(lst, key=lambda v: lst.count(v)) # v 在 lst 的出现次数作为大小比较的依据

调用 mode:

In [14]: lst = [1, 3, 3, 2, 1, 1, 2]
    ...: r = mode(lst)
    ...: print(f'{lst} 中出现次数最多的元素为:{r}')
[1, 3, 3, 2, 1, 1, 2]中出现次数最多的元素为:1

出镜最多的元素有多个时,按照以上方法,默认只返回一个。

下面,支持返回多个:

In [34]: def mode(lst):
    ...:     if not lst:
    ...:         return None
    ...:     max_freq_elem = max(lst, key=lambda v: lst.count(v))
    ...:     max_freq = lst.count(max_freq_elem) # 出现最多次数
    ...:     ret = []
    ...:     for i in lst:
    ...:         if i not in ret and lst.count(i)==max_freq:
    ...:             ret.append(i)
    ...:     return ret

In [35]: mode([1,1,2,2,3,2,1])
Out[35]: [1, 2]

max( ) 方法返回给定参数的最大值,参数可以为序列。
返回值:返回给定参数的最大值。

max(iterable, *[, key, default])
max(arg1, arg2, *args[, key])

默认数值型参数,取值大者;
字符型参数,取字母表排序靠后者。
key:可做为一个函数,用来指定取最大值的方法。
default:用来指定最大值不存在时返回的默认值。
arg1:字符型参数/数值型参数,默认数值型

下面例子展示max( )函数使用方法

1、传入多个参数取最大值(元组、列表、集合)

print(max(1,2,3,4,5,6))
# 6

2、传入可迭代对象时,取其元素最大值

s = '12345'  #2、传入可迭代对象时,取其元素最大值
print(max(s))
# 5

3、传入可迭代对象为空时,必须指定参数default,用来返回默认值

print(max((),default=1))
# 1
print(max(())) # 报错
#  Traceback (most recent call last):
#   File "H:/py/60dpy/4.5.1.py", line 1, in <module>
#     print(max(()))
# ValueError: max() arg is an empty sequence

4、传入命名参数key,其为一个函数,用来指定取最大值的方法(灵活运用,根据字典的键值)

s = [{'name': 'li', 'age': 24},{'name': 'he', 'age': 45} ]
b = max(s, key=lambda x: x['age'])
print(b)
# {'name': 'he', 'age': 45}  

Python min( ) 函数与此函数功能相反。

此内容与上述展示的 4 个方法来自:
Python max()函数 – 官方全村的希望 – CSDN

6. 更长列表

带有一个 * 的参数为可变的位置参数,意味着能传入任意多个位置参数。

key 函数定义怎么比较大小:lambda 的参数 vlists 中的一个元素。

In [15]: def max_len(*lists):
    ...:     return max(*lists, key=lambda v: len(v)) # v 代表一个 list,其长度作为大小比较的依据

调用 max_len,传入三个列表,正是 v 可能的三个取值。

In [17]: r = max_len([1, 2, 3], [4, 5, 6, 7], [8])
    ...: print(f' 更长的列表是 {r}')
更长的列表是 [4, 5, 6, 7]

双星号** 和 星号* 是什么意思?

What does ** (double star/asterisk) and * (star/asterisk) do for parameters?

你还可以参考此原典:
https://docs.python.org/dev/tutorial/controlflow.html#more-on-defining-functions

在 Python 的函数中经常能看到输入的参数前面有一个或者两个星号:

def foo(param1, *param2):
def bar(param1, **param2):

这两种用法其实都是用来将 任意个数 的参数导入到 Python 函数中。

单星号(*):*param2 会将所有参数分配为 元组(tuple) 的形式导入:

>>> def foo(param1, *param2):
        print param1
        print param2
>>> foo(1,2,3,4,5)
1
(2, 3, 4, 5)
# 在 foo() 主体中 *param2 是一个包含 2-5 的序列

双星号(**):**param2 将参数分配为 字典 的形式导入

>>> def bar(param1, **param2):
        print param1
        print param2
>>> bar(1,a=2,b=3)
1
{'a': 2, 'b': 3}
# # 在 bar() 主体中 *param2 是一个包含 {'a': 2, 'b': 3} 的字典

这两个习惯用法均可与普通参数混用,以使用一组固定参数和一些可变的参数:

def foo(kind, *args, **kwargs):
   pass

这两个用法可以亦同时出现在一个函数:

>>> def foo(a, b=10, *args, **kwargs):
        print a
        print b
        print args
        print kwargs
>>> foo(1, 2, 3, 4, e=5, f=6, g=7)
1
2
3 4
{'e': 5, 'g': 7, 'f': 6}

此外,单星号的另一个用法是在调用函数时解压缩参数列表:

>>> def foo(bar, lee):
        print bar, lee
>>> l = [1, 2]
>>> foo(*l)
1 2

在Python 3中,可以 *l 在分配的左侧使用(Extended Iterable Unpacking),尽管在这种情况下它提供的是列表而不是元组:

first, *rest = [1,2,3,4]
first, *l, last = [1,2,3,4]

Python 3还添加了新的语义(请参阅 PEP 3102):

def func(arg1, arg2, arg3, *, kwarg1, kwarg2):
    pass

这个 func 函数只接受 3 个 位置参数(positional arguments),之后的所有内容只能作为关键字参数(keyword arguments)传递。

页面: 1 2 3 4 5 6

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注