【问题标题】:python class read-only attributes (in datetime)python类只读属性(日期时间)
【发布时间】:2018-07-04 01:53:39
【问题描述】:

我知道将属性设置为私有的一种快速方法是在属性之前使用__稍后更正,因为这实际上是为了名称修改,而不是为了限制访问),或使用@property

但是,我发现对于一个 python 标准库模块,例如,datetime,这是以不同的方式设置的?

解释我的问题,请到the source code of datetime

我们以timedelta类为例:

class timedelta:
    ...
    ...
    ... 

timedelta.min = timedelta(-999999999)
timedelta.max = timedelta(days=999999999, hours=23, minutes=59, seconds=59,
                          microseconds=999999)
timedelta.resolution = timedelta(microseconds=1)

类属性是在类之外设置的吗?为什么?

如果我:

import datetime
d= datetime.timedelta(days=1, hours=12)
print(d)
print(d.max)  # >>> 999999999 days, 23:59:59.999999
print(type(d.max))  # >>> <class 'datetime.timedelta'>

d.max = 1000  # regardless of the reason, if I just want to do this
# >>> AttributeError: 'datetime.timedelta' object attribute 'max' is read-only

我想知道这个AttributeError 来自哪里?我在源代码的任何地方都找不到会引发此​​错误消息的地方?

谢谢!

【问题讨论】:

  • Python 中没有私有属性。双下划线名称修改会名称修改,它不限制访问。
  • @juanpa.arrivillaga 我知道事实上__private 伪装成_Class__private,所以它并不是真正的只读。这让我更加想知道他们如何设置它以使 timedelta.max 只读
  • @juanpa.arrivillaga 知道了,谢谢!

标签: python python-3.x oop


【解决方案1】:

类属性是在类之外设置的吗?为什么?

timedelta 在执行 timedelta 类的主体时不存在。在创建类对象之前,您必须执行 class timedelta: 块中的所有代码,并且可以单独使用。

我想知道这个 AttributeError 是从哪里来的?我在源代码的任何地方都找不到会引发此​​错误消息的地方?

datetime 模块是用纯 Python 编写的,但如果可以的话,tries to use 是一个更快的模块 written in C。纯 Python 代码按您的预期工作:

>>> import sys
>>> sys.modules['_datetime'] = None  # prevent the C module from loading
>>> from datetime import timedelta
>>> timedelta.min = 5
>>> timedelta.min
5

timedelta 类将tp_flags 设置为Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE。您只能设置包含Py_TPFLAGS_HEAPTYPE flag的对象的属性。

【讨论】:

  • 非常感谢您的清晰解释!作为一个刚开始学习python不久的初学者(而且只是python),我可能在这个早期阶段问这个问题太过分了。
  • 如果我可以根据您的回答提出进一步的问题。如何判断 .py 文件是否正在尝试使用用 C 编写的模块?从 datetime.py 文件中,我只能在 cmets 中看到 CPython,而在其他地方看不到
  • @Code_Control_jxie0755:如果您查看datetime.py 的最底部,它有trys 执行from _datetime import * 的代码。使用下划线前缀的模块名称是支持在纯 Python 中实现的模块的 C 扩展模块的 Python 3 标准,以及“定义所有 Python 内容,但然后看看我们是否不能将大部分/全部替换为加速器模块的等价物”相当普遍。
【解决方案2】:

这不是 CPython 解释器使用的日期时间模块的源代码。出于性能原因,CPython 源代码在 C 中实现了许多标准库。它们确实提供了仅限 Python 的实现(例如,我相信 PyPy 在许多情况下都依赖这些实现)。

datetime的源码其实在这里:

https://github.com/python/cpython/blob/3.6/Modules/_datetimemodule.c

访问权限在 C 级别受到限制。

注意,双下划线名称修改名称修改,它不限制访问。

【讨论】:

    猜你喜欢
    • 2011-11-08
    • 2019-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-25
    • 2017-03-22
    • 2014-01-08
    相关资源
    最近更新 更多