It is a couple of days later, but I managed to create a more expanded proposal.
This proposal is about having a simple and consistent way of getting the name of an object. Whether it is a class, type, function, method or variable or any other object. # Why? ## Usage in strings The first situation this could be used is in strings (for example in `__repr__`, `__str__` and `print()`) I've come across too many situations where the developer made a typo (which is usually the developer is a hurry or just having a bad day) or in the case of a refactoring where the developer didn't rename the object in the string representation. To be honest, I am a big fan of IDEs, like PyCharm, which have great refactoring tools, but it doesn't refactor strings. ## Usage in comparisons Another situation is when you want to do a comparison. An example of this would be: ```python def my_factory(class_name: str): if class_name == "Foo": return Foo() if class_name == "Bar": return Bar() ``` I know this is a very simple example that can be solved with the example below, but it would be nice if we can do the same with methods, functions and attributes. ```python def my_factory(class_name: str): if class_name == Foo.__name__: return Foo() if class_name == Bar.__name__: return Bar() ``` ## The Zen of Python The Zen of Python has a couple of items that apply to this one in my opinion: Beautiful is better than ugly. Simple is better than complex. Sparse is better than dense. Readability counts. **There should be one-- and preferably only one --obvious way to do it.** Although that way may not be obvious at first unless you're Dutch. # How? >From the messages in this thread I concluded there is some confusion about >what I would like to achieve with this proposal. In this part I will try to make it more clear what the behavior would be. For now I'll stick to the C# naming `nameof()`. ## Class names When you want to get the name of a class, you should just use the name. So `nameof(Foo)` becomes `"Foo"` and `nameof(type(foo))` also becomes `"Foo"`. The results are basically the same as `Foo.__name__` and `type(foo).__name__`. ## Function names When you want to get the name of a function, you would do the same you do with a class. ```python def foo(): ... nameof(foo) #Returns 'foo' ``` This is (again) the same as `foo.__name__` ## Attribute names You should be able to get the name of an attribute. ```python class Foo: bar: str = "Hello" def __init__(self): self.baz = "World" def __str__(self): return f"{nameof(self.bar)}: {bar}, {nameof(self.baz): {baz}}" # Returns "bar: Hello, baz: World" foo = Foo() nameof(foo) # Returns "foo" nameof(foo.bar) # Returns "bar" ``` As Chris Angelico suggested we can already use a special syntax for f-strings which is pretty cool, but it has the limitation that we have less control over the output. ```python return f"{self.name=}" # returns `self.name="something"` ``` ## Invalid usage There are also situations that will return an error. ```python nameof(1) nameof("foo") nameof(["bar", "baz"]) ``` ## Stuff to think about There are also situations that I haven't been able to make a decision about and I think these should be discussed further down the road. ```python nameof(None) nameof(type) nameof(int) _foo = Foo() nameof(_foo) #Should this return "_foo" or "foo"? ... ``` ## How should the interpreter handle it? I think the interpreter should handle it as anything else that is passed to a function, so when the value passed to the `nameof()` function doesn't exist, an error should be thrown. # How can this be built in the Python language (or a library) Some people responded this will be very hard to implement because of the way Python is built. To be honest, I don't know nearly enough about the internals of Python to make a solid statement on that. I also don't know how the new f-string syntax `f"{self.name=}"` works under the hood, but it does give me the impression that implementing this proposal should be possible. # What about `__name__`? Most of the examples I wrote above can be solved by just using `__name__`, which solves most use cases, except for variable and attribute names, which cannot be resolved right now because objects don't have names. So when we want to follow `There should be one-- and preferably only one --obvious way to do it.` it would be better to use `__name__` on an object, but I believe that would cause breaking changes. What I mean is: ```python class Foo: ... foo = Foo print(foo.__name__) # Prints "foo" foo = Foo() print(foo.__name__) # Throws AttributeError: 'Foo' object has no attribute '__name__' ``` _______________________________________________ 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/CIHKBAMUCEY5HE2NSAXLH3SLDR5WIQYW/ Code of Conduct: http://python.org/psf/codeofconduct/