It looks strange. A variable with a name classes is printed but is undefined when trying to execute filter(...) contruction.
Here is a code:
def start(self, tag, attrib):
classes = attrib[self._CLASS_ATTR] if self._CLASS_ATTR in attrib else None
if tag == self._TAG_P:
p = self._doc.add_paragraph('')
self._cur_p = p
if classes is not None:
alignments = [self._left_align, self._center_align, self._right_align]
import pdb; pdb.set_trace()
alignments = filter(lambda x: partial(x.is_in, classes), alignments)
if len(alignments) > 0:
p.alignment = alignments[0].get()
assert len(alignments) < 2
Pdb stops on it's break. When I try to execute filter():
(Pdb) print filter(lambda x: partial(x.is_in, classes), alignments)
*** NameError: global name 'classes' is not defined
But:
(Pdb) print classes
center title
(Pdb) classes
u'center title'
Why the filter(...) instruction could not be executed normally?
Let's reproduce it in short code:
from functools import partial
def f():
classes = 'my_classes'
def my_bool(obj, _):
return True
if classes is not None:
import pdb; pdb.set_trace() # point a
alignments = filter(lambda x: my_bool(x, classes), ['1', '2', '3'])
import pdb; pdb.set_trace() # point b
pass
f()
...
(Pdb) filter(lambda x: my_bool(x, classes), ['1', '2', '3'])
*** NameError: global name 'my_bool' is not defined
However, the command c (continue) of pdb in point a does not generate an exception.
pdb is an eval loop. An eval loop essentially takes what you write to the prompt line by line and eval(...)s it. This means it doesn't bind closure-scoped variables in defined functions (lambdas). eval (which is a function) has its own scope and doesn't participate in the closure you are evaluating in.
You can see the equivalent problem from this example code:
def f():
x = 1
return eval('lambda: x')
>>> f()()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <lambda>
NameError: name 'x' is not defined
An (unfortunate) workaround is to define any lambdas up-front and use them in your pdb expression.
Related
I'm making a program that makes variables with a base name and variables like their id and series.
I use vars()[str(name+id+serie)] to make them and make it a button using the tkinter module.
When I launch it, it works until it tries to .get() the value from it, saying
keyError (variable name)
I tried to change how it's named, making it int() or moving the .get() here and there but nothing works.
# -*- coding: utf-8 -*
from tkinter import *
import math
import random
fenetre = Tk()
fenetre.geometry("1000x1000")
kanvas=Canvas(fenetre, width=500, height=500, bg="white")
id = 0
serie = 1
idcounter=0
while 1:
print("serie =",serie)
def cheezegrater():
global serie,id,idcounter
vars()[str("var_cheeze_sum"+str(serie))]=0
for o in range(1,val+1):
print("var11 =",var_cheeze_value11.get())
vars()[str("var_cheeze_sum"+str(serie))] += vars()[str("var_cheeze_value"+str(id-val+o)+str(serie))].get()
kanvas.pack()
fenetre.mainloop()
vars()[str("nombre_de_formes"+str(serie))] =int(float(input("combien?")))
val = vars()[str("nombre_de_formes"+str(serie))]
for o in range(1,val+1):
id+=1
vars()[str("var_cheeze_value"+str(id)+str(serie))] = Entry(kanvas, width=10)
o+=1
vars()[str("var_cheeze_value"+str(id)+str(serie))].pack
kanvas.pack()
fenetre.mainloop()
Traceback (most recent call last):
File "C:\Users\Utilisateur\AppData\Local\Programs\Python\Python37-32\lib\tkinter\__init__.py", line 1705, in __call__
return self.func(*args)
File "C:/Users/Utilisateur/.PyCharmEdu2019.1/config/scratches/scratch_1.py", line 38, in cheezegrater
vars()[str("var_cheeze_sum"+str(serie))] += vars()[str("var_cheeze_value"+str(id-val+o)+str(serie))].get()
KeyError: 'var_cheeze_value11'
You're inside a function and therefore outside of the same namespace where vars() doesn't contain those variables. Have a look at this example:
x = 1
print('Outside', x, 'x' in vars())
def f():
global x
print('Inside', x, 'x' in vars())
f()
It prints:
Outside 1 True
Inside 1 False
As you can see, even though we have global x and can print its value, it's not a key in vars() inside the function.
Also: Why are global variables evil?
Why did you choose to use vars() in the first place? Maybe you could just use a separate dict object instead? There's a lot of information in this question Python: Using vars() to assign a string to a variable
An improved version of the example from above might look like this:
data = {}
key = 'x'
data[key] = 1
print('Outside', data['x'], 'x' in data)
def f(data):
print('Inside', data['x'], 'x' in data)
f(data)
Of course, instead of 'x', you can use your own keys like str("var_cheeze_sum"+str(serie)).
comodin.py
def name():
x = "car"
comodin_1.py
import comodin
print comodin.x
Error:
Traceback (most recent call last):
File "./comodin_2.py", line 4, in <module>
print comodin.x
AttributeError: 'module' object has no attribute 'x'
Is this possible?
In the code you wrote, "x" doesn't exist in "comodin". "x" belongs to the function name() and comodin can't see it.
If you want to access a variable like this, you have to define it at the module scope (not the function scope).
In comodin.py:
x = "car"
def name():
return x
In comodin_1.py:
import comodin
print comodin.name()
print comodin.x
The last 2 lines will print the same thing. The first will execute the name() function and print it's return value, the second just prints the value of x because it's a module variable.
There's a catch: you have to use the 'global' statement if you want to edit the value "x" from a function (add this at the end of comodin.py):
def modify_x_wrong():
x = "nope"
def modify_x():
global x
x = "apple"
And in comodin_1.py:
print comodin.name() # prints "car"
comodin.modify_x_wrong()
print comodin.name() # prints "car", once again
comodin.modify_x()
print comodin.name() # prints "apple"
I'm doing code generation and I end up with a string of source that looks like this:
Source
import sys
import operator
def add(a,b):
return operator.add(a,b)
def mul(a,b):
return operator.mul(a,b)
def saveDiv(a,b):
if b==0:
return 0
else:
return a/b
def subtract(a,b):
return operator.sub(a,b)
def main(y,x,z):
y = int(y)
print y
x = int(x)
print x
z = int(z)
print z
ind = lambda y,x,z: mul(saveDiv(x, add(z, z)), 1)
return ind(y,x,z)
print main(**sys.argv)""
Execution
When I'm executing code using exec() and then piping it through stdoutIO()
Working
args={'x':"1",'y':"1",'z':"1"}
source = getSource()
sys.argv = args
with stdoutIO() as s:
exec source
s.getvalue
Not Working
class Coder():
def start(self):
args={'x':"1",'y':"1",'z':"1"}
source = getSource()
sys.argv = args
with stdoutIO() as s:
exec source
return s.getvalue
print "out:", Coder().start()
And the stdoutIO() is implemented like this:
class Proxy(object):
def __init__(self,stdout,stringio):
self._stdout = stdout
self._stringio = stringio
def __getattr__(self,name):
if name in ('_stdout','_stringio','write'):
object.__getattribute__(self,name)
else:
return getattr(self._stringio,name)
def write(self,data):
self._stdout.write(data)
self._stringio.write(data)
#contextlib.contextmanager
def stdoutIO(stdout=None):
old = sys.stdout
if stdout is None:
stdout = StringIO.StringIO()
sys.stdout = Proxy(sys.stdout,stdout)
yield sys.stdout
sys.stdout = old
Problem
If I execute the execution code outside of the class everything works however when I run it inside a class it breaks with this error. How can I fix it or avoid this problem?
File "<string>", line 29, in <module>
File "<string>", line 27, in main
File "<string>", line 26, in <lambda>
NameError: global name 'add' is not defined
Thanks
When you run exec expression, it executes the code contained in expression in the current scope (see here). Apparently inside a class, the function in your expression are dropping out of scope before main is run. I honestly have no idea why (it seems to me like it should work) but maybe someone can add a complete explanation in a comment.
Anyway, if you specifically provide a scope for the expression to be evaluated in, (which is good practice anyway so that you don't pollute your namespace), it works fine inside the class.
So, replace the line:
exec source
with
exec source in {}
and you should be right!
Here we provide an empty dictionary as a the globals() and locals() dctionaries during the evaluation of your expression. You can keep this dictionary if you want, or let it be garbage collected immediately as I have demonstrated in my code. This is all explained in the exec documentation in the link above.
I want to know if there is a way in python to call the name of an instance variable? For example, if I define a class
>>>class A(object):
... def get_instance_name(self):
... return # The name of the instance variable
>>>obj = A()
>>>obj.get_instance_name()
obj
>>>blah = A()
>>>blah.get_instance_name()
blah
Raise an exception. Not only is it the appropriate way to signal an error, it's also more useful for debugging. The traceback includes the line which did the method call but also additional lines, line numbers, function names, etc. which are more useful for debugging than just a variable name. Example:
class A:
def do(self, x):
if x < 0:
raise ValueError("Negative x")
def wrong(a, x):
a.do(-x)
wrong(A(), 1)
This gives a traceback similar to this, if the exception isn't caught:
Traceback (most recent call last):
File "...", line 1, in <module>
wrong(A(), 1)
File "...", line 7, in wrong
a.do(-x)
File "...", line 4, in do
raise ValueError("Negative x")
ValueError: Negative x
You can also use the traceback module to get this information programmatically, even without an exception (print_stack and friends).
globals() return a dictionary that represents the namespace of the module (the namespace is not this dictionary, this latter only represents it)
class A(object):
def get_instance_name(self):
for name,ob in globals().iteritems():
if ob is self:
return name
obj = A()
print obj.get_instance_name()
blah = A()
print blah.get_instance_name()
tu = (obj,blah)
print [x.get_instance_name() for x in tu]
result
obj
blah
['obj', 'blah']
.
EDIT
Taking account of the remarks, I wrote this new code:
class A(object):
def rondo(self,nameinst,namespace,li,s,seen):
for namea,a in namespace.iteritems():
if a is self:
li.append(nameinst+s+namea)
if namea=='__builtins__':
#this condition prevents the execution to go
# in the following section elif, so that self
# isn't searched among the cascading attributes
# of the builtin objects and the attributes.
# This is to avoid to explore all the big tree
# of builtin objects and their cascading attributes.
# It supposes that every builtin object has not
# received the instance, of which the names are
# searched, as a new attribute. This makes sense.
for bn,b in __builtins__.__dict__.iteritems():
if b is self:
li.append(nameinst+'-'+b)
elif hasattr(a,'__dict__') \
and not any(n+s+namea in seen for n in seen)\
and not any(n+s+namea in li for n in li):
seen.append(nameinst+s+namea)
self.rondo(nameinst+s+namea,a.__dict__,li,'.')
else:
seen.append(nameinst+s+namea)
def get_instance_name(self):
li = []
seen = []
self.rondo('',globals(),li,'')
return li if li else None
With the following
bumbum = A()
blah = A()
print "bumbum's names:\n",bumbum.get_instance_name()
print "\nmap(lambda y:y.get_instance_name(), (bumbum,blah) :\n",map(lambda y:y.get_instance_name(), (bumbum,blah))
print "\n[y.get_instance_name() for y in (bumbum,blah)] :\n",[y.get_instance_name() for y in (bumbum,blah)]
the result is
bumbum's names:
['bumbum']
map(lambda y:y.get_instance_name(), (bumbum,blah) :
[['bumbum'], ['blah']]
[y.get_instance_name() for y in (bumbum,blah)] :
[['bumbum', 'y'], ['blah', 'y']]
The second list comprehension shows that the function get_instance_name() must be used with care. In the list comp, identifier y is assigned in turn to every element of (bumbum,blah) then the finction finds it out as a name of the instance !
.
Now, a more complex situation:
ahah = A() # ahah : first name for this instance
class B(object):
pass
bobo = B()
bobo.x = ahah # bobo.x : second name for ahah
jupiter = bobo.x # jupiter : third name for ahah
class C(object):
def __init__(self):
self.azerty = jupiter # fourth name for ahah
ccc = C()
kkk = ccc.azerty # kkk : fifth name for ahah
bobo.x.inxnum = 1005
bobo.x.inxwhat = kkk # bobo.x.inxwhat : fifth name for ahah
# Since bobo.x is instance ahah, this instruction also
# creates attribute inxwhat in ahah instance's __dict__ .
# Consequently, instance ahah having already 5 names,
# this instruction adds 5 additional names, each one
# ending with .inxwhat
# By the way, this kkk being ahah itself, it results that ahah
# is the value of its own attribute inxwhat.
print ahah.get_instance_name()
result
['bobo.x', 'bobo.x.inxwhat',
'ahah', 'ahah.inxwhat',
'jupiter', 'jupiter.inxwhat',
'kkk', 'kkk.inxwhat',
'ccc.azerty', 'ccc.azerty.inxwhat']
I concur to judge this solution a little heavy and that if a coder thinks he needs such a heavy function, it is probably because the algorithm isn't optimal. But I find interesting to see that it's possible to do this in Python though it doesn't seem evident.
I say heavy, not hacky, I don't find it's hacky, by the way.
No, you can't. Objects can have any number of names, so the question doesn't even make sense. Consider:
a1 = a2 = a3 = A()
What is the name of the instance of A()?
The code is from the guide of pyquery
from pyquery import PyQuery
d = PyQuery('<p class="hello">Hi</p><p>Bye</p>')
d('p').filter(lambda i: PyQuery(this).text() == 'Hi')
My question is this in the 3rd line is an unbound variable and is never defined in current environment, but the above code still works.
How can it work? Why it doesn't complain NameError: name 'this' is not defined?
It seems that something happens at https://bitbucket.org/olauzanne/pyquery/src/c148e4445f49/pyquery/pyquery.py#cl-478 , could anybody explain it?
This is done via Python's func_globals magic, which is
A reference to the dictionary that holds the function’s global variables — the global namespace of the module in which the function was defined.
If you dive into PyQuery code:
def func_globals(f):
return f.__globals__ if PY3k else f.func_globals
def filter(self, selector):
if not hasattr(selector, '__call__'):
return self._filter_only(selector, self)
else:
elements = []
try:
for i, this in enumerate(self):
# The magic happens here
func_globals(selector)['this'] = this
if callback(selector, i):
elements.append(this)
finally:
f_globals = func_globals(selector)
if 'this' in f_globals:
del f_globals['this']
return self.__class__(elements, **dict(parent=self))
Others have correctly point out how this is defined inside that lambda you are talking about.
To elaborate a bit more, try out the following code:
>>> def f():
... print f_global
...
>>> f()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in f
NameError: global name 'f_global' is not defined
>>> f.__globals__['f_global'] = "whoa!!" #Modify f()'s globals.
>>> f()
whoa!!
This is exactly what is happening there. On line 496, you would see the following code:
for i, this in enumerate(self): #this is the current object/node.
func_globals(selector)['this'] = this #func_globals returns selector.__globals__
This doesn't throw a NameError because the variable might exist at the time the actual function is called.
>>> f = lambda i: some_non_named_var
>>> f(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <lambda>
NameError: global name 'some_non_named_var' is not defined
The above does not error until you call the function that you've stashed away. In the example code you showed, they are manually setting a variable called this in the func_globals before calling the lambda selector function.