首页 > 解决方案 > 日期时间模块的日期类的__slots__

问题描述

我做了一些与日期类有关的工作。所以,我在 C:\Python34\Lib 中阅读了 datetime.py。顺便说一句,我在 Python 3.4 上。我偶然发现了这些行代码:

class date:   
    __slots__ = '_year', '_month', '_day'

    def __new__(cls, year, month=None, day=None):        
        if (isinstance(year, bytes) and len(year) == 4 and
            1 <= year[2] <= 12 and month is None):  # Month is sane
            # Pickle support
            self = object.__new__(cls)
            self.__setstate(year)
            return self
        _check_date_fields(year, month, day)
        self = object.__new__(cls)
        self._year = year
        self._month = month
        self._day = day
        return self

……

    @property
    def year(self):
        """year (1-9999)"""
        return self._year

    @property
    def month(self):
       """month (1-12)"""
       return self._month

    @property
    def day(self):
        """day (1-31)"""
        return self._day

我理解__slots__拒绝创建__dict__实例。正如我在示例和文档中所读到的,__slots__并不拒绝直接访问即时/类属性。但是,在日期类的情况下,我尝试从实例访问 _year、_month、_date。它出错了。例如:

In [32]: from datetime import date    
In [33]: mydate = date(2019, 3, 10)
In [34]: mydate._year
>>>AttributeError Traceback (most recent call last) <ipython-input-31-8de5c748f55b> in <module>() ----> 1 mydate._year
AttributeError: 'datetime.date' object has no attribute '_year'

我知道'_'变量意味着不直接访问,@property 年、月、日是它们的 getter 函数。但是,我认为'_'即使在声明的情况下也可以访问变量__slots__

我编写了一个 Foo 类如下进行测试:

class Foo:
    __slots__ = ('_bar',)

    def __new__(cls):    
        self = super().__new__(cls)
        self._bar = 'barz'
        return self

    @property
    def bar(self):
        return self._bar

In [35]: f = Foo()

In [36]: f._bar
Out[36]: 'barz'

这个 Foo 类的实例 f 访问 _bar 没有问题,尽管使用__slots__和@property

为什么 Foo 类能够访问_bar在访问时声明__slots__日期类错误_year

标签: pythonpython-3.x

解决方案


在您正在阅读的文件的底部,有以下几行:

try:
    from _datetime import *
except ImportError:
    pass

这会尝试从_datetime模块中导入任何可用的名称。该_datetime模块是一个用 C 编写的“加速器”模块。它提供了在datetime.py. 正如juanpa.arrivillaga对您的问题所评论的那样,这里是_datetime.

您尝试访问的属性在该类型的 C 版本中不存在date。正如下划线前缀应该向您暗示的那样,这些属性不是 的公共 API 的一部分datetime.date,因此即使您正在获取 Python 实现,您也会在内部搞乱,这些内部结构可能会在未来版本的 Python 中更改而不会发出警告。


推荐阅读