我做了一些与日期课有关的工作。所以,我在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
?
在您正在阅读的文件的底部,有以下行:
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中不加警告地改变内部。