python / cpython

The Python programming language
https://www.python.org
Other
62.17k stars 29.88k forks source link

Improve ``NameError`` message when non-mangled name exists in the global scope #119901

Open PC-Killer opened 3 months ago

PC-Killer commented 3 months ago

Bug report

Bug description:

Here is the code:

def __a():
    print("A")

class A:
    def b(self):
        __a()

a = A()
a.b()

It was expected to show a short message "A". However, I got a NameError:

❯ python3.12 bug\ represent.py
Traceback (most recent call last):
  File "/home/PC-Killer/python_work/Demos/bug represent.py", line 11, in <module>
    a.b()
  File "/home/PC-Killer/python_work/Demos/bug represent.py", line 7, in b
    __a()
    ^^^
NameError: name '_A__a' is not defined
❯ python3.13 bug\ represent.py
Traceback (most recent call last):
  File "/home/PC-Killer/python_work/Demos/bug represent.py", line 11, in <module>
    a.b()
    ~~~^^
  File "/home/PC-Killer/python_work/Demos/bug represent.py", line 7, in b
    __a()
    ^^^
NameError: name '_A__a' is not defined

It seems that the name had been translated in an unexpected way.

CPython versions tested on:

3.12, 3.13

Operating systems tested on:

Linux

Eclips4 commented 3 months ago

This is intended behaviour. Explanation: https://docs.python.org/3.12/faq/programming.html#i-try-to-use-spam-and-i-get-an-error-about-someclassname-spam.

PC-Killer commented 3 months ago

Hmm...... But I'm trying to call a function outside the class. Why should it "mangled"? Shouldn't it happen only I am trying to get a class method?  

Anonymous @.***

 

------------------ 原始邮件 ------------------ 发件人: "Kirill @.>; 发送时间: 2024年6月1日(星期六) 晚上7:19 收件人: @.>; 抄送: @.>; @.>; 主题: Re: [python/cpython] Unexpected NameError (Issue #119901)

This is intended behaviour. Explanation: https://docs.python.org/3.12/faq/programming.html#i-try-to-use-spam-and-i-get-an-error-about-someclassname-spam.

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you authored the thread.Message ID: @.***>

Eclips4 commented 3 months ago

Hmm...... But I'm trying to call a function outside the class. Why should it "mangled"? Shouldn't it happen only I am trying to get a class method?

In an ideal world, yes. But how do we determine that some lookups inside the class body are class-specific? These slow down performance due to additional lookups and just slightly increase user experience. To summarize, just don't name your functions with double leading underscores. :)

PC-Killer commented 3 months ago

That's perhaps the best solution:) But, could the interpreter tell the user the problem when it show the error? I don't think showing error needs to be as fast as possible :) 

Anonymous @.***

 

------------------ 原始邮件 ------------------ 发件人: "Kirill @.>; 发送时间: 2024年6月1日(星期六) 晚上7:31 收件人: @.>; 抄送: @.>; @.>; 主题: Re: [python/cpython] Unexpected NameError (Issue #119901)

Hmm...... But I'm trying to call a function outside the class. Why should it "mangled"? Shouldn't it happen only I am trying to get a class method?

In an ideal world, yes. But how do we determine that some lookups inside the class body are class-specific? These slow down performance due to additional lookups and just slightly increase user experience. To summarize, just don't name your functions with double leading underscores. :)

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you authored the thread.Message ID: @.***>

Eclips4 commented 3 months ago

That's perhaps the best solution:) But, could the interpreter tell the user the problem when it show the error? I don't think showing error needs to be as fast as possible :)

Yes, that's sounds reasonable for me.

Eclips4 commented 3 months ago

cc @pablogsal Do you think it's worth improving the error message for "NameError" in such cases?

pablogsal commented 3 months ago

I can take a look this weekend 👍

SweetyAngel commented 3 months ago

I want to extend this issue. This code:

def __a():
    print("A")

class A:
    def b(self):
        self.__a()

a = A()
a.b()

throws another error:

AttributeError: 'A' object has no attribute '_A__a'

If NameError is planning to be improved, this should be also fixed

pablogsal commented 3 months ago

Yeah they normally go in tandem. I will let you know what we decide here once I have some time to play with this