[Python] 入门(8):Python 基础 -- 解析式,生成器和程序错误

往期回顾:

  • [Python] 入门(1):安装 Python 及必要组件
  • [Python] 入门(2):Python 基础 – 变量
  • [Python] 入门(3):Python 基础 – 内建函数
  • [Python] 入门(4):Python 基础 – 列表和词典的方法
  • [Python] 入门(5):Python 基础 – 字符串的方法
  • [Python] 入门(6):Python 基础 – Python 基础 – 循环,条件和迭代器
  • [Python] 入门(7):Python 基础 – 自定义函数
  • [Python] 入门(8):Python 基础 – 解析式,生成器和程序错误(本文)
  • [Python] 入门(9):Python 基础 – 字符串格式化
  • [Python] 入门(10):Python 基础 – 面向对象编程

本文目录


在老宅看来,解析式绝对是 Python 最伟大的发明之一,因为它是 Python 特有的功能。

解析式 Comprehension

老宅有一个函数:

>>> def find_odd():
...     """
...     寻找 10 以内的奇数,
...     
...     并保存起来
...     """
...     lst = []
...     for i in range(11):
...         if i % 2 == 1:
...             lst.append(i)
...     return lst
>>> find_odd()
[1, 3, 5, 7, 9]

假如老宅告诉你,一行代码就可以实现上面的函数,你信吗?解析式就可以!请看:

>>> [i for i in range(11) if i % 2 == 1] # '== 1'可以省略,因为除 2 的余数只能是 1 或 0,而 0 是 False
[1, 3, 5, 7, 9]

很神奇吧!上面用的是解析式的一种,列表解析式。

列表解析式

列表解析式的语法是:
[动作 for 元素 in 可迭代对象 if 条件]
列表解析式非常好理解:遍历可迭代对象里的元素,判断是否符合条件,如果符合就放到列表里。

列表解析式是解析式里最常用的一种。

集合解析式

语法和列表解析式是一样的,只是把中括号 [] 换成了大括号 {}。集合解析式也可以去重。

>>> {i for i in [1, 2, 1, 2, 1]}
{1, 2}
字典解析式

因为字典有键和值两个变量,所以字典解析式的语法比集合解析式稍微复杂点。
{动作 for 键 in 可迭代对象 for 值 in 可迭代对象}
举例:

>>> {i:j for i in range(3) for j in "abc"}
{0: 'c', 1: 'c', 2: 'c'}

生成器

在第六篇里我们已经了解了迭代器,而这里我们来研究迭代器的一种 – 生成器。生成器的优点在于只在调用的时候才会生成返回值,这在数据规模很大的时候可以节省内存,因为生成器保存的是算法。生成器分为生成器函数和生成器解析式两种。

生成器函数

生成器函数与普通函数的区别在于它使用 yield 代替 return。例如:

>>> def get():
...     yield 0
...     yield 1
>>> gen = get()
>>> print(gen)
<generator object get at 0x10d024930>

在使用生成器时,要先生成一个生成器对象(gen),然后在使用 next() 调用。以上生成器只有在用 next() 调用的时候才生成并返回值。

>>> next(gen)
0
>>> next(gen)
1
生成器解析式

生成器解析式和列表解析式非常相似,唯一的区别在于生成器解析式使用 () 而列表解析式使用 []。所以生成器解析式的语法为:

(元素 for 元素 in 可遍历对象 if 条件)

来看示例:

>>> add = (x + 1 for x in range(10)
>>> add
<generator object <genexpr> at 0x10d024c78>
>>> next(add)
1
>>> next(add)
2

我们也可以用 for 循环遍历生成器:

>>> for i in add:
...     print(i)
1
2
3
4
5
6
7
8
9
10

程序错误和异常

写程序难免会出错。有时候可能是笔误,有可能是程序的设计有问题。程序出现错误和异常会停止运行,并返回错误信息,理解程序返回的错误信息就很有必要。错误和异常有很多种,完整的列表可以在 Python 的官方文档里找到,常见的有如下几种:

IndexError

当序列抽取超出范围时将被引发。

>>> rng = range(5)
>>> rng[6]
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-1-0300ed2c7be7> in <module>
      1 rng = range(5)
----> 2 rng[6]

IndexError: range object index out of range

上面创建了一个有 5 个元素的范围,试图调用第 7 个元素,所以返回 IndexError。

NameError

当某个局部或全局名称未找到时将被引发。

>>> lst2
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-3-a6198233248f> in <module>
----> 1 lst2

NameError: name 'lst2' is not defined

之前没有定义 lst2 变量,试图调用返回 nameError。

StopIteration

由内置函数 next() 和 iterator 的 next() 方法所引发,用来表示该迭代器不能产生下一项。

>>> rng = iter(range(1))
>>> print(next(rng))
>>> print(next(rng))
0
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-9-5d676f6f6480> in <module>
      1 rng = iter(range(1))
      2 print(next(rng))
----> 3 print(next(rng))

StopIteration: 

迭代器里只有一个元素,当所有元素遍历完以后再试图遍历的话会返回 StopIteration。

SyntaxError

当解析器遇到语法错误时将被引发。

>>> def sum
>>>     1 + 2
  File "<ipython-input-10-1e46b721ba15>", line 1
    def sum
           ^
SyntaxError: invalid syntax

自定义函数后应该加 :,忘记加会返回 SyntaxError。

TypeError

当一个操作或函数被应用于类型不适当的对象时将被引发。

>>> int([1])
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-12-4b50125e83a8> in <module>
----> 1 int([1])

TypeError: int() argument must be a string, a bytes-like object or a number, not 'list'

传入参数的类型错误 (例如在要求 int 时却传入了 list) 会返回 TypeError。

ValueError

当操作或函数接收到具有正确类型但值不适合的参数。

>>> int("a")
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-11-d9136db7b558> in <module>
----> 1 int("a")

ValueError: invalid literal for int() with base 10: 'a'
处理异常

很多时候异常信息都不是很清楚,并且出现异常的话会打断程序的运行。而我们希望收到清楚的异常信息,并且能够继续运行程序,我们可以使用 try 语句来处理,语法如下:

try:
    动作
except:
    动作

我们来看一个示例:

>>> while True:
...     try:
...         x = int(input("输入一个数字: "))
...         break
...     except ValueError:
...         print("输入的不是数字。再试一次...")
输入一个数字: a
输入的不是数字。再试一次...
输入一个数字: b
输入的不是数字。再试一次...
输入一个数字: 1

正常情况下,程序会返回异常并终止程序,而用了 try 语句以后仅仅返回异常信息,程序继续运行。

抛出异常

raise 语句允许强制产生例外。

>>> raise ValueError("出错了!")
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-21-a7a668f1a77f> in <module>
----> 1 raise ValueError("出错了!")

ValueError: 出错了!

善用异常可以在出现异常的时候定制信息、继续程序。


练习(写出生成如下变量的代码或结果):

给定了两个列表(lst1 包含 lst2),利用列表解析式找出 lst1 里有但是 lst2 里没有的元素。
lst1 = [“cat”, “dog”, “bird”, “fish”, “tiger”, “lion”]
lst2 = [“cat”, "dog’]

答案下篇文章公布。欢迎把答案留言与老宅交流、互动!


上一篇练习的答案:

>>> def BMI(height, weight):
...     BMI = weight / height ** 2
...     if BMI < 18.5:
...         print("偏瘦")
...     elif BMI < 25:
...         print("正常")
...     elif BMI < 30:
...         print("偏胖")
...     else:
...         print("肥胖")
>>> BMI(height=1.75, weight=65)
>>> BMI(height = 1.8, weight = 90)
>>> BMI(1.6, 45)
正常
偏胖
偏瘦
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值