This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author conqp
Recipients conqp
Date 2020-12-28.15:26:40
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1609169200.88.0.326770807054.issue42765@roundup.psfhosted.org>
In-reply-to
Content
I have use cases in which I use named tuples to represent data sets, e.g:

class BasicStats(NamedTuple):
    """Basic statistics response packet."""

    type: Type
    session_id: BigEndianSignedInt32
    motd: str
    game_type: str
    map: str
    num_players: int
    max_players: int
    host_port: int
    host_ip: IPAddressOrHostname

I want them to behave as intended, i.e. that unpacking them should behave as expected from a tuple:

type, session_id, motd, … = BasicStats(…)

I also want to be able to serialize them to a JSON-ish dict.
The NamedTuple has an _asdict method, that I could use.

json = BasicStats(…)._asdict()

But for the dict to be passed to JSON, I need customization of the dict representation, e.g. set host_ip to str(self.host_ip), since it might be a non-serializable ipaddress.IPv{4,6}Address. Doing this in an object hook of json.dumps() is a non-starter, since I cannot force the user to remember, which types need to be converted on the several data structures.
Also, using _asdict() seems strange as an exposed API, since it's an underscore method and users hence might not be inclined to use it.

So what I did is to add a method to_json() to convert the named tuple into a JSON-ish dict:

    def to_json(self) -> dict:
        """Returns a JSON-ish dict."""
        return {
            'type': self.type.value,
            'session_id': self.session_id,
            'motd': self.motd,
            'game_type': self.game_type,
            'map': self.map,
            'num_players': self.num_players,
            'max_players': self.max_players,
            'host_port': self.host_port,
            'host_ip': str(self.host_ip)
        }

It would be nicer to have my type just return this appropriate dict when invoking dict(BasicStats(…)). This would require me to override the __iter__() method to yield key / value tuples for the dict.
However, this would break the natural behaviour of tuple unpacking as described above.

Hence, I propose to add a method __iter_items__(self) to the python data model with the following properties:

1) __iter_items__ is expected to return an iterator of 2-tuples representing key / value pairs.
2) the built-in function dict(), when called on an object, will attempt to create the object from __iter_items__ first and fall back to __iter__.

Alternative names could also be __items__ or __iter_dict__.
History
Date User Action Args
2020-12-28 15:26:40conqpsetrecipients: + conqp
2020-12-28 15:26:40conqpsetmessageid: <1609169200.88.0.326770807054.issue42765@roundup.psfhosted.org>
2020-12-28 15:26:40conqplinkissue42765 messages
2020-12-28 15:26:40conqpcreate