Python modifies unicode identifiers?

Viewed 109

Python 3.8 supports using a limited set of non-ASCII Unicode characters in identifiers. So, it seems that it is valid to use as a character in an identifier.

However, something is wrong...

Problem

def f():
    print(f'{=}')

f(1)
f(=2)
f(**{'': 3})

The first two calls are fine, but the third fails:

=1
=2
Traceback (most recent call last):
  File "sigma.py", line 24, in <module>
    f(**{'': 3})
TypeError: f() got an unexpected keyword argument ''

Analysis

Let's see what is actually going on:

def f2(**kw):
    for name, value in kw.items():
        print(f'{name}={value}     {ord(name)=}')
f2(=2)
f2(**{'': 3})

It prints:

Σ=2     ord(name)=931
=3     ord(name)=120506

I called it with both times, but it was changed to the very similar simpler Σ in the first call.

It seems that an argument named (U+1D6BA) is implicitly renamed to Σ (U+03A3), and in every call to the function, argument is also implicitly renamed to Σ, except if it is passed as **kwargs.

The Questions

Is this a bug? It does not look like it is accidental. Is it documented? Is there a set of true characters and a list of alias characters available somewhere?

1 Answers

I think this happens because of the way Python handles characters.
If you set a variable using one of your provided sigma letters: Σ or , you can also access it with the other one. Knowing that both these snippets work:

>>> Σ = 5
>>> 
5
>>>  = 5
>>> Σ
5

You can see in globals() it is assigned to Σ (ord: 931)
My guess is Python modifies the character before performing a variable lookup.
Similar discussion here, posted by me in github/wtfpython

Related