前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【数据分析从入门到“入坑“系列】利用Python学习数据分析-Python函数-2

【数据分析从入门到“入坑“系列】利用Python学习数据分析-Python函数-2

作者头像
天道Vax的时间宝藏
发布2021-08-11 15:58:53
5860
发布2021-08-11 15:58:53
举报

生成器

能以一种一致的方式对序列进行迭代(比如列表中的对象或文件中的行)是Python的一个重要特点。这是通过一种叫做迭代器协议(iterator protocol,它是一种使对象可迭代的通用方式)的方式实现的,一个原生的使对象可迭代的方法。比如说,对字典进行迭代可以得到其所有的键:

代码语言:javascript
复制
In [180]: some_dict = {'a': 1, 'b': 2, 'c': 3}
​
In [181]: for key in some_dict:
   .....:     print(key)
a
b
c

当你编写for key in some_dict时,Python解释器首先会尝试从some_dict创建一个迭代器:

代码语言:javascript
复制
In [182]: dict_iterator = iter(some_dict)
​
In [183]: dict_iterator
Out[183]: <dict_keyiterator at 0x7fbbd5a9f908>

迭代器是一种特殊对象,它可以在诸如for循环之类的上下文中向Python解释器输送对象。大部分能接受列表之类的对象的方法也都可以接受任何可迭代对象。比如min、max、sum等内置方法以及list、tuple等类型构造器:

代码语言:javascript
复制
In [184]: list(dict_iterator)
Out[184]: ['a', 'b', 'c']

生成器(generator)是构造新的可迭代对象的一种简单方式。一般的函数执行之后只会返回单个值,而生成器则是以延迟的方式返回一个值序列,即每返回一个值之后暂停,直到下一个值被请求时再继续。要创建一个生成器,只需将函数中的return替换为yeild即可:

代码语言:javascript
复制
def squares(n=10):
    print('Generating squares from 1 to {0}'.format(n ** 2))
    for i in range(1, n + 1):
        yield i ** 2

调用该生成器时,没有任何代码会被立即执行:

代码语言:javascript
复制
In [186]: gen = squares()
​
In [187]: gen
Out[187]: <generator object squares at 0x7fbbd5ab4570>

直到你从该生成器中请求元素时,它才会开始执行其代码:

代码语言:javascript
复制
In [188]: for x in gen:
   .....:     print(x, end=' ')
Generating squares from 1 to 100
1 4 9 16 25 36 49 64 81 100

生成器表达式

另一种更简洁的构造生成器的方法是使用生成器表达式(generator expression)。这是一种类似于列表、字典、集合推导式的生成器。其创建方式为,把列表推导式两端的方括号改成圆括号:

代码语言:javascript
复制
In [189]: gen = (x ** 2 for x in range(100))
​
In [190]: gen
Out[190]: <generator object <genexpr> at 0x7fbbd5ab29e8>

它跟下面这个冗长得多的生成器是完全等价的:

代码语言:javascript
复制
def _make_gen():
    for x in range(100):
        yield x ** 2
gen = _make_gen()

生成器表达式也可以取代列表推导式,作为函数参数:

代码语言:javascript
复制
In [191]: sum(x ** 2 for x in range(100))
Out[191]: 328350
​
In [192]: dict((i, i **2) for i in range(5))
Out[192]: {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

itertools模块

标准库itertools模块中有一组用于许多常见数据算法的生成器。例如,groupby可以接受任何序列和一个函数。它根据函数的返回值对序列中的连续元素进行分组。下面是一个例子:

代码语言:javascript
复制
In [193]: import itertools
​
In [194]: first_letter = lambda x: x[0]
​
In [195]: names = ['Alan', 'Adam', 'Wes', 'Will', 'Albert', 'Steven']
​
In [196]: for letter, names in itertools.groupby(names, first_letter):
   .....:     print(letter, list(names)) # names is a generator
A ['Alan', 'Adam']
W ['Wes', 'Will']
A ['Albert']
S ['Steven']

表3-2中列出了一些我经常用到的itertools函数。建议参阅Python官方文档,进一步学习。

错误和异常处理

优雅地处理Python的错误和异常是构建健壮程序的重要部分。在数据分析中,许多函数函数只用于部分输入。例如,Python的float函数可以将字符串转换成浮点数,但输入有误时,有ValueError错误:

代码语言:javascript
复制
In [197]: float('1.2345')
Out[197]: 1.2345
​
In [198]: float('something')
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-198-439904410854> in <module>()
----> 1 float('something')
ValueError: could not convert string to float: 'something'

假如想优雅地处理float的错误,让它返回输入值。我们可以写一个函数,在try/except中调用float:

代码语言:javascript
复制
def attempt_float(x):
    try:
        return float(x)
    except:
        return x

当float(x)抛出异常时,才会执行except的部分:

代码语言:javascript
复制
In [200]: attempt_float('1.2345')
Out[200]: 1.2345
​
In [201]: attempt_float('something')
Out[201]: 'something'

你可能注意到float抛出的异常不仅是ValueError:

代码语言:javascript
复制
In [202]: float((1, 2))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-202-842079ebb635> in <module>()
----> 1 float((1, 2))
TypeError: float() argument must be a string or a number, not 'tuple'

你可能只想处理ValueError,TypeError错误(输入不是字符串或数值)可能是合理的bug。可以写一个异常类型:

代码语言:javascript
复制
def attempt_float(x):
    try:
        return float(x)
    except ValueError:
        return x

然后有:

代码语言:javascript
复制
In [204]: attempt_float((1, 2))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-204-9bdfd730cead> in <module>()
----> 1 attempt_float((1, 2))
<ipython-input-203-3e06b8379b6b> in attempt_float(x)
      1 def attempt_float(x):
      2     try:
----> 3         return float(x)
      4     except ValueError:
      5         return x
TypeError: float() argument must be a string or a number, not 'tuple'

可以用元组包含多个异常:

代码语言:javascript
复制
def attempt_float(x):
    try:
        return float(x)
    except (TypeError, ValueError):
        return x

某些情况下,你可能不想抑制异常,你想无论try部分的代码是否成功,都执行一段代码。可以使用finally:

代码语言:javascript
复制
f = open(path, 'w')
​
try:
    write_to_file(f)
finally:
    f.close()

这里,文件处理f总会被关闭。相似的,你可以用else让只在try部分成功的情况下,才执行代码:

代码语言:javascript
复制
f = open(path, 'w')
​
try:
    write_to_file(f)
except:
    print('Failed')
else:
    print('Succeeded')
finally:
    f.close()

IPython的异常

如果是在%run一个脚本或一条语句时抛出异常,IPython默认会打印完整的调用栈(traceback),在栈的每个点都会有几行上下文:

代码语言:javascript
复制
In [10]: %run examples/ipython_bug.py
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
/home/wesm/code/pydata-book/examples/ipython_bug.py in <module>()
     13     throws_an_exception()
     14
---> 15 calling_things()
​
/home/wesm/code/pydata-book/examples/ipython_bug.py in calling_things()
     11 def calling_things():
     12     works_fine()
---> 13     throws_an_exception()
     14
     15 calling_things()
​
/home/wesm/code/pydata-book/examples/ipython_bug.py in throws_an_exception()
      7     a = 5
      8     b = 6
----> 9     assert(a + b == 10)
     10
     11 def calling_things():
​
AssertionError:

自身就带有文本是相对于Python标准解释器的极大优点。你可以用魔术命令%xmode,从Plain(与Python标准解释器相同)到Verbose(带有函数的参数值)控制文本显示的数量。后面可以看到,发生错误之后,(用%debug或%pdb magics)可以进入stack进行事后调试。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-06-20 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 生成器
  • 生成器表达式
  • itertools模块
  • 错误和异常处理
  • IPython的异常
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档