首页 > 编程语言 >Python3 列表生成式和最近刷题遇到问题

Python3 列表生成式和最近刷题遇到问题

时间:2023-04-17 21:33:16浏览次数:48  
标签:11 生成式 list else range 列表 Python3 刷题

python3创建二维数组需要用到列表生成式

列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式。

举个例子,要生成list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]可以用list(range(1, 11))

>>> list(range(1, 11))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

但如果要生成[1x1, 2x2, 3x3, ..., 10x10]怎么做?方法一是循环:

>>> L = []
>>> for x in range(1, 11):
...    L.append(x * x)
...
>>> L
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

但是循环太繁琐,而列表生成式则可以用一行语句代替循环生成上面的list:

>>> [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

写列表生成式时,把要生成的元素x * x放到前面,后面跟for循环,就可以把list创建出来,十分有用,多写几次,很快就可以熟悉这种语法。

for循环后面还可以加上if判断,这样我们就可以筛选出仅偶数的平方:

>>> [x * x for x in range(1, 11) if x % 2 == 0]
[4, 16, 36, 64, 100]

还可以使用两层循环,可以生成全排列:

>>> [m + n for m in 'ABC' for n in 'XYZ']
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']

三层和三层以上的循环就很少用到了。

运用列表生成式,可以写出非常简洁的代码。例如,列出当前目录下的所有文件和目录名,可以通过一行代码实现:

>>> import os # 导入os模块,模块的概念后面讲到
>>> [d for d in os.listdir('.')] # os.listdir可以列出文件和目录
['.emacs.d', '.ssh', '.Trash', 'Adlm', 'Applications', 'Desktop', 'Documents', 'Downloads', 'Library', 'Movies', 'Music', 'Pictures', 'Public', 'VirtualBox VMs', 'Workspace', 'XCode']

for循环其实可以同时使用两个甚至多个变量,比如dictitems()可以同时迭代key和value:

>>> d = {'x': 'A', 'y': 'B', 'z': 'C' }
>>> for k, v in d.items():
...     print(k, '=', v)
...
y = B
x = A
z = C

因此,列表生成式也可以使用两个变量来生成list:

>>> d = {'x': 'A', 'y': 'B', 'z': 'C' }
>>> [k + '=' + v for k, v in d.items()]
['y=B', 'x=A', 'z=C']

最后把一个list中所有的字符串变成小写:

>>> L = ['Hello', 'World', 'IBM', 'Apple']
>>> [s.lower() for s in L]
['hello', 'world', 'ibm', 'apple']

if ... else

使用列表生成式的时候,有些童鞋经常搞不清楚if...else的用法。

例如,以下代码正常输出偶数:

>>> [x for x in range(1, 11) if x % 2 == 0]
[2, 4, 6, 8, 10]

但是,我们不能在最后的if加上else

>>> [x for x in range(1, 11) if x % 2 == 0 else 0]
  File "<stdin>", line 1
    [x for x in range(1, 11) if x % 2 == 0 else 0]
                                              ^
SyntaxError: invalid syntax

这是因为跟在for后面的if是一个筛选条件,不能带else,否则如何筛选?

另一些童鞋发现把if写在for前面必须加else,否则报错:

>>> [x if x % 2 == 0 for x in range(1, 11)]
  File "<stdin>", line 1
    [x if x % 2 == 0 for x in range(1, 11)]
                       ^
SyntaxError: invalid syntax

这是因为for前面的部分是一个表达式,它必须根据x计算出一个结果。因此,考察表达式:x if x % 2 == 0,它无法根据x计算出结果,因为缺少else,必须加上else

>>> [x if x % 2 == 0 else -x for x in range(1, 11)]
[-1, 2, -3, 4, -5, 6, -7, 8, -9, 10]

上述for前面的表达式x if x % 2 == 0 else -x才能根据x计算出确定的结果。

可见,在一个列表生成式中,for前面的if ... else是表达式,而for后面的if是过滤条件,不能带else

练习

如果list中既包含字符串,又包含整数,由于非字符串类型没有lower()方法,所以列表生成式会报错:

>>> L = ['Hello', 'World', 18, 'Apple', None]
>>> [s.lower() for s in L]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <listcomp>
AttributeError: 'int' object has no attribute 'lower'

使用内建的isinstance函数可以判断一个变量是不是字符串:

>>> x = 'abc'
>>> y = 123
>>> isinstance(x, str)
True
>>> isinstance(y, str)
False

请修改列表生成式,通过添加if语句保证列表生成式能正确地执行:

# -*- coding: utf-8 -*-
L1 = ['Hello', 'World', 18, 'Apple', None]
# 测试:
print(L2)
if L2 == ['hello', 'world', 'apple']:
    print('测试通过!')
else:
    print('测试失败!')
  python rang的上边界是停止的意思,所以并不会取上边界的值

可以这么想,range 的上界参数并非数学意义上的上界,而是计算意义上的跳出循环的条件(当把循环结构作用于这个 range 时,遇到“上界”,就意味着跳出);与 C / C++ 中数组指针为什么被允许指向数组后面的一个元素的原因类似。题主可以查查 Andrew Koenig 在这方面非常细致深入的讨论。

了解程序正确性证明的话,明确循环体结构的跳出条件是验证程序正确性的重要步骤。而把 range 的上界直接设为跳出条件,大大方便了日常使用时对循环体跳出条件的设置,能避免不少犯错的机会。而由于循环体在指令式语言的重要性,这样的设计就有了基本的意义。

刚才查了一下 Python 的文档,其实函数定义里已经把这一点明确下来了:range(start, stop[, step])。是 stop,不是 upper bound :)

如果需要包含最后一项的表达方式,可以参考 numpy.linspace 。其语法类似 range,但默认包含最后一项,除非设置参数 endpoint 为 False 。

标签:11,生成式,list,else,range,列表,Python3,刷题
From: https://www.cnblogs.com/coolcold/p/17327569.html

相关文章

  • 力扣刷题
    1/*TheisBadVersionAPIisdefinedintheparentclassVersionControl.2booleanisBadVersion(intversion);*/34publicclassSolutionextendsVersionControl{5publicintfirstBadVersion(intn){6if(n==0){7......
  • python3-list
    1、介绍builtins.py文件中定义了list类,用于处理python中列表数据。list也是python的基本数据类型之一。列表是单列的元素集合,用[]包围,内部元素之间用,分隔列表的元素可以是任意类型,且某一列表中可以同时包含不同类型列表支持元素的增删改列表支持数值索引元素不会进行默认......
  • python3-tuple
    1、介绍builtins.py文件中定义了tuple类,用于处理python中元组数据。tuple也是python的基本数据类型之一。元组是单列的元素集合,用()包围,内部元素之间用,分隔元组的元素可以是任意类型,且某一元组中可以同时包含不同类型元组定义后不支持对容量和元素的修改元组支持数值索引......
  • python3-set
    1、介绍builtins.py文件中定义了set类,用于处理python中集合数据。set也是python的基本数据类型之一。集合是单列的元素集合,用{}包围,内部元素之间用,分隔集合的元素可以是任意类型,且某一集合中可以同时包含不同类型集合定义后可以进行增删改集合不支持数值索引set是无序集......
  • python3-dict
    1、介绍builtins.py文件中定义了dict类,用于处理python中字典数据。list也是python的基本数据类型之一。2、类classdict(object):def__init__(self,seq=None,**kwargs):pass3、字面量初始化键必须是number、str和tuple这几种不可变类型,值可以是任意类型......
  • python3-range
    1、介绍range是一个类,用于帮助for循环。2、类classrange(object):"""range(stop)->rangeobjectrange(start,stop[,step])->rangeobject"""def__init__(self,stop):pass3、使用(1)一个参数foriinrange(3):#遍历0,......
  • python3-open
    1、介绍python3中,可以通过内建模块的open函数,进行文件的读写,以及创建文件。2、函数open(file,mode='r',buffering=-1,encoding=None,errors=None,newline=None,closefd=True,opener=None)file:必需,文件路径(相对或者绝对路径)。mode:可选,文件打开模式buffering:设......
  • python3-bytes
    1、介绍python3中,使用bytes类处理字节数据。2、类classbytes(object):"""bytes(iterable_of_ints)->bytesbytes(string,encoding[,errors])->bytesbytes(bytes_or_buffer)->immutablecopyofbytes_or_bufferbytes(int)->byt......
  • python3-type
    1、介绍type本身是内建模块中的一个类,其主要作用是用于判断变量的数据类型。2、类classtype(object):def__init__(cls,what,bases=None,dict=None):"""type(object_or_name,bases,dict)type(object)->theobject'stypetype......
  • python3-len
    1、介绍python3中,可以使用函数len获取容器对象的长度,比如str字符串、list列表等。2、函数deflen(*args,**kwargs):pass返回类型为int,如果长度为0,则就返回0不能对非容器变量使用,会报错,比如int、None值3、示例#不能对非容器变量使用,会报错#print(len(123))pri......