+ 2

What's happening in this code?

This doesn't work: ValueError = 12 raise ValueError But this works (I mean, it raises the "real" ValueError): ValueError = 12 print(int('a')) Why is it so in the second case? I had tried to delete the ValueError variable (del ValueError) but it didn't work. What's happening?

6th Aug 2021, 8:21 AM
Calvin Thomas
Calvin Thomas - avatar
22 Respostas
+ 8
With the scoping logic I explained, you can actually del ValueError by specifying the namespace of ValueError, which in this case is an alias for the built-in module where ValueError originated from. del __builtins__.ValueError However, this does not cause int('a') to fail to throw the exception, since __builtins__ is just an alias for the actual built-in module, and the actual built-in module is not part of the main script's namespace, so there is effectively no way to delete the actual definition of ValueError.
6th Aug 2021, 9:54 AM
Hatsy Rei
Hatsy Rei - avatar
+ 4
My understanding is that built-in exceptions are defined locally within an 'exception' module (which is built-in, and does not have to explicitly be imported). Ultimately, ValueError is defined in this module, and is raised when code within that module is executed. Since you are overwriting the definition of ValueError within your script instead of overwriting the local copy within the built-in exception module, it does not prevent the actual exception from being thrown when the module deems necessary. You can try this offline. Create a lib.py with the following content: myval=39 def func(): print(myval) Then create the following script: from lib import * myval=40 func() Observe that 39 is printed although myval appears to have been overwritten.
6th Aug 2021, 8:46 AM
Hatsy Rei
Hatsy Rei - avatar
+ 3
🤔 That's an interesting question.. I am still researching right now
6th Aug 2021, 9:06 AM
Ahmed Yasser
Ahmed Yasser - avatar
+ 3
Calvin Thomas The scoping part here is a little lengthy to explain, but I found this article which talks about how each module has its own global scope, and that global variables are unique to their own modules. https://towardsdatascience.com/common-mistakes-when-dealing-with-multiple-JUMP_LINK__&&__python__&&__JUMP_LINK-files-b4f4dc4d5643 In order to correctly overwrite the value of a variable declared in a different module, it is necessary to specify the module namespace. E.g. in my previous example, instead of from lib import * myval = 40 you'll need to do import lib lib.myval = 40 The main design rationale for why the first example does not overwrite is to save every single programmer who writes modules from having to somehow contact each other to make sure that they do not use the same global variable name.
6th Aug 2021, 9:48 AM
Hatsy Rei
Hatsy Rei - avatar
+ 2
Calvin Thomas ValueError will be considered as a variable in 1st case In 2nd case a is a character but you are casting to int that's why there is ValueError
6th Aug 2021, 8:46 AM
A͢J
A͢J - avatar
+ 2
In conclusion, redefining variables/objects in Python is scope based. myval = 39 def func(): myval = 40 print(myval) func() print(myval) Output: 40 39
6th Aug 2021, 8:50 AM
Hatsy Rei
Hatsy Rei - avatar
+ 1
ValueError is not supposed to be a variable, It's probably a class raise ValueError("Message") This should do the trick
6th Aug 2021, 8:44 AM
Ahmed Yasser
Ahmed Yasser - avatar
+ 1
In Python, all exceptions must be instances of a class that derives from BaseException That being said, To define your own Exception you can make a class and pass the Exception as the arg class MyException(Exception): pass raise MyException
6th Aug 2021, 8:49 AM
Ahmed Yasser
Ahmed Yasser - avatar
+ 1
you can't raise Exception without BaseException! you are re-defining builtin 'ValueError' which is not good. what are you trying to do ? your question is not clear! in second example you are getting ValueError because "ValueError raised when an operation or function receives an argument that has the right type but inappropriate value." https://www.sololearn.com/learning/2443/ https://docs.python.org/3.8/library/exceptions.html#ValueError
6th Aug 2021, 8:50 AM
Ratnapal Shende
Ratnapal Shende - avatar
+ 1
Also, Check out the documentation: https://docs.python.org/3/library/exceptions.html
6th Aug 2021, 8:52 AM
Ahmed Yasser
Ahmed Yasser - avatar
+ 1
A͢J - S͟o͟l͟o͟ H͟e͟l͟p͟e͟r͟ The intention of my code was to mask the error. Why does it throw the exception, if the variable containing the reference to the actual value error class is replaced with that of an int?
6th Aug 2021, 8:52 AM
Calvin Thomas
Calvin Thomas - avatar
+ 1
Ratnapal Shende Well, I know that this isn't useful. But I had came across this when i was playing around with exceptions. I couldn't find any reasons why this won't work. Re-defining it doesn't throw an error. I mean, when the actual error occurs when giving an invalid value to the str() cast function, how is the ValueError class "called" if it has been re-defined?
6th Aug 2021, 8:55 AM
Calvin Thomas
Calvin Thomas - avatar
+ 1
Hatsy Rei Well, this makes total sense. But I don't understand about this "module". In my code, I've modified the ValueError variable (everything is a variable for me). Now, where does this "code-scope" end? I mean, there's only a single scope, i.e., the main scope, right? How could the variable's value change, then?
6th Aug 2021, 9:02 AM
Calvin Thomas
Calvin Thomas - avatar
+ 1
Ahmed Yasser Thank you, but this doesn't solve the original question. Why does the error get raised in the first place, if I have replaced this one with another value?
6th Aug 2021, 9:04 AM
Calvin Thomas
Calvin Thomas - avatar
+ 1
Hatsy Rei Why doesn't 'del' work here? This throws another exception: del ValueError Also, why doesn't 'ValueError()' exit the program with the error message? What does 'raise' do actually? I had thought that simply calling the class would throw the exception.
6th Aug 2021, 9:05 AM
Calvin Thomas
Calvin Thomas - avatar
+ 1
Calvin Thomas In 1st you are getting TypeError as ValueError is a class and you have assigned int value to that class. There is type mismatch. So if you want to raise actual TypeError then you have to do like this: ValueError('12') raise ValueError
6th Aug 2021, 9:19 AM
A͢J
A͢J - avatar
+ 1
I figured something out ``` ValueError = "a" raise ValueError ``` Actually overwrites the class "IN YOUR SCOPE" When you call int(invalid arg) The exception behind its back-end basically remains the same thus, It successfully raise any exception
6th Aug 2021, 9:19 AM
Ahmed Yasser
Ahmed Yasser - avatar
+ 1
In summary: To actually overwrite the exception for all calling blocks, You need to edit the source code
6th Aug 2021, 9:21 AM
Ahmed Yasser
Ahmed Yasser - avatar
+ 1
Hatsy Rei Wow, that's really cool. Thank you very much for answering my question.
6th Aug 2021, 11:13 AM
Calvin Thomas
Calvin Thomas - avatar
+ 1
Runtime Terror Thank you, but the original question is totally unrelated. You may have a look at Hatsy Rei's answer to have a clear idea of what I had actually meant. What I had meant was how ValueError is raised in the second code if it's been replaced by something else. It seems that all of this has to deal with scope (the best relatable thing I can find is a Python function object).
6th Aug 2021, 3:11 PM
Calvin Thomas
Calvin Thomas - avatar