I'm working with global vars but I get the error "NameError: name 'second_global_var' is not defined"
def my_function():
global first_global_var, second_global_var
if(first_global_var or second_global_var):
pass
Why it shows the error for 'second_global_var' and not for 'first_global_var', even if I define them each one with in its own line with global, the error persist for the variable 'second_global_var'.
The global statement does not create variables. It just makes Python look for them in the global namespace instead of the local namespace. In other words, saying global some_name tells Python to look for a global variable called some_name whenever you try to refer to some_name.
If that variable doesn't exist when you try to use it, Python will raise a NameError.
Inside the interpreter, you have:
>>> def my_function():
... global first_global_var, second_global_var
... if(first_global_var or second_global_var):
... pass
...
Then calling the function:
>>> my_function()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in my_function
NameError: global name 'first_global_var' is not defined
It complains about the first variable that it is not defined.
Related
I'm trying to print method's name using __getattribute__
but I get typeerror everytime I called the method, and the method is not excuted, is there anyway to get rid of the type error and have the method excuted ?
class Person(object):
def __init__(self):
super()
def test(self):
print(1)
def __getattribute__(self, attr):
print(attr)
p = Person()
p.test()
The above code gives the error
test
Traceback (most recent call last):
File "test1.py", line 15, in <module>
p.test()
TypeError: 'NoneType' object is not callable
Is there anyway to print the method's name only without giving the error ?
I tried to catch typeError inside __getattribute__ method, but it doesn't work
Another question is, why it says None Type object is not callable here
Thank you !
Ps. I know I can catch the error when I call the method, I mean is there anyway to deal this error inside __getattribute method? since my goal is to print method's name everytime a method is called
Answering your second question first, why is it saying NoneType not callable.
When you call p.test() Python tries to lookup the test attribute of the p instance. It calls the __getattribute__ method that you've overridden which prints 'test' and then returns. Because you're not returning anything it implicitly returns None. p.test is therefore None and calling it gives the error you get.
So how do we fix this? Once you've printed the attribute name, you need to return the attribute you're after. You can't just call getattr(self, attr) or you'll end up in an infinite loop so you have to call the method that would have been called if you hadn't overridden it.
def __getattribute__(self, attr):
print(attr)
return super().__getattribute__(attr) # calls the original method
I have a function 'draw_humans' in class 'TfPoseEstimator' in 'estimator.py' which is defined as:
def draw_humans:
global cocoDict
cocoDict = {}
cocoDict = dict(zip(a,zip(b,c)))
'''
'''
return (npimg, cocoDict, dist_dict)
I call this function in the main.py module and assign the returned values to variables like this:
image, cocoDict_clone, dist_dict_clone = TfPoseEstimator.draw_humans(image, humans, imgcopy=False)
But I get the error mentioned above.
Traceback (most recent call last):
File "run_webcam.py", line 306, in <module>
image, cocoDict_clone, dist_dict_clone = TfPoseEstimator.draw_humans(image, humans, imgcopy=False)
File "C:\Python\Python37\summer\PoseEstimation\tf_pose\estimator.py", line 772, in draw_humans
return (npimg, cocoDict, dist_dict)
NameError: name 'cocoDict' is not defined
[ WARN:1] terminating async callback
I have even tried to make it global but it did not work. Usually, it does work, can someone figure it out?
Actually, the problem was related to the scope of the variables (cocoDict in my case). This dictionary was initialized within the for loop but was being returned outside it. So, I declared it before the for loop and then after manipulating it within the for loop, returned it with no issues.
def draw_humans(npimg, humans, imgcopy=False):
global cocoDict
cocoDict = {}
for human in humans:
'''
'''
return (npimg, cocoDict, dist_dict)
I guess scope in Python is causing me a lot of efforts as I am from a C++ background.
The following code
class Foo:
def bar(self) -> None:
pass
foo = Foo()
if hasattr(foo.bar, '__annotations__'):
foo.bar.__annotations__ = 'hi'
crashes with
AttributeError: 'method' object has no attribute '__annotations__'
How can this happen?
The attribute error here is raised because you can't set any attribute on a method object:
>>> foo.bar.baz = 42
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'method' object has no attribute 'baz'
The exception here is perhaps confusing because method objects wrap a function object and proxy attribute read access to that underlying function object. So when attributes on the function exist, then hasattr() on the method will return True:
>>> hasattr(foo.bar, 'baz')
False
>>> foo.bar.__func__.baz = 42
>>> hasattr(foo.bar, 'baz')
True
>>> foo.bar.baz
42
However, you still can't set those attributes via the method, regardless:
>>> hasattr(foo.bar, 'baz')
True
>>> foo.bar.baz = 42
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'method' object has no attribute 'baz'
So, just because the attribute can be read doesn't mean you can set it. hasattr() is speaking the truth, you just interpreted it to mean something different.
Now, if you tried to set the __annotations__ attribute directly on the underlying function object you'd get another error message:
>>> foo.bar.__func__.__annotations__ = 'hi'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __annotations__ must be set to a dict object
You would want to use a dictionary object here:
>>> foo.bar.__func__.__annotations__ = {'return': 'hi'}
>>> foo.bar.__annotations__
{'return': 'hi'}
However, because __annotations__ is a mutable dictionary, it is just easier to directly manipulate the keys and values to that object, which is perfectly feasible to do via the method wrapper:
>>> foo.bar.__annotations__['return'] = 'int'
>>> foo.bar.__annotations__
{'return': 'int'}
Now, if you were hoping to set per instance annotations, you can't get away with setting attributes on method objects, because method objects are ephemeral, they are created just for the call, then usually discarded right after.
You would have to use custom method descriptor objects via a metaclass and re-create the __annotations__ attribute for those each time, or you could instead pre-bind methods with a new function object that would be given their own attributes. You then have to pay a larger memory price:
import functools
foo.bar = lambda *args, **kwargs: Foo.bar(foo, *args, **kwargs)
functools.update_wrapper(foo.bar, Foo.bar) # copy everything over to the new wrapper
foo.bar.__annotations__['return'] = 'hi'
Either way you completely kill important speed optimisations made in Python 3.7 this way.
And tools that operate on the most important use case for __annatotions__, type hints, do not actually execute code, they read code statically and would completely miss these runtime alterations.
You're getting an error. because __annotations__ is a dictionary. If you want to change values you'll have to do it like this:
if hasattr(foo.bar, '__annotations__'):
foo.bar.__annotations__['return'] = 'hi'
This will make the return value of your foo.bar be hi instead of None. The only thing I'm not sure about is how the __annotations__ are protected, not allowing you to change them from a dict to string, but I suppose it's some internal check in the source.
UPDATE
For more control over the signature you can use the inspect module and get the Signature object of your class(or method) and edit it from there. For example
import inspect
sig = inspect.signature(foo.bar)
sig.return_annotation # prints None (before modifying)
sig.replace(return_annotation="anything you want")
More on that here
am getting that error?
Traceback (most recent call last):
File "python", line 5, in <module>
NameError: name 'maximum' is not defined
You have to return maximum in your max() and then call your defined function in print or put print(maximum) in max() definition and just call defined function.
I would suggest to rename your function.
You def a function, but neither call it or makes it return.
Why is python shell throwing a NameError where as windows console a ValueError?
def PrintArgs(*arg):
list = ['1','2']
for i in arg:
try:
print(list[int(i)])
except ValueError:
print('Please enter integer value')
except NameError:
print('Name Error')
if __name__ == '__main__':
PrintArgs(*sys.argv[1:])
Providing the following arguments to Windows Console gives this output:
Here is how I call the code in windows console:
C:\>C:\Python34\python C:\Users\User\Documents\PYTest\Test.py 0 a
1
Please enter integer value
Providing the following arguments to Python Shell does not display the cusom error for NameError as mentioned in the code above, but mentions the following error:
PrintArgs(0,a)
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
PrintArgs(0,a)
NameError: name 'a' is not defined
In the code example you've provided you define a list i, then you iterate over a collection called list you never initiated, and assign the values in this list to i, thus dropping the original value. I guess you only provided a part of your code, please provide a minimum working example.
If I try to reproduce your problem, I only get a type error, for iterating over a list which is not initialized.