Finally got around to fleshing out my idea here.
My thought was to make an anonymous names tuple not as a new anonymous class, but simply as an instance with specific field names. So all of these would the the same class, but they would also be lightweight, and all subclasses of tuple -- from a typing perspective, it's just be a tuple - and could be used anywhere a tuple could.
Here's a quick prototype I came up with:
class TupleWithNames(tuple):
def __new__(cls, **fields):
self = tuple.__new__(cls, fields.values())
for name, val in fields.items():
self.__dict__[name] = val
return self
def __setattr__(self, attr, val):
raise AttributeError("Can't set attributes on TupleWithNames")
def __repr__(self):
return f"TupleWithNames({', '.join(f'{k}={v}' for k, v in self.__dict__.items())})"
In [172]: point = TupleWithNames(x=5, y=10)
In [173]: point
Out[173]: TupleWithNames(x=5, y=10)
In [174]: point.x
Out[174]: 5
In [175]: point.y
Out[175]: 10
In [176]: point.x = 2
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-176-6a65d3605158> in <module>
----> 1 point.x = 2
~/PythonStuff/tuplewithnames/tuplewithnames.py in __setattr__(self, attr, val)
11
12 def __setattr__(self, attr, val):
---> 13 raise AttributeError("Can't set attributes on TupleWithNames")
14
15 def __repr__(self):
AttributeError: Can't set attributes on TupleWithNames
In [177]: point.z = 3
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-177-902df67327f4> in <module>
----> 1 point.z = 3
~/PythonStuff/tuplewithnames/tuplewithnames.py in __setattr__(self, attr, val)
11
12 def __setattr__(self, attr, val):
---> 13 raise AttributeError("Can't set attributes on TupleWithNames")
14
15 def __repr__(self):
AttributeError: Can't set attributes on TupleWithNames
In [178]: point[0]
Out[178]: 5
In [179]: point[1]
Out[179]: 10
In [180]: point[1] = 3
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-180-d6d4f8cfca2f> in <module>
----> 1 point[1] = 3
TypeError: 'TupleWithNames' object does not support item assignment
So it's a (subclass of) tuple -- you can access the entries by name, you can't change them.
It's truly immutable, 'cause the __dict __ is there to mess with, but that (I think) could be fixed if it were implemented in C.
This really simple version hashes as the tuple -- so it's the same as a tuple with the same values, or a TupleWithNames with the same values, and any arbitrary names.
Which I think is OK -- the idea here is that it IS just like a tuple except you can use the field names to access items for readability. But you could customize the hash, too if you wanted.
Anyway -- that's in idea -- details to be fleshed out if anyone wanted to pursue this.
-CHB