如何在Python中制作一个不可变的对象

如何在Python中制作一个不可变的对象

本文介绍了如何在Python中制作一个不可变的对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尽管我从不需要它,但令我感到惊讶的是,在Python中创建不可变的对象可能会有些棘手.您不能只覆盖 __setattr__ ,因为那样的话甚至无法在 __init__ 中设置属性.将元组子类化是一种有效的技巧:

Although I have never needed this, it just struck me that making an immutable object in Python could be slightly tricky. You can't just override __setattr__, because then you can't even set attributes in the __init__. Subclassing a tuple is a trick that works:

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

但是随后您可以通过self[0]self[1]访问ab变量,这很烦人.

But then you have access to the a and b variables through self[0] and self[1], which is annoying.

在纯Python中这可能吗?如果没有,我该如何使用C扩展名呢?

Is this possible in Pure Python? If not, how would I do it with a C extension?

(仅在Python 3中有效的答案是可以接受的.)

(Answers that work only in Python 3 are acceptable).

更新:

因此,在Pure Python中子类化元组是实现此目的的方法,除了通过[0][1]等访问数据的其他可能性之外,该方法行之有效.在C中正确地"执行此操作,我怀疑这很简单,只需不执行任何geititemsetattribute等.但是我不是自己做,而是为此提供了赏金,因为我很懒. :)

So subclassing tuple is the way to do it in Pure Python, which works well except for the additional possibility of accessing the data by [0], [1] etc. So, to complete this question all that is missing is howto do it "properly" in C, which I suspect would be quite simple, by just not implementing any geititem or setattribute, etc. But instead of doing it myself, I offer a bounty for that, because I'm lazy. :)

推荐答案

我刚刚想到的另一种解决方案:获得与原始代码相同行为的最简单方法是

Yet another solution I just thought of: The simplest way to get the same behaviour as your original code is

Immutable = collections.namedtuple("Immutable", ["a", "b"])

它不能解决可以通过[0]等访问属性的问题,但至少要短得多,并且具有与picklecopy兼容的其他优点.

It does not solve the problem that attributes can be accessed via [0] etc., but at least it's considerably shorter and provides the additional advantage of being compatible with pickle and copy.

namedtuple 创建的类型类似于我在此答案,即源自,然后使用__slots__.它在Python 2.6或更高版本中可用.

namedtuple creates a type similar to what I described in this answer, i.e. derived from tuple and using __slots__. It is available in Python 2.6 or above.

这篇关于如何在Python中制作一个不可变的对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-28 08:10