#365 · Classes · Advanced · 130 XP · about 25 min
Some data should never change once it is made: a point on a map, a date, a database row you have already checked. Objects that cannot change are also the only safe dictionary keys and set members. Build a class Record like that.
Record(**fields) makes a record from keyword arguments, for example Record(name='Ada', year=1815). Fields are read as attributes: r.name. Reading a field that does not exist raises AttributeError.r.year = 1816, r.x = 1, del r.name) raises AttributeError, and the record stays as it was.r.replace(**changes) returns a new record with some fields changed, leaving r untouched. A name that is not one of the record's fields raises TypeError.r.fields() returns a tuple of the field names in the order they were given.==) when they have the same field names with equal values, in any order. A record is never equal to something that is not a record.hash(r): equal records must have equal hashes, and records that differ should almost always have different hashes, so that sets and dicts of records stay fast.repr(r) returns the text Record(name='Ada', year=1815): the fields in the order given, each value written with repr.r = Record(name='Ada', year=1815) r.name # returns 'Ada' r.year = 1816 # raises AttributeError r.replace(year=1816) # Record(name='Ada', year=1816) r == Record(year=1815, name='Ada') # True len({r, Record(year=1815, name='Ada')}) # 1
replace and fieldsFirst solves only, ranked by stars and then time.