On Wed, Jan 22, 2020 at 5:48 AM Johan Vergeer <johanverg...@gmail.com> wrote: > > I have worked with both C# and Python for a while now and there is one > feature of C# I'm missing in the Python language. > > This feature is the "nameof" operator. > (https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/nameof). > The place I use this the most in C# is in `ToString()` methods or logging > messages. > This makes sure the developer cannot forget to update the name of a member. > > As an example I created this `Person` class. > > ``` > class Person: > def __init__(self, name, age): > self.name = name > self.age = age > > def __repr__(self): > return f"Person(name: {self.name}, age: {self.age})" > ``` > > With the `nameof` operator this would look like the following: > > ``` > class Person: > def __init__(self, name, age): > self.name = name > self.age = age > > def __repr__(self): > return f"{nameof(Person)}({nameof(self.name)}: {self.name}, > {nameof(self.age)}: {self.age})" > ``` > > What do you think about this?
Some objects (including types) have "inherent names", which can be accessed using the __name__ attribute: def __repr__(self): return f"{type(self).__name__}(... etc ...)" I'm not sure how this compares to what nameof(Person) should return, but the above idiom (or something like it) is very common in Python, as it allows repr to acknowledge a subclass. If you create "class Martian(Person): pass", then a Martian's repr will say "Martian". On the other hand, if you actually want "the name of the surrounding class", then that can be spelled __class__.__name__, and that will always be Person even if it's been subclassed. Not nearly as common, but available if you need it. For the attributes, though, there's no inherent name (at least, I presume self.name is a string and self.age is some sort of number). You CAN do some neat tricks with f-strings: return f"{self.name=}" but that would include "self.name" rather than simply "name", which I think is what you want. I would suggest creating a helper function that takes a list of attribute names, loops over them, and grabs the attributes. Using getattr in a loop is going to be less error-prone than your proposed form, which still has to have the word "age" repeated twice. Hmm. Maybe this should be a recipe in the docs, or something: "how to make a repr that reconstructs an object". def describe(obj, attrs): attrs = [f"{a}={getattr(obj, a)!r}" for a in attrs] return f"{type(obj).__name__}({", ".join(attrs)})" def __repr__(self): return describe(self, "name age spam ham location".split()) This comes up often enough that I think it'd be a useful thing to point people to. ChrisA _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/AH3FUD4IQW62OXMYAVDEQPXO4QZFVS3U/ Code of Conduct: http://python.org/psf/codeofconduct/