Existence of mutable named tuple in Python?

前端 未结 10 2126
旧巷少年郎
旧巷少年郎 2020-11-29 16:23

Can anyone amend namedtuple or provide an alternative class so that it works for mutable objects?

Primarily for readability, I would like something similar to namedt

相关标签:
10条回答
  • 2020-11-29 16:46

    types.SimpleNamespace was introduced in Python 3.3 and supports the requested requirements.

    from types import SimpleNamespace
    t = SimpleNamespace(foo='bar')
    t.ham = 'spam'
    print(t)
    namespace(foo='bar', ham='spam')
    print(t.foo)
    'bar'
    import pickle
    with open('/tmp/pickle', 'wb') as f:
        pickle.dump(t, f)
    
    0 讨论(0)
  • 2020-11-29 16:46

    If you want similar behavior as namedtuples but mutable try namedlist

    Note that in order to be mutable it cannot be a tuple.

    0 讨论(0)
  • 2020-11-29 16:54

    Provided performance is of little importance, one could use a silly hack like:

    from collection import namedtuple
    
    Point = namedtuple('Point', 'x y z')
    mutable_z = Point(1,2,[3])
    
    0 讨论(0)
  • 2020-11-29 17:00

    Tuples are by definition immutable.

    You can however make a dictionary subclass where you can access the attributes with dot-notation;

    In [1]: %cpaste
    Pasting code; enter '--' alone on the line to stop or use Ctrl-D.
    :class AttrDict(dict):
    :
    :    def __getattr__(self, name):
    :        return self[name]
    :
    :    def __setattr__(self, name, value):
    :        self[name] = value
    :--
    
    In [2]: test = AttrDict()
    
    In [3]: test.a = 1
    
    In [4]: test.b = True
    
    In [5]: test
    Out[5]: {'a': 1, 'b': True}
    
    0 讨论(0)
  • 2020-11-29 17:03

    It seems like the answer to this question is no.

    Below is pretty close, but it's not technically mutable. This is creating a new namedtuple() instance with an updated x value:

    Point = namedtuple('Point', ['x', 'y'])
    p = Point(0, 0)
    p = p._replace(x=10) 
    

    On the other hand, you can create a simple class using __slots__ that should work well for frequently updating class instance attributes:

    class Point:
        __slots__ = ['x', 'y']
        def __init__(self, x, y):
            self.x = x
            self.y = y
    

    To add to this answer, I think __slots__ is good use here because it's memory efficient when you create lots of class instances. The only downside is that you can't create new class attributes.

    Here's one relevant thread that illustrates the memory efficiency - Dictionary vs Object - which is more efficient and why?

    The quoted content in the answer of this thread is a very succinct explanation why __slots__ is more memory efficient - Python slots

    0 讨论(0)
  • 2020-11-29 17:08

    There is a mutable alternative to collections.namedtuple - recordclass.

    It has the same API and memory footprint as namedtuple and it supports assignments (It should be faster as well). For example:

    from recordclass import recordclass
    
    Point = recordclass('Point', 'x y')
    
    >>> p = Point(1, 2)
    >>> p
    Point(x=1, y=2)
    >>> print(p.x, p.y)
    1 2
    >>> p.x += 2; p.y += 3; print(p)
    Point(x=3, y=5)
    

    For python 3.6 and higher recordclass (since 0.5) support typehints:

    from recordclass import recordclass, RecordClass
    
    class Point(RecordClass):
       x: int
       y: int
    
    >>> Point.__annotations__
    {'x':int, 'y':int}
    >>> p = Point(1, 2)
    >>> p
    Point(x=1, y=2)
    >>> print(p.x, p.y)
    1 2
    >>> p.x += 2; p.y += 3; print(p)
    Point(x=3, y=5)
    

    There is a more complete example (it also includes performance comparisons).

    Since 0.9 recordclass library provides another variant -- recordclass.structclass factory function. It can produce classes, whose instances occupy less memory than __slots__-based instances. This is can be important for the instances with attribute values, which has not intended to have reference cycles. It may help reduce memory usage if you need to create millions of instances. Here is an illustrative example.

    0 讨论(0)
提交回复
热议问题