+ 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?
22 Réponses
+ 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.
+ 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.
+ 3
🤔 That's an interesting question.. I am still researching right now
+ 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.
+ 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
+ 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
+ 1
ValueError is not supposed to be a variable, It's probably a class
raise ValueError("Message")
This should do the trick
+ 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
+ 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
+ 1
Also, Check out the documentation: https://docs.python.org/3/library/exceptions.html
+ 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?
+ 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?
+ 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?
+ 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?
+ 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.
+ 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
+ 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
+ 1
In summary: To actually overwrite the exception for all calling blocks, You need to edit the source code
+ 1
Hatsy Rei Wow, that's really cool. Thank you very much for answering my question.
+ 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).