如何在Python中创建不可变对象?

如何在Python中创建不可变对象?

虽然我从来没有需要这个,但让我感到震惊的是在Python中创建一个不可变对象可能会有点棘手。你不能只是覆盖__setattr__,因为那时你甚至不能设置属性__init__。对元组进行子类化是一种有效的技巧:

class Immutable(tuple):

    def __new__(cls, a, b):
        return tuple.__new__(cls, (a, b))

    @property
    def a(self):
        return self[0]

    @property
    def b(self):
        return self[1]

    def __str__(self):
        return "<Immutable {0}, {1}>".format(self.a, self.b)

    def __setattr__(self, *ignored):
        raise NotImplementedError

    def __delattr__(self, *ignored):
        raise NotImplementedError

但是你可以通过和访问ab变量,这很烦人。self[0]self[1]

这在纯Python中是否可行?如果没有,我将如何使用C扩展?

(只能在Python 3中使用的答案是可以接受的)。

更新:

因此,子类的元组是做纯Python,效果很好,除了通过访问数据的另一种可能性的方式[0][1]等等。所以,要完成这个问题,所有这一切都缺少的是HOWTO在C,做“正确的”,这我怀疑是非常简单,只是没有实现任何geititemsetattribute等等。但我不是自己做,我为此提供赏金,因为我很懒。:)


慕的地6264312
浏览 699回答 3
3回答

素胚勾勒不出你

.如何在C中“正确”地做到您可以使用Cython为Python创建扩展类型:cdef&nbsp;class&nbsp;Immutable: &nbsp;&nbsp;&nbsp;&nbsp;cdef&nbsp;readonly&nbsp;object&nbsp;a,&nbsp;b &nbsp;&nbsp;&nbsp;&nbsp;cdef&nbsp;object&nbsp;__weakref__&nbsp;#&nbsp;enable&nbsp;weak&nbsp;referencing&nbsp;support &nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;__init__(self,&nbsp;a,&nbsp;b): &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.a,&nbsp;self.b&nbsp;=&nbsp;a,&nbsp;b它适用于Python 2.x和3。测试#&nbsp;compile&nbsp;on-the-flyimport&nbsp;pyximport;&nbsp;pyximport.install()&nbsp;#&nbsp;$&nbsp;pip&nbsp;install&nbsp;cythonfrom&nbsp;immutable&nbsp;import&nbsp;Immutableo&nbsp;=&nbsp;Immutable(1,&nbsp;2)assert&nbsp;o.a&nbsp;==&nbsp;1,&nbsp;str(o.a)assert&nbsp;o.b&nbsp;==&nbsp;2try:&nbsp;o.a&nbsp;=&nbsp;3except&nbsp;AttributeError: &nbsp;&nbsp;&nbsp;&nbsp;passelse: &nbsp;&nbsp;&nbsp;&nbsp;assert&nbsp;0,&nbsp;'attribute&nbsp;must&nbsp;be&nbsp;readonly'try:&nbsp;o[1]except&nbsp;TypeError: &nbsp;&nbsp;&nbsp;&nbsp;passelse: &nbsp;&nbsp;&nbsp;&nbsp;assert&nbsp;0,&nbsp;'indexing&nbsp;must&nbsp;not&nbsp;be&nbsp;supported'try:&nbsp;o.c&nbsp;=&nbsp;1except&nbsp;AttributeError: &nbsp;&nbsp;&nbsp;&nbsp;passelse: &nbsp;&nbsp;&nbsp;&nbsp;assert&nbsp;0,&nbsp;'no&nbsp;new&nbsp;attributes&nbsp;are&nbsp;allowed'o&nbsp;=&nbsp;Immutable('a',&nbsp;[])assert&nbsp;o.a&nbsp;==&nbsp;'a'assert&nbsp;o.b&nbsp;==&nbsp;[]o.b.append(3)&nbsp;#&nbsp;attribute&nbsp;may&nbsp;contain&nbsp;mutable&nbsp;objectassert&nbsp;o.b&nbsp;==&nbsp;[3]try:&nbsp;o.cexcept&nbsp;AttributeError: &nbsp;&nbsp;&nbsp;&nbsp;passelse: &nbsp;&nbsp;&nbsp;&nbsp;assert&nbsp;0,&nbsp;'no&nbsp;c&nbsp;attribute'o&nbsp;=&nbsp;Immutable(b=3,a=1)assert&nbsp;o.a&nbsp;==&nbsp;1&nbsp;and&nbsp;o.b&nbsp;==&nbsp;3try:&nbsp;del&nbsp;o.bexcept&nbsp;AttributeError: &nbsp;&nbsp;&nbsp;&nbsp;passelse: &nbsp;&nbsp;&nbsp;&nbsp;assert&nbsp;0,&nbsp;"can't&nbsp;delete&nbsp;attribute"d&nbsp;=&nbsp;dict(b=3,&nbsp;a=1)o&nbsp;=&nbsp;Immutable(**d)assert&nbsp;o.a&nbsp;==&nbsp;d['a']&nbsp;and&nbsp;o.b&nbsp;==&nbsp;d['b']o&nbsp;=&nbsp;Immutable(1,b=3)assert&nbsp;o.a&nbsp;==&nbsp;1&nbsp;and&nbsp;o.b&nbsp;==&nbsp;3try:&nbsp;object.__setattr__(o,&nbsp;'a',&nbsp;1)except&nbsp;AttributeError: &nbsp;&nbsp;&nbsp;&nbsp;passelse: &nbsp;&nbsp;&nbsp;&nbsp;assert&nbsp;0,&nbsp;'attributes&nbsp;are&nbsp;readonly'try:&nbsp;object.__setattr__(o,&nbsp;'c',&nbsp;1)except&nbsp;AttributeError: &nbsp;&nbsp;&nbsp;&nbsp;passelse: &nbsp;&nbsp;&nbsp;&nbsp;assert&nbsp;0,&nbsp;'no&nbsp;new&nbsp;attributes'try:&nbsp;Immutable(1,c=3)except&nbsp;TypeError: &nbsp;&nbsp;&nbsp;&nbsp;passelse: &nbsp;&nbsp;&nbsp;&nbsp;assert&nbsp;0,&nbsp;'accept&nbsp;only&nbsp;a,b&nbsp;keywords'for&nbsp;kwd&nbsp;in&nbsp;[dict(a=1),&nbsp;dict(b=2)]: &nbsp;&nbsp;&nbsp;&nbsp;try:&nbsp;Immutable(**kwd) &nbsp;&nbsp;&nbsp;&nbsp;except&nbsp;TypeError: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pass &nbsp;&nbsp;&nbsp;&nbsp;else: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assert&nbsp;0,&nbsp;'Immutable&nbsp;requires&nbsp;exactly&nbsp;2&nbsp;arguments'如果您不介意索引支持,那么@Sven Marnachcollections.namedtuple建议您更喜欢:Immutable&nbsp;=&nbsp;collections.namedtuple("Immutable",&nbsp;"a&nbsp;b")
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python