8

I'm looking for something very like namedtuples:

>>> from collections import namedtuple
>>> Party = namedtuple('Party', ['guests', 'location'])
>>> p = Party(['Jed', 'Fred', 'Kathy'], "Steve's House")

which I use a wrapper class around to add extensibility:

>>> class Party(namedtuple('Party', ['guests', 'location'])):
    ...

but with two differences. I would like the fields to be mutable, and I would like inheritance to work. (Right now I don't think there's a way to have one namedtuple inherit from another).

I've heard about types.SimpleNamespace, but I don't think it allows positional arguments in creation (someone correct me if I'm wrong). I like namedtuples because they keep me from having to write __init__, __repr__, and __eq__, all of which I need for my use case.

What is important to me: built-in implementations of __init__, __repr__ and __eq__ so I don't have to write them myself. I'm going to need many (30+) of these class definitions, and some of them will have many (15+) fields.

What isn't important to me (right now): memory efficiency. I don't plan to have more than five hundred instances of these at any one time.

I'm thinking of rolling my own, but want to make sure I'm not re-inventing the wheel.

Eli Rose
  • 6,788
  • 8
  • 35
  • 55
  • 1
    Would using the `__slots__` attribute in `class Party` suffice? – chepner Aug 03 '15 at 15:14
  • 1
    When you say *"very like `namedtuple`"*, what *precise* qualities are you looking for? If it's a space issue, then @chepner's suggestion to use [`__slots__`](https://docs.python.org/2/reference/datamodel.html#slots) is a good one. – jonrsharpe Aug 03 '15 at 15:15
  • @jonrsharpe: Yes, good question. I want `__eq__`, `__repr__` and `__init__`. It doesn't need to be hashable or to subclass `tuple`. – Eli Rose Aug 03 '15 at 15:17
  • 2
    @EliRose so size *isn't* an issue? Why don't you just write a regular class? – jonrsharpe Aug 03 '15 at 15:18
  • @jonrsharpe: I'm going to have 50 of these, some with many fields, and don't want to rewrite the same `__repr__` and `__init__` logic for every one of them. So, the amount of code it takes to define a class is important to me. – Eli Rose Aug 03 '15 at 15:19
  • 1
    @EliRose 50 *classes*, or 50 *instances*? As it stands, it is **profoundly unclear** what you're asking for; please edit the question to clarify what exactly you're trying to achieve generally and why you can't just write a regular superclass specifically. You could always look at [the source code for `namedtuple`](https://hg.python.org/cpython/file/2.7/Lib/collections.py#l234) and borrow what you need from that. – jonrsharpe Aug 03 '15 at 15:21
  • You're right, thanks for helping me realize how to communicate this better. The 50 refers to class definitions. – Eli Rose Aug 03 '15 at 15:24
  • 1
    Python isn't designed for type checking, so it does not really make very much sense (in some cases it can make, I admit) to make own classes for these lightweight data structures. How about just using [an arbitrary data type](https://code.activestate.com/recipes/579092-data-a-class-for-arbitrary-data/)? – Alfe Aug 03 '15 at 15:25
  • @Alfe: Looks interesting, but I'd like to be able to specify my fields in the class definition and throw an error (as `namedtuple` does) if you try to instantiate without providing all of them. – Eli Rose Aug 03 '15 at 15:30
  • You could probably achieve what you want by writing a single metaclass that provides the dynamic implementation of `__eq__` etc, then each of your actual classes would be instances of that, which just provide the names of that class's attributes. – Tom Dalton Aug 03 '15 at 15:36
  • @TomDalton: That's what I was going to do, but I wanted to make sure I wasn't re-inventing the wheel. (There seems to be a lot of coding involved in e.g. making sure subclassing works correctly). – Eli Rose Aug 03 '15 at 15:42
  • FWIW, there's a simple way to [combine namedtuples](http://stackoverflow.com/a/28942143/4014959). But I guess that's not really relevant here, since you need mutability. – PM 2Ring Aug 03 '15 at 15:54
  • Which [namedtuple](https://docs.python.org/3/library/collections.html#collections.namedtuple) features _do_ you actually need? Eg, do you need numerical indexing & the ability to iterate? – PM 2Ring Aug 03 '15 at 15:55
  • @PM2Ring: I need nothing except the implementations of `__init__`, `__repr__` and `__eq__`. – Eli Rose Aug 03 '15 at 15:56

2 Answers2

5

For anyone finding this question in 2022, the most appropriate Python feature that achieves this is now dataclasses:

from dataclasses import dataclass
from typing import List

@dataclass
class Party:
    guests: List[str]
    location: str
Alex W
  • 37,233
  • 13
  • 109
  • 109
1

For a problem you need 50 class definitions for less than five hundred instances . . . in total ? Maybe you should re-consider the problem and find a very different approach ? Tried looking at dictionaries ?

item1 = {'party':'easter', 'guests': ['john', fred','kathy'], 'location':'here'}

Than you need only the standard python dict-class and can easy test field presence, add fields and so on, it has init, repr and eq.

Or provide some more information on the problem.

henkidefix
  • 139
  • 4