全部版块 我的主页
论坛 数据科学与人工智能 数据分析与数据科学 数据分析与数据挖掘
1999 1
2020-10-15
Python 3.9:不错的新功能供您尝试
Python 3.9在这里!过去一年来,来自世界各地的志愿者一直在致力于Python的改进。尽管beta版本已经存在了一段时间,但python 3.9的第一个正式版本于2020年10月5日发布。
每个Python版本都包含新的,改进的和不推荐使用的功能,Python 3.9也不例外。该文档提供了更改的完整列表。下面,您将深入了解最新版本的Python带来的最酷的功能。
在本教程中,您将了解:
时区访问和计算
有效地合并和更新字典
使用基于表达式的装饰器
组合类型提示和其他注释
要自己尝试这些新功能,您需要安装Python 3.9。您可以从Python主页下载并安装它。或者,您可以使用官方Docker image进行尝试。有关更多详细信息,请参见在Docker中运行Python版本:如何尝试最新的Python版本。
正确的时区支持
Python通过datetime标准库中的模块为使用日期和时间提供了广泛的支持。但是,对于时区的工作一直缺乏支持。到目前为止,建议使用时区的方法是使用第三方库,例如dateutil。
在纯Python中使用时区的最大挑战在于,您必须自己实现时区规则。Adatetime支持设置时区,但仅UTC可用。其他时区需要在抽象tzinfo基类之上实现。
访问时区
您可以从库中获取UTC时间戳,datetime如下所示:
>>> from datetime import datetime
>>> datetime.now(tz=timezone.utc)
datetime.datetime(2020
请注意,生成的时间戳记可以识别时区。它具有由指定的附加时区tzinfo。没有任何时区信息的时间戳称为朴素。
Paul Ganssle担任了dateutil多年的维护者。他于2019年加入Python核心开发人员,并帮助添加了一个新的zoneinfo标准库,该标准库使使用时区更加方便。
zoneinfo提供对Internet号码分配机构(IANA)时区数据库的访问。IANA每年都会多次更新其数据库,这是时区信息的最权威来源。
使用zoneinfo,您可以获得一个描述数据库中任何时区的对象:
>>> from zoneinfo import ZoneInfo
>>> ZoneInfo("America/Vancouver")
zoneinfo.ZoneInfo(key='America/Vancouver')
您可以使用几个键之一访问时区。在这种情况下,请使用"America/Vancouver"。
注意: zoneinfo使用本地计算机上的IANA时区数据库。您可能没有任何这样的数据库,或者zoneinfo将无法找到它,尤其是在Windows上。如果您收到类似以下的错误,则表明zoneinfo找不到时区数据库:
>>> from zoneinfo import ZoneInfo
>>> ZoneInfo("America/Vancouver")
Traceback (most recent call last):
  File "<stdin>"
ZoneInfoNotFoundError: 'No time zone found with key America/Vancouver'
IANA时区数据库的Python实现可在PyPI上以的形式获得tzdata。您可以使用安装pip:
$ python -m pip install tzdata
一旦tzdata安装,zoneinfo应该能够读取有关所有支持的时区的信息。tzdata由Python核心团队维护。请注意,您需要使软件包保持更新,以便可以访问IANA时区数据库中的最新更改。
您可以使用函数的tz或tzinfo参数制作时区感知的时间戳datetime:
>>> from datetime import datetime
>>> from zoneinfo import ZoneInfo
>>> datetime.now(tz=ZoneInfo("Europe/Oslo"))
datetime.datetime(2020
                  tzinfo=zoneinfo.ZoneInfo(key='Europe/Oslo'))
>>> datetime(2020
datetime.datetime(2020
                  tzinfo=zoneinfo.ZoneInfo(key='America/Vancouver'))
将时区与时间戳一起记录对于保持记录非常有用。它还使在时区之间进行转换变得很方便:
>>> from datetime import datetime
>>> from zoneinfo import ZoneInfo
>>> release = datetime(2020
>>> release.astimezone(ZoneInfo("Europe/Oslo"))
datetime.datetime(2020
                  tzinfo=zoneinfo.ZoneInfo(key='Europe/Oslo'))
请注意,奥斯陆的时间比温哥华的时间晚九小时。
调查时区
IANA时区数据库非常庞大。您可以使用列出所有可用的时区zoneinfo.available_timezones():
>>> import zoneinfo
>>> zoneinfo.available_timezones()
{'America/St_Lucia'
>>> len(zoneinfo.available_timezones())
609
数据库中的时区数量可能会因您的安装而异。在此示例中,您可以看到609列出了时区名称。每个时区都记录了已发生的历史更改,您可以更仔细地查看每个时区。
基里蒂马蒂(Kiritimati)也被称为圣诞节岛,目前位于世界最西端的时区UTC + 14。并非总是如此。在1995年之前,该岛位于UTC-10的国际日期变更线的另一侧。为了越过日期线,Kiritimati完全跳过了1994年12月31日。
您可以通过仔细查看"Pacific/Kiritimati"时区对象来了解这种情况是如何发生的:
>>> from datetime import datetime
>>> from zoneinfo import ZoneInfo
>>> hour = timedelta(hours=1)
>>> tz_kiritimati = ZoneInfo("Pacific/Kiritimati")
>>> ts = datetime(1994
>>> ts.astimezone(tz_kiritimati)
datetime.datetime(1994
                  tzinfo=zoneinfo.ZoneInfo(key='Pacific/Kiritimati'))
>>> (ts + 1 * hour).astimezone(tz_kiritimati)
datetime.datetime(1995
                  tzinfo=zoneinfo.ZoneInfo(key='Pacific/Kiritimati'))
新年从1994年12月30日23:00在基里蒂马蒂(Kiritimati)的时钟读出一小时后开始。1994年12月31日,从未发生!
您还可以看到与UTC的偏移量已更改:
>>> tz_kiritimati.utcoffset(datetime(1994
-10.0
>>> tz_kiritimati.utcoffset(datetime(1995
14.0
.utcoffset()返回timedelta。计算给定代表多少小时的最有效方法timedelta是将其除以timedelta代表一个小时。
关于时区还有许多其他怪异的故事。Paul Ganssle在他的PyCon 2019演讲中介绍了其中的一些内容,《与时区一起工作:您希望知道的一切》。查看是否可以在时区数据库中找到其他任何跟踪。
移除广告
采用最佳实践
使用时区可能很棘手。但是,借助zoneinfo标准库中的可用性,它变得更容易了。在处理日期和时间时,请牢记以下几点建议:
诸如会议时间,火车出发时间或音乐会之类的民事时间最好存储在其本地时区。您通常可以通过将朴素的时间戳记与时区的IANA密钥一起存储来完成此操作。将民事时间存储为字符串的一个示例是"2020-10-05T14:00:00
时间戳代表特定时间,通常记录事件的顺序。计算机日志就是一个例子。您不希望仅因为您的时区从夏令时更改为标准时间而使日志混乱。通常,您会将这些类型的时间戳记存储为UTC中的原始日期时间。
由于IANA时区数据库一直在更新,因此您应注意保持本地时区数据库同步。如果您正在运行对时区敏感的任何应用程序,则这尤其重要。
在Mac和Linux上,通常可以信任系统以保持本地数据库更新。如果您依赖该tzdata软件包,则应记住不时更新它。特别是,您多年不应该将其固定在一个特定的版本上。
像这样的名称"America/Vancouver"使您可以明确访问给定的时区。但是,在向用户传达时区感知的日期时间时,最好使用常规时区名称。这些.tzname()在时区对象上可用:
>>> from datetime import datetime
>>> from zoneinfo import ZoneInfo
>>> tz = ZoneInfo("America/Vancouver")
>>> release = datetime(2020
>>> f"Release date: {release:%b %d
'Release date: Oct 05
您需要提供一个时间戳记.tzname()。这是必需的,因为时区的名称可能会随时间而变化,例如夏时制:
>>> tz.tzname(datetime(2021
'PST'
冬季,温哥华采用太平洋标准时间(PST),夏季则采用太平洋夏令时间(PDT)。
zoneinfo仅在Python 3.9及更高版本的标准库中可用。但是,如果您使用的是Python的早期版本,则仍然可以利用zoneinfo。反向端口在PyPI上可用,并且可以通过以下方式安装pip:
$ python -m pip install backports.zoneinfo
然后,您可以在导入时使用以下习惯用法zoneinfo:
try:
    import zoneinfo
except ImportError:
    from backports import zoneinfo
这使您的程序与3.6及更高版本的所有Python版本兼容。有关的更多详细信息,请参见PEP 615zoneinfo。
辞书更简单的更新
字典是Python中基本的数据结构之一。它们在语言中到处都有使用,并且随着时间的推移已经得到了相当优化。
可以合并两种字典的几种方法。但是,该语法有点含糊或繁琐:
>>> pycon = {2016: "Portland"
>>> europython = {2017: "Rimini"
>>> {**pycon
{2016: 'Portland'
>>> merged = pycon.copy()
>>> for key
...     merged[key] = value
...
>>> merged
{2016: 'Portland'
这两种方法都合并了字典而不更改原始数据。需要注意的是"Cleveland"已被覆盖,通过"Edinburgh"在merged。您也可以就地更新字典:
>>> pycon.update(europython)
>>> pycon
{2016: 'Portland'
不过,这会更改您的原始词典。请记住,.update()它不会返回更新的字典,因此,在.update()不影响原始数据的情况下进行巧妙的使用尝试的效果并不理想:
>>> pycon = {2016: "Portland"
>>> europython = {2017: "Rimini"
>>> merged = pycon.copy().update(europython)  # Does NOT work
>>> print(merged)
None
请注意,这merged是None,当两个字典合并时,该结果已被丢弃。您可以使用Python 3.8中引入的walrus运算符(:=)来完成这项工作:
>>> (merged := pycon.copy()).update(europython)
>>> merged
{2016: 'Portland'
但是,这不是一个特别可读或令人满意的解决方案。
基于PEP 584,新版本的Python引入了两个新的字典运算符:union(|)和就地union(|=)。您可以使用|合并两个字典,同时|=将在适当位置更新字典:
>>> pycon = {2016: "Portland"
>>> europython = {2017: "Rimini"
>>> pycon | europython
{2016: 'Portland'
>>> pycon |= europython
>>> pycon
{2016: 'Portland'
如果d1和d2是两个字典,则d1 | d2与相同{**d1
使用的优点之一|是,它适用于不同的类似于字典的类型,并通过合并保持类型:
>>> from collections import defaultdict
>>> europe = defaultdict(lambda: ""
>>> africa = defaultdict(lambda: ""
>>> europe | africa
defaultdict(<function <lambda> at 0x7f0cb42a6700>
  {'Norway': 'Oslo'
>>> {**europe
{'Norway': 'Oslo'
defaultdict当您想有效处理丢失的密钥时,可以使用a 。请注意,|保留defaultdict,而不保留{**europe
|字典的+工作方式和列表的工作方式之间有一些相似之处。实际上,最初也建议+运算符合并字典。当您查看就地运算符时,这种对应关系变得更加明显。
的基本用途|=是在适当位置更新字典,类似于.update():
>>> libraries = {
...     "collections": "Container datatypes"
...     "math": "Mathematical functions"
... }
>>> libraries |= {"zoneinfo": "IANA time zone support"}
>>> libraries
{'collections': 'Container datatypes'
'zoneinfo': 'IANA time zone support'}
当您将合并字典时|,两个字典都必须具有正确的字典类型。另一方面,就地运算符(|=)很乐意使用任何类似于字典的数据结构:
>>> libraries |= [("graphlib"
>>> libraries
{'collections': 'Container datatypes'
'zoneinfo': 'IANA time zone support'
'graphlib': 'Functionality for graph-like structures'}
在此示例中,您libraries从2元组的列表中进行更新。当您要合并的两个字典中有重叠的键时,将保留最后一个值:
>>> asia = {"Georgia": "Tbilisi"
>>> usa = {"Missouri": "Jefferson City"
>>> asia | usa
{'Georgia': 'Atlanta'
>>> usa | asia
{'Missouri': 'Jefferson City'
在第一个示例中,"Georgia"指向"Atlanta"因为usa是合并中的最后一个字典。"Tbilisi"来自的值asia已被覆盖。请注意,键"Georgia"仍然是结果字典中的第一个元素,因为它是中的第一个元素asia。反转合并顺序会同时更改的位置和值"Georgia"。
运营商|和|=已加入不仅定期字典也让许多类似字典类,包括UserDict,ChainMap,OrderedDict,defaultdict,WeakKeyDictionary,WeakValueDictionary,_Environ,和MappingProxyType。他们没有被添加到抽象基类Mapping或MutableMapping。该Counter容器已|用于查找最大计数。这没有改变。
你可以改变的行为|,并|=通过实施.__or__()和.__ior__()分别。有关更多详细信息,请参见PEP 584。

关注 CDA人工智能学院 ,回复“录播”获取更多人工智能精选直播视频!


二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

全部回复
2020-11-6 20:15:09
3.9不支持Win7了。
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

相关推荐
栏目导航
热门文章
推荐文章

说点什么

分享

扫码加好友,拉您进群
各岗位、行业、专业交流群