日期时间模块的日期类的__slots__

问题描述 投票:0回答:1

我做了一些与日期课有关的工作。所以,我在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__不会拒绝直接访问instant / class属性。但是,在日期类的情况下,我试图从实例访问_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'

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

为什么Foo类能够访问_bar__slots__中声明,而日期类错误访问_year

python python-3.x
1个回答
1
投票

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

try:
    from _datetime import *
except ImportError:
    pass

这会尝试从_datetime模块导入任何可用的名称。 _datetime模块是用C语言编写的“加速器”模块。它提供了datetime.py中Python代码中定义的一些函数和类型的更快实现。正如juanpa.arrivillaga在你的问题上评论的那样,here's the C source for _datetime

您尝试访问的属性不存在于date类型的C版本中。由于下划线前缀应该提示给你,这些属性不是datetime.date的公共API的一部分,所以即使你正在使用Python实现,你也会在未来版本的Python中不加警告地改变内部。

© www.soinside.com 2019 - 2024. All rights reserved.