Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Decimal类如何是不可变的?_Python_Decimal_Immutability_Metaclass_Standard Library - Fatal编程技术网

Python Decimal类如何是不可变的?

Python Decimal类如何是不可变的?,python,decimal,immutability,metaclass,standard-library,Python,Decimal,Immutability,Metaclass,Standard Library,我在玩python3k解释器时,在Decimal.py模块中遇到了Decimal类。类的文档表明从类创建的对象是不可变的。我试图查看python库代码,以了解程序员是如何编写类以使其不可变的。不幸的是,我无法确切地发现他们做了什么(主要是因为类本身相当大) 我很想知道是否有人理解这个类是如何实现其不变状态的。我认为这可能与重写类中的getattr()和setattr()方法有关,但我找不到任何证据 我还注意到这个类能够以某种方式隐藏它在slot变量中定义的属性。也许该类使用某种类型的元类技术来实

我在玩python3k解释器时,在Decimal.py模块中遇到了Decimal类。类的文档表明从类创建的对象是不可变的。我试图查看python库代码,以了解程序员是如何编写类以使其不可变的。不幸的是,我无法确切地发现他们做了什么(主要是因为类本身相当大)

我很想知道是否有人理解这个类是如何实现其不变状态的。我认为这可能与重写类中的getattr()和setattr()方法有关,但我找不到任何证据

我还注意到这个类能够以某种方式隐藏它在slot变量中定义的属性。也许该类使用某种类型的元类技术来实现这一点以及它的不变性


如果有人有任何想法,我将感谢您的反馈。谢谢

好问题。对我来说似乎不是不可战胜的。Python 2.7.2:

>>> from decimal import Decimal
>>> d = Decimal('1.23')
>>> d
Decimal('1.23')
>>> f = d
>>> f
Decimal('1.23')
>>> d._exp = 1
>>> f
Decimal('1.23E+3')
我确实看到文件上说它是不可变的。我猜他们的意思是,如果你使用文档化的接口,它是不可变的。例如

>>> d += 100
>>> f
Decimal('1.23E+3')
>>> d
Decimal('1330')

其工作方式很简单,Decimal不为?=运算符定义运算符重载:函数如
\uuu i[op]\uu
。在这种情况下,
d+=100
转换为
d=d.\uuu add\uuu(100)
,它返回一个新对象并更改d的标识,同时不影响原始对象。

您给我的示例在python 2.7.2上的效果与预期一样。Decimal通过更改其实现属性(如_exp)是完全可变的。但是,如果您尝试在python 3.3.2中运行相同的代码,当您尝试访问表示该属性不存在的_exp时,将得到AttributeError。我相信这个模块是为Python2和Python3编写的。也许它在不同的版本中没有使用相同的属性标识符或其他什么是的,我猜你使用的是不同的版本,因为你的一些陈述与我的观察结果不匹配。尽管如此,2.7文档声称它是不可变的,但它并不像int那么不可变。在Python3.3中,十进制模块是用C实现的,默认情况下使用它。纯Python实现仍然存在,但通常不使用。C版本的速度明显加快,但一些实现细节已经更改_exp是一种不受支持的、自担风险的方法,仅在纯Python实现中可用。它的使用或滥用可能会导致意想不到的结果。哦,这是有道理的。自从我在源代码中首先找到python版本以来,我从未想到该模块可能已经用C重新实现。我当时正在绞尽脑汁想弄清楚他们是如何用python实现的(我想我缺少了某种模糊的语言特性)。非常感谢您和@morningstar对我的帮助