Extend dataclass __repr__ programmatically

2024/10/14 5:13:34

Suppose I have a dataclass with a set method. How do I extend the repr method so that it also updates whenever the set method is called:

from dataclasses import dataclass
@dataclass
class State:A: int = 1B: int = 2def set(self, var, val):setattr(self, var, val)

Ex:

In [2]: x = State()In [3]: x
Out[3]: State(A=1, B=2)In [4]: x.set("C", 3)In [5]: x
Out[5]: State(A=1, B=2)In [6]: x.C
Out[6]: 3

The outcome I would like

In [7]: x
Out[7]: State(A=1, B=2, C=3)
Answer

The dataclass decorator lets you quickly and easily build classes that have specific fields that are predetermined when you define the class. The way you're intending to use your class, however, doesn't match up very well with what dataclasses are good for. You want to be able to dynamically add new fields after the class already exists, and have them work with various methods (like __init__, __repr__ and presumably __eq__). That removes almost all of the benefits of using dataclass. You should instead just write your own class that does what you want it to do.

Here's a quick and dirty version:

class State:_defaults = {"A": 1, "B": 2}def __init__(self, **kwargs):self.__dict__.update(self._defaults)self.__dict__.update(kwargs)def __eq__(self, other):return self.__dict__ == other.__dict__ # you might want to add some type checking heredef __repr__(self):kws = [f"{key}={value!r}" for key, value in self.__dict__.items()]return "{}({})".format(type(self).__name__, ", ".join(kws))

This is pretty similar to what you get from types.SimpleNamespace, so you might just be able to use that instead (it doesn't do default values though).

You could add your set method to this framework, though it seems to me like needless duplication of the builtin setattr function you're already using to implement it. If the caller needs to dynamically set an attribute, they can call setattr themselves. If the attribute name is constant, they can use normal attribute assignment syntax instead s.foo = "bar".

https://en.xdnf.cn/q/69452.html

Related Q&A

find least common denominator for list of fractions in python

I have a list of fractionsfrom fractions import Fractionfractions_list=[Fraction(3,14),Fraction(1,7),Fraction(9,14)]The output should be a list with the numerators for each fraction, then the denominat…

How to configure uwsgi to encode logging as json except app output

Im running uwsgi around a Python Flask webapp with these options (among others) to get JSON-encoded log records on stdout:fmt=${"timestamp": "${strftime:%FT%TZ}", "level":…

Testing aiohttp client with unittest.mock.patch

Ive written a simple HTTP client using aiohttp and Im trying to test it by patching aiohttp.ClientSession and aiohttp.ClientResponse. However, it appears as though the unittest.mock.patch decorator is …

GridsearchCV: cant pickle function error when trying to pass lambda in parameter

I have looked quite extensively on stackoverflow and elsewhere and I cant seem to find an answer to the problem below. I am trying to modify a parameter of a function that is itself a parameter inside …

How to insert a carriage return in a ReportLab paragraph?

Is there a way to insert a carriage return in a Paragraph in ReportLab? I am trying to concatenate a "\n" to my paragraph string but this isnt working. Title = Paragraph("Title" + …

How to get predictions and calculate accuracy for a given test set in fast ai?

Im trying to load a learner which was exported by learn.export() and I want to run it against a test set. I want my test set have labels so that I can measure its accuracy. This is my code: test_src = …

Splitting the legend in matploblib

Is it possible to split up a single big legend into multiple (usually 2) smaller ones.from pylab import *t = arange(0.0, 2.0, 0.01) s = sin(2*pi*t) plot(t, s, linewidth=1.0, label="Graph1") g…

Python 3.x - iloc throws error - single positional indexer is out-of-bounds

I am scraping election data from a website and trying to store it in a dataframe import pandas as pd import bs4 import requestscolumns = [Candidate,Party,Criminal Cases,Education,Age,Total Assets,Liabi…

Supposed automatically threaded scipy and numpy functions arent making use of multiple cores

I am running Mac OS X 10.6.8 and am using the Enthought Python Distribution. I want for numpy functions to take advantage of both my cores. I am having a problem similar to that of this post: multithre…

Golang net.Listen binds to port thats already in use

Port 8888 is already bound on my (OS X 10.13.5) system, by a process running inside a docker container:$ netstat -an | grep 8888 tcp6 0 0 ::1.8888 *.* LISTE…