Following system colour scheme - Python 增强提案 Selected dark colour scheme - Python 增强提案 Selected light colour scheme - Python 增强提案

Python 增强提案

PEP 495 – 本地时间歧义

作者:
Alexander Belopolsky <alexander.belopolsky at gmail.com>, Tim Peters <tim.peters at gmail.com>
讨论邮件列表:
Datetime-SIG 列表
状态:
最终
类型:
标准跟踪
创建:
2015年8月2日
Python 版本:
3.6
决议:
Datetime-SIG 消息

目录

摘要

此 PEP 向 datetime.timedatetime.datetime 类的实例添加了一个新的属性 fold,该属性可用于区分本地时间相同的两个时间点。fold 属性的允许值为 0 和 1,其中 0 对应于较早的时间,1 对应于模棱两可的本地时间的两个可能读数中较晚的时间。

基本原理

在世界上的大多数地方,过去和将来都存在本地时钟被拨回的时候。[1] 在这些时间里,会出现本地时钟在同一天显示相同时间两次的时间间隔。在这些情况下,本地时钟上显示的信息(或存储在 Python datetime 实例中)不足以识别特定时间点。提出的解决方案是向 datetime 实例添加一个属性,该属性取值 0 和 1,用于枚举两个模棱两可的时间。

A cartoon of a strong man struggling to stop the hands of a large clock. The caption reads: You can't stop time... but you can turn it back one hour at 2 a.m. Oct. 28 when daylight-saving time ends and standard time begins."

术语

当时钟被拨回时,我们说时间中创建了一个折叠 [2]。当时钟被拨快时,就会创建一个间隙。落在折叠中的本地时间称为模棱两可的。落在间隙中的本地时间称为缺失的

提案

“fold” 属性

我们建议向 datetime.timedatetime.datetime 类的实例添加一个名为 fold 的属性。对于所有实例,此属性的值应为 0,除了表示模棱两可情况下第二个(按时间顺序)时间点的实例。对于这些实例,该值将为 1。[3]

受影响的 API

属性

datetime.timedatetime.datetime 类的实例将获得一个新的属性 fold,它有两个可能的值:0 和 1。

构造函数

datetime.timedatetime.datetime 类的 __new__ 方法将获得一个名为 fold 的新的仅限关键字参数,其默认值为 0。 fold 参数的值将用于初始化返回实例中 fold 属性的值。

方法

datetime.timedatetime.datetime 类的 replace() 方法将获得一个名为 fold 的新的仅限关键字参数。它的行为类似于其他 replace() 参数:如果指定了 fold 参数并赋予其 0 或 1 的值,则 replace() 返回的新实例的 fold 属性将设置为该值。在 CPython 中,fold 的任何非整数值都会引发 TypeError,但其他实现可能会允许值 None 的行为与未给出 fold 时相同。[4](这是对跨 Python 实现的此方法其他位置的 None 参数处理方式的现有差异的认可;它并非意在为将来对 fold=None 的替代解释敞开大门。)如果未指定 fold 参数,则原始的 fold 属性值将复制到结果中。

C-API

将定义访问宏以从 PyDateTime_DateTimePyDateTime_Time 对象中提取 fold 的值。

int PyDateTime_DATE_GET_FOLD(PyDateTime_DateTime *o)

fold 的值作为 C int 返回。

int PyDateTime_TIME_GET_FOLD(PyDateTime_Time *o)

fold 的值作为 C int 返回。

将定义新的构造函数,这些构造函数将采用一个额外的参数来指定在创建的实例中 fold 的值

PyObject* PyDateTime_FromDateAndTimeAndFold(
    int year, int month, int day, int hour, int minute,
    int second, int usecond, int fold)

返回一个具有指定年份、月份、日期、小时、分钟、秒、微秒和折叠的 datetime.datetime 对象。

PyObject* PyTime_FromTimeAndFold(
    int hour, int minute, int second, int usecond, int fold)

返回一个具有指定小时、分钟、秒、微秒和折叠的 datetime.time 对象。

受影响的行为

现在几点?

不带参数调用的 datetime.now() 方法在返回系统本地时间折叠中的两个模棱两可时间中的第二个时,将设置 fold=1。当使用 tzinfo 参数调用时,fold 的值将由 tzinfo.fromutc() 实现确定。当将 datetime.timezone 类(stdlib 的固定偏移量 tzinfo 子类,例如 datetime.timezone.utc)的实例作为 tzinfo 传递时,返回的 datetime 实例将始终具有 fold=0datetime.utcnow() 方法不受影响。

从朴素时间转换为感知时间

提议了一项新功能,以促进从朴素 datetime 实例到感知时间的转换。

astimezone() 方法现在可以用于朴素的 self。在这种情况下,将假定系统本地时区,并且将使用 fold 标志来确定模棱两可的情况下哪个本地时区有效。

例如,在设置为 US/Eastern 时区的系统上

>>> dt = datetime(2014, 11, 2, 1, 30)
>>> dt.astimezone().strftime('%D %T %Z%z')
'11/02/14 01:30:00 EDT-0400'
>>> dt.replace(fold=1).astimezone().strftime('%D %T %Z%z')
'11/02/14 01:30:00 EST-0500'

这意味着 datetime.now(tz) 完全等效于 datetime.now().astimezone(tz)(假设 tz 是 PEP 后 tzinfo 实现的实例,即正确处理和设置 fold 的实例)。

从纪元开始的 POSIX 秒数转换为感知时间

datetime.datetimefromtimestamp() 静态方法将在返回的对象中适当地设置 fold 属性。

例如,在设置为 US/Eastern 时区的系统上

>>> datetime.fromtimestamp(1414906200)
datetime.datetime(2014, 11, 2, 1, 30)
>>> datetime.fromtimestamp(1414906200 + 3600)
datetime.datetime(2014, 11, 2, 1, 30, fold=1)

从感知时间转换为纪元开始的 POSIX 秒数

datetime.datetimetimestamp() 方法将仅当这些实例表示模棱两可或缺失时间时,才会为仅 fold 属性值不同的 datetime.datetime 实例返回不同的值。

datetime.datetime 实例 dt 表示模棱两可的时间时,存在两个值 s0s1,使得

datetime.fromtimestamp(s0) == datetime.fromtimestamp(s1) == dt

(这是因为 == 忽略了 fold 的值 - 请参见下文。)

在这种情况下,如果 dt.fold == 0,则 dt.timestamp() 将返回 s0s1 中较小的值,否则返回较大的值。

例如,在设置为 US/Eastern 时区的系统上

>>> datetime(2014, 11, 2, 1, 30, fold=0).timestamp()
1414906200.0
>>> datetime(2014, 11, 2, 1, 30, fold=1).timestamp()
1414909800.0

datetime.datetime 实例 dt 表示缺失时间时,不存在这样的值 s

datetime.fromtimestamp(s) == dt

但我们可以形成两个“了解一下”的 s 值,它们相差的时间间隔(以秒为单位)。一个是 s 的值,它对应于在时区中 dt,其中 UTC 偏移量始终与时间间隔之前的偏移量相同,另一个是类似的值,但在 UTC 偏移量始终与时间间隔之后的偏移量相同的时区中。

对于给定的缺失的 dtdt.timestamp() 返回的值将是这两个“了解一下”值中较大的值,如果 dt.fold == 0,否则为较小的值。(这不是打字错误 - 它有意与模棱两可时间规则相反。)

例如,在设置为 US/Eastern 时区的系统上

>>> datetime(2015, 3, 8, 2, 30, fold=0).timestamp()
1425799800.0
>>> datetime(2015, 3, 8, 2, 30, fold=1).timestamp()
1425796200.0

感知时间 datetime 实例

tzinfo 的 PEP 之前实现的用户将不会看到其已知日期时间实例的行为有任何变化。仅 fold 属性的值不同的两个这样的实例,除了显式访问 fold 值之外,无法通过任何其他方式区分。(这是因为这些 PEP 之前的实现未使用 fold 属性。)

另一方面,如果对象的 tzinfo 设置为支持折叠的实现,那么在折叠或间隙中,fold 的值将影响几个方法的结果:utcoffset()dst()tzname()astimezone()strftime()(如果在格式规范中使用了“%Z”或“%z”指令)、isoformat()timetuple()

组合和拆分日期和时间

datetime.datetime.combine() 方法会将 fold 属性的值复制到生成的 datetime.datetime 实例。

datetime.datetime.time() 方法会将 fold 属性的值复制到生成的 datetime.time 实例。

Pickle

折叠属性的值仅保存在使用协议版本 4(在 Python 3.4 中引入)或更高版本创建的 pickle 中。

datetime.datetimedatetime.time 对象的 pickle 大小不会改变。fold 值将编码在 datetime.datetime pickle 有效负载的第 3 个字节的第一个比特中;以及 datetime.time 有效负载的第一个字节的第一个比特中。在当前实现中,这些字节用于存储月份 (1-12) 和小时 (0-23) 值,并且第一个比特始终为 0。我们选择这些字节是因为它们是当前 unpickle 代码检查的唯一字节。因此,在 PEP 之前的 Python 中加载 PEP 之后的 fold=1 pickle 将导致异常,而不是具有超出范围组件的实例。

标准库中 tzinfo 的实现

本 PEP 中没有提出 datetime.tzinfo 抽象类的任何新实现。现有的(固定偏移)时区不会引入模棱两可的本地时间,并且无论 fold 的值如何,它们的 utcoffset() 实现都将返回与现在相同的常数值。

抽象 datetime.tzinfo 类中 fromutc() 的基本实现不会改变。它目前在标准库中没有任何地方使用,因为唯一包含的 tzinfo 实现(实现固定偏移时区的 datetime.timezone 类)覆盖了 fromutc()。保持默认实现不变的好处是,继承默认 fromutc() 的 PEP 之前的第三方实现不会意外受到影响。

新的 tzinfo 实现指南

想要支持可变 UTC 偏移量(由于夏令时和其他原因)的具体 datetime.tzinfo 子类的实现者应遵循以下指南。

无知是福

utcoffset()tzname()dst() 方法的新实现应该忽略 fold 的值,除非它们在模棱两可或缺失的时间上被调用。

在折叠中

新的子类应该覆盖基类 fromutc() 方法并实现它,以便在所有两个不同的 UTC 时间 u0u1u0 < u1)对应于相同的本地时间 t 的情况下,fromutc(u0) 将返回一个 fold=0 的实例,而 fromutc(u1) 将返回一个 fold=1 的实例。在所有其他情况下,返回的实例都应该具有 fold=0

utcoffset()tzname()dst() 方法应该使用折叠属性的值来确定一个原本模棱两可的时间 t 是否对应于转换前或转换后的时间。根据定义,在任何导致折叠的转换之前,utcoffset() 较大,之后较小。tzname()dst() 返回的值可能取决于或可能不取决于 fold 属性的值,具体取决于转换的类型。

Diagram of relationship between UTC and local time around a fall-back transition – see full description on page.

上图说明了在回拨转换前后 UTC 时间和本地时间之间的关系。锯齿线是 fromutc() 实现的函数的图形。UTC 轴上与转换点相邻且大小为转换时的时间偏移量的两个区间映射到本地轴上的同一区间。 fromutc() 方法的新实现应该在 self 位于 UTC 轴上黄色标记的区域时将折叠属性设置为 1。(所有区间都应被视为左侧闭合,右侧打开。)

注意间隙

fromutc() 方法绝不应产生间隙中的时间。

如果在落在间隙中的本地时间上调用 utcoffset()tzname()dst() 方法,则如果 fold=0,则应使用转换前的规则。否则,应使用转换后的规则。

Diagram of relationship between UTC and local time around a spring-forward transition – see full description on page.

上图说明了在顺拨转换前后 UTC 时间和本地时间之间的关系。在转换时,本地时钟将向前跳动,跳过间隙中的时间。为了确定 utcoffset()tzname()dst() 的值,转换前的线将向前延伸以找到对应于 fold=0 的间隙中的时间的 UTC 时间,而对于 fold=1 的实例,转换后的线将向后延伸。

转换时的规则总结

在模棱两可/缺失的时间上,utcoffset() 应根据下表返回相应的值

fold=0 fold=1
折叠 oldoff newoff = oldoff - delta
间隙 oldoff newoff = oldoff + delta

其中 oldoffnewoff)是转换前(后)的 UTC 偏移量,delta 是折叠或间隙的绝对大小。

请注意,折叠属性的解释在折叠和间隙情况下是一致的。在这两种情况下,fold=0fold=1)表示使用转换前(后)的 fromutc() 线来查找 UTC 时间。仅在“折叠”情况下,UTC 时间 u0u1 是方程 fromutc(u) == t 的“真实”解,而在“间隙”情况下,它们是“虚构”解。

夏令时转换

在 DST 开始时引入的缺失时间上,utcoffset()dst() 方法返回的值应如下所示

fold=0 fold=1
utcoffset() stdoff stdoff + dstoff
dst() zero dstoff

在 DST 结束时引入的模棱两可时间上,utcoffset()dst() 方法返回的值应如下所示

fold=0 fold=1
utcoffset() stdoff + dstoff stdoff
dst() dstoff zero

其中stdoff是标准(非夏令时)偏移量,dstoff是夏令时校正值(通常为dstoff = timedelta(hours=1)),zero = timedelta(0)

时间算术和比较运算符

数学方面,他胜过
第谷·布拉赫或厄拉·帕特
因为他,通过几何比例,
可以计算啤酒罐的大小;
用正弦和正切直接解决,
面包或黄油是否缺斤少两,
并巧妙地告诉一天中的几点
时钟用代数来报时。
——塞缪尔·巴特勒的《胡迪布拉斯》

对于所有使用朴素日期时间实例的操作,fold属性的值都将被忽略。因此,仅fold值不同的朴素datetime.datetimedatetime.time实例将被视为相等。需要区分此类实例的应用程序应显式检查fold的值,或将这些实例转换为没有模糊时间(例如UTC)的时区。

每当将timedelta加到或减去可能为已知或朴素的datetime实例时,fold的值也将被忽略。即使原始datetime实例具有fold=1,将timedelta加到(从)datetime的结果始终将fold设置为0。

对于日期时间实例ts,计算差值t - s的方式没有提出任何更改。如果两个实例都是朴素的,或者t.tzinfos.tzinfo是同一个实例(t.tzinfo is s.tzinfo计算结果为True),则t - s是一个timedelta d,使得s + d == t。如上一段所述,timedelta加法会忽略foldtzinfo属性,区域内或朴素日期时间减法也是如此。

朴素和区域内比较将忽略fold的值并返回与现在相同的结果。(这是保持向后兼容性的唯一方法。如果您需要使用fold的已知区域内比较,请先将双方都转换为UTC。)

区域间减法将按现在的定义进行:t - s计算为(t - t.utcoffset()) - (s - s.utcoffset()).replace(tzinfo=t.tzinfo),但结果将取决于t.folds.fold的值,前提是t.tzinfos.tzinfo是PEP后的。[5]

感知时间 datetime 的相等比较

已知日期时间比较运算符的工作方式与现在相同,其结果会间接受到fold值的影响,只要其中一个操作数的utcoffset()值依赖于它,就有一个例外。每当区域间比较中的一个或两个操作数使得其utcoffset()依赖于其fold属性的值时,结果为False[6]

形式上,当t.tzinfo is s.tzinfo计算结果为False时,t == s可以定义如下。令toutc(t, fold)为一个函数,该函数接受一个已知日期时间实例t并返回一个表示UTC中相同时间的朴素实例,假设fold具有给定值。

def toutc(t, fold):
    u = t - t.replace(fold=fold).utcoffset()
    return u.replace(tzinfo=None)

然后t == s等价于

toutc(t, fold=0) == toutc(t, fold=1) == toutc(s, fold=0) == toutc(s, fold=1)

向后和向前兼容性

此提案对不显式读取fold标志或使用执行此操作的tzinfo实现的程序的影响很小。对于此类程序,唯一可见的变化是,到POSIX时间戳的转换和从POSIX时间戳的转换现在将正确往返(最多浮点数舍入)。可能需要修改实现了旧错误行为解决方法的程序。

旧程序生成的pickle将保持完全向前兼容。只有在新的版本中以pickle形式保存的fold=1的datetime/time实例将无法被旧版本的Python读取。具有fold=0(默认值)的实例的pickle将保持不变。

问答

为什么不将新标志称为“isdst”?

非技术性答案

  • 爱丽丝:鲍勃——我们明天凌晨1:30举行一次观星派对吧!
  • 鲍勃:我是否应该最初假设指定时间是否处于夏令时?
  • 爱丽丝:啊?

  • 鲍勃:爱丽丝——我们明天凌晨1:30举行一次观星派对吧!
  • 爱丽丝:你知道,鲍勃,明天凌晨1:30会发生两次。你指的是哪一次?
  • 鲍勃:我没有想过,但让我们选择第一次。

(相同的人物,一小时后)


  • 鲍勃:爱丽丝——我的这个Py-O-Clock小玩意儿要求我在设置明天凌晨1:30时在fold=0和fold=1之间进行选择。我该怎么办?
  • 爱丽丝:我从未听说过Py-O-Clock,但我想fold=0是第一次凌晨1:30,fold=1是第二次。

技术原因

虽然time.struct_time对象的tm_isdst字段可用于消除fold中的本地时间歧义,但这种消除歧义的语义与本PEP中的提案完全不同。

tm_isdst字段的主要问题在于,如果不了解仅对tzinfo实现可用的有关时区的信息,就无法知道tm_isdst的哪个值是合适的。因此,虽然tm_isdst在诸如time.localtime之类的函数的输出中很有用,但作为诸如time.mktime之类的函数的输入,它却很麻烦。

如果程序员错误地将tm_isdst的非负值指定给time.mktime,则结果时间将相差1小时,并且由于很少有方法可以在调用time.mktime之前了解有关DST的任何信息,因此唯一明智的选择通常是tm_isdst=-1

tm_isdst不同,建议的fold属性不会影响datetime实例的解释,除非在没有该属性的情况下,两种(或零种)解释都是可能的。

由于将某些内容称为isdst,但其语义与tm_isdst不同,这会非常令人困惑,因此我们需要一个不同的名称。此外,datetime.datetime类已经有一个名为dst()的方法,如果我们将fold称为“isdst”,那么我们必然会遇到“isdst”为零但dst()不为零或反之亦然的情况。

为什么是“fold”?

由Guido van Rossum建议,并得到一位(但最初未得到另一位)作者的支持。在属性的允许值从False/True更改为0/1后,达成了一致意见。“fold”(折叠)这个名词具有正确的含义和简单的助记规则,但同时又不诱发毫无根据的假设。

什么是“first”?

这是最初选择的属性的工作名称,因为明显的替代方案(“second”)与现有属性冲突。它主要因会使 True 成为默认值而被拒绝。

以下替代名称也已被考虑

later
与“fold”非常接近的一个竞争者。一位作者不喜欢它,因为它容易与同样合适的“latter”混淆,但在到处都是自动完成的时代,这是一个小的考虑因素。一个更强烈的反对意见可能是,在缺少时间的情况下,我们将拥有 later=True 实例被 .astimezone(timezone.utc) 转换为更早的时间,而 later=False 则不会。但是,这也可以被解释为一个理想的指示,表明原始时间无效。
which
用于 localtime 函数分支索引的 原始 占位符名称 独立地被提出 用于歧义属性的名称,并获得 一些支持
repeated
在邮件列表中没有收到任何支持。
ltdf
(本地时间歧义标志) - 简短且没有人会尝试猜测其含义,除非阅读文档。(此缩写词在 PEP 讨论中被那些不想认可任何替代方案的人使用,其含义为 ltdf=False 是较早的。)

两个值足够吗?

已经提出了几个原因,以允许 fold 属性具有 None 或 -1 值:向后兼容性、与 tm_isdst 的类比以及对无效时间的严格检查。

向后兼容性

有人建议,如果 fold 标志的默认值为 None,则可以改进向后兼容性,这将表示请求 PEP 之前的行为。根据下面的分析,我们认为,使用 fold=0 作为默认值的提议更改具有足够的向后兼容性。

本 PEP 仅提供三种方法供程序发现两个在其他方面相同的 datetime 实例具有不同的 fold 值:(1) 对 fold 属性进行显式检查;(2) 如果实例是朴素的 - 使用 astimezone() 方法转换为另一个时区;以及 (3) 使用 timestamp() 方法转换为 float

由于 fold 是一个新属性,因此现有程序无法使用第一个选项。请注意,选项 (2) 仅适用于恰好位于系统时区中的折叠或间隙中的朴素日期时间。在所有其他情况下,fold 的值在转换中将被忽略,除非实例使用 fold 感知的 tzinfo,而这在 PEP 之前的程序中是不可用的。类似地,对朴素实例调用的 astimezone() 在此类程序中也将不可用,因为 astimezone() 目前不适用于朴素日期时间。

这使得我们只有一种情况,即现有程序在实施本 PEP 后可能会开始产生不同的结果:当对恰好位于折叠或间隙中的朴素日期时间实例调用 datetime.timestamp() 方法时。在当前的实现中,结果是未定义的。根据系统 mktime 实现,程序在这些情况下可能会看到不同的结果或错误。使用本 PEP,时间戳的值在这些情况下将是明确定义的,但将取决于 fold 标志的值。我们认为 datetime.timestamp() 方法行为的变化是由本 PEP 启用的错误修复。依赖于旧行为的用户仍然可以通过编写 time.mktime(dt.timetuple()) + 1e-6*dt.microsecond 而不是 dt.timestamp() 来模拟旧行为。

与 tm_isdst 的类比

time.mktime 接口允许 tm_isdst 标志具有三个值:-1、0 和 1。正如我们上面解释的那样,-1(要求 mktime 根据其余字段从给定时间确定 DST 是否有效)是实际上唯一有用的选择。

但是,使用 fold 标志,datetime.timestamp() 将在 99.98% 的时间内返回与 mktime 具有 tm_isdst=-1 的相同值,这适用于大多数具有 DST 转换的时区。此外,无论 fold 的值如何,都指定了类似于 tm_isdst=-1 的行为。

只有在 0.02% 的情况下(每年 2 小时),datetime.timestamp()mktime 具有 tm_isdst=-1 可能会不一致。但是,即使在这种情况下,大多数 mktime 实现也将返回 fold=0fold=1 值,即使相关标准允许 mktime 返回 -1 并在这些情况下设置错误代码。

换句话说,本 PEP 中并没有缺少 tm_isdst=-1 行为。相反,它是以两种不同的明确定义的方式提供的唯一行为。缺少的行为是当给定的本地小时由于 tm_isdst 指定错误而被解释为不同的本地小时时。

例如,在北半球的遵守 DST 的时区(DST 在 6 月份有效)中,可以获得

>>> from time import mktime, localtime
>>> t = mktime((2015, 6, 1, 12, 0, 0, -1, -1, 0))
>>> localtime(t)[:]
(2015, 6, 1, 13, 0, 0, 0, 152, 1)

请注意,12:00 被 mktime 解释为 13:00。使用 datetime.timestampdatetime.fromtimestamp,目前保证

>>> t = datetime.datetime(2015, 6, 1, 12).timestamp()
>>> datetime.datetime.fromtimestamp(t)
datetime.datetime(2015, 6, 1, 12, 0)

本 PEP 将相同的保证扩展到 fold 的两个值

>>> t = datetime.datetime(2015, 6, 1, 12, fold=0).timestamp()
>>> datetime.datetime.fromtimestamp(t)
datetime.datetime(2015, 6, 1, 12, 0)
>>> t = datetime.datetime(2015, 6, 1, 12, fold=1).timestamp()
>>> datetime.datetime.fromtimestamp(t)
datetime.datetime(2015, 6, 1, 12, 0)

因此,建议用于 fold=-1 的用途之一(匹配旧行为)是不需要的。fold 的任何选择都将匹配旧行为,除了旧行为未定义的少数情况。

严格的无效时间检查

另一个建议是使用 fold=-1fold=None 来指示程序确实无法处理折叠和间隙,并且只要 dt 表示模棱两可或缺少的本地时间,dt.utcoffset() 就会引发错误。

此提议的主要问题是,dt.utcoffset() 在引发错误不是选项的情况下在内部使用:例如,在字典查找或列表/集合成员资格检查中。因此,严格的间隙/折叠检查行为需要由一个单独的标志控制,例如 dt.utcoffset(raise_on_gap=True, raise_on_fold=False)。但是,此功能可以在用户代码中轻松实现。

def utcoffset(dt, raise_on_gap=True, raise_on_fold=False):
    u = dt.utcoffset()
    v = dt.replace(fold=not dt.fold).utcoffset()
    if u == v:
        return u
    if (u < v) == dt.fold:
        if raise_on_fold:
            raise AmbiguousTimeError
    else:
        if raise_on_gap:
            raise MissingTimeError
    return u

此外,在问题情况下引发错误只是许多可能解决方案之一。交互式程序可以向用户请求其他输入,而服务器进程可以记录警告并采取适当的默认操作。我们不可能为所有可能的用户信息需求提供函数,但本 PEP 提供了在几行代码中实现任何所需行为的方法。

实现

图片来源

此图像是美国军方或国防部员工的作品,是在执行其官方职责时拍摄或制作的。作为美国联邦政府的作品,该图像是公共领域的一部分。


来源:https://github.com/python/peps/blob/main/peps/pep-0495.rst

上次修改时间:2024-01-11 16:25:09 GMT