Sorry, sent early… ignore that and try this version.

> 
> On Jan 31, 2020, at 19:58, Andrew Barnert <abarn...@yahoo.com> wrote:
> 
> Here’s a concrete proposal.
> 
tl;dr: `nameof x == "x"`, and `nameof x.y == "y"`.

Rationale:

Even though as far as Python is concerned `nameof x.y` is identical to `"y"`, 
it can make a difference to human readers—and to at least two classes of 
automated tools.

When refactoring code to rename something, there is no way to tell whether a 
string—or a substring in a larger string—that matches the name should be 
changed. But a nameof expression is unambiguously a reference to the name, and 
therefore the tool knows that it needs to change.

For example:

    class Spam:
        cheese = 10
        def __repr__(self)
            return f"<{type(self).__name__} at {id(self)} {nameof self.cheese}: 
{self.cheese}>"

If I ask my IDE to rename cheese to beans, that `nameof self.cheese` is 
unambiguous: it clearly should be changed to `nameof self.beans`. If I had just 
included the substring “cheese” within the string, it would need some kind of 
heuristics or trained AI or something to figure that out.

Similarly for this example:

    rpc.register(nameof spam, spam)

Again, if I just used the string "spam", renaming the function spam to eggs 
would be ambiguous.

And if I used spam.__name__, this would be unambiguous, but potentially 
incorrect. For example:

    spam = SpamHandler.handle
    rpc.register(spam.__name__, spam) # oops

A second use is static type checkers. If a type checker sees `nameof 
spam.eggs`, it can apply whatever rules it would use for `spam.eggs` itself. 
For example, if it can figure out the type or `spam`, and that type declared 
its attributes, and there is no attribute named `eggs`, this can be a static 
type error.

Grammar:

    atom ::= identifier | literal | enclosure | nameof_atom
    nameof_atom ::= "nameof" nameof_name
    nameof_name ::= identifier | attributeref

Semantics:

The value of nameof_atom is a string: the name of the identifier itself for the 
first case, or of the identifier after the dot for the second case. The string 
value is semantically identical to a literal for the same string, so `nameof 
foo.bar` and `"bar"` should be compiled to identical code. There is no 
difference to Python, only to human readers and automated tools.

Compatibility:

Because `nameof` is a valid identifier today, there may be code that uses it as 
a variable name. This means the usual 3-version __future__ schedule is probably 
needed. And a search through public code to make sure it isn’t a lot more 
common than you’d expect.

Alternatives:

Why no parentheses? Because in Python, only function calls take parentheses. In 
C# (where this feature originated) there are other compile-time operators like 
sizeof that take parens, and ultimately this goes back to making those 
operators look like calls to preprocessor macros in 1970s C; that isn’t 
relevant in Python, so requiring parens would just be confusing for no benefit.

Why no runtime behavior? Because there’s nothing that could reasonably be 
checked. Unlike C#, Python doesn’t have “variables” at runtime; it just has 
names bound to objects in namespaces. Given an object, there is no way to know 
what name you used to access it. Also, Python attributes are completely 
dynamic—in C#, `spam.eggs` means something like “the int-typed value found 
between 4 and 8 bytes after the start of `spam` in memory”; in Python, it means 
“the result of calling getattr(spam, 'eggs'), which could be any arbitrary 
code”. Even if it were possible, it’s not clear what the benefit would be, and 
without someone making a case for a benefit, it’s not worth trying to come up 
with something clever in the first place.

_______________________________________________
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/I77NGRZJWPCZMY7JLPWUKD5CIUV4FLSN/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to