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 -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/CIHKBAMUCEY5HE2NSAXLH3SLDR5WIQYW/
Code of Conduct: http://python.org/psf/codeofconduct/