вторник, 17 марта 2015 г., 20:21:01 UTC+3 пользователь Eric V. Smith написал:
On 03/17/2015 12:52 PM, Luciano Ramalho wrote:
> Sometimes we need a simple class to hold some mutable attributes,
> provide a nice repr, support == for testing, and support iterable
> unpacking, so you can write:
>>>> p = Point(3, 4)
>>>> x, y = p
> That's very much like the classes built by namedtuple, but mutable.
It also adds default values to the generated constructor, which may or
may not be desirable. But if used exactly like collections.namedtuple,
it ignores the default values.
Since named tuple is considered as an object that is a tuple with attribute access.
The mutable alternative could be considered as an array with attribute access.
Array in this context is tuple-like object that support assign operation.
Since python have not such object there are different approaches tomutable named tuple alternatives.
Python definitely does have such an object: list. A list is effectively the same as a tuple but mutable; it's the paradigm MutableSequence while tuple is the paradigm Sequence. Under the covers they have very similar headers that both use the same storage (a C array of pointers to Python objects, in CPython), and C API functions like PySequence_Fast_GET_ITEM don't distinguish between the two.
However, list is resizable, and presumably a "namedlist" would not be. That makes things more complicated for both the interface (there's no is-a relationship; a type without append is not a list--and, worse, a type that has __setitem__ but can't handle slice replacement is not a list but that's very hard to detect...) and the implementation (e.g., a list reserves extra space at the end to avoid having to reallocate on every append).
(Python _also_ has an array type, which is for homogenous simple types (like 32-bit int) which can store the values directly, as opposed to tuple and list, which store (pointers to) heterogenous normal Python objects.)
One should note that particular property of named tuple is memory saving.
So one can expect similar property of mutable named tuple too.
If you don't need to access the items by index for whatever reason, you don't need a namedtuple, and using one as a misguided misoptimization is a bad idea.
Besides the fact that a normal class with __slots__ is also small, and even a normal class with a dict (in newer CPython versions and PyPy) not that much bigger, besides the fact that you can eliminate the row overhead rather than just slightly reducing it by using, e.g., a 2D array, you're optimizing the wrong thing in the first place--if your rows have 9 elements, reducing the row overhead is focusing on fixing 10% of your overhead, while reducing or eliminating the element overhead by using, e.g., a 2D numpy array of low-level values fixes the 90% (along with the 10%).