I'm trying so check if a variable exists, but inside a function.
I was taught that, to do this, the only thing you needed to do was:
'a' in locals()
Unfortunately, things turned out to be a little bit more difficult than I expected.
I tried to define a function that included this method.
q=[1,2,3]
def f():
print('q' in locals())
When I run this function, it returns:
False
The problem is, as we can see, that q is a variable, so when I run the same command, but outside the function:
'q' in locals()
It returns:
True
Is there a way to solve this?
You may test for the existence of your list q in the globals() dictionary, since it exists in global scope, not the local scope of your function f, i.e.:
def f():
print('q' in globals())
As pointed out in the comments, testing the existence of variables using their string names like this is not ideal and you may instead use a try/except:
def f():
try:
# Do something with q
print(q)
except NameError:
print("Variable not defined")
When you code the following lines
q=[1,2,3]
def f():
print('q' in locals())
f()
Here, variable 'q' is not local to function f() as it is declared outside the function scope.Inside the function, q can be accessed using global.
But, outside the function 'q' is a local variable.
Therefore, when you check inside the function
q=[1,2,3]
def f():
print('q' in locals())
it will return False
But if you declare inside the function and check as follow:-
def f():
q=[1,2,3]
print('q' in locals())
It will return True as q is now local to the function.
Also if you check 'q' inside the function as global it will return True as 'q' is declared outside the function and has global scope.
q=[1,2,3]
def f():
print('q' in globals())
f()
Output
True
you can use
hasattr(obj, "var")
and replace obj with self
class test():
def __init__(self):
self.a = 1
def check(self, var):
return hasattr(self, var)
t = test()
print(t.check("a"))
print(t.check("b"))
output
True
False
Related
code = "def foo(): return 'bar'"
def lol(code):
exec code
return foo
a = lol(code)
print a()
This works normally, but the problem starts when we don't know what the function in the string is called. If I can guarantee that the code will be small, with a single function, how can I return that function?
One solution I thought of was just requiring the function be called 'foo' etc, so I can just return that, but it feels ugly.
Thoughts?
You could do it by explicitly specifying dictionaries exec should use for the global and local execution context. Afterwards the one used for locals should have a single entry for the function object, which can be returned without knowing its name since it should be the only item defined in the dictionary:
from textwrap import dedent
import types
def lol(code):
globals_ = {"__builtins__": None} # no built-ins for safety
locals_ = {}
exec(code, globals_, locals_)
if len(locals_) != 1:
raise ValueError("code didn't define exactly one item")
value = locals_.popitem()[1] # get value of the one item defined
if type(value) != types.FunctionType:
raise ValueError("code didn't define a function")
return value # return function object that was defined
my_code = dedent("""
def foo():
return 'bar'
""")
a = lol(my_code)
print(a())
def A():
def B():
#do something
a = A()
a.B()
Why isn't the above (such simple code) possible in Python? Is there a 'pythonic' (legible, unsurprising, non-hacky) workaround that does not turn A() into a class?
Edit 1: The above was explained to me that B is local to A, thus it only exists as long as A is being evaluated. So if we make it global (and be sure not to have it overriden), then why doesn't this work?
def A():
def B():
#do something
return A()
a = A()
a.B()
It says it's returning a 'NoneType' object.
Because a function definition just creates a name in the local namespace. What you are doing is no different than:
def f():
a = 2
and then asking why you can't access a from outside the function. Names bound inside a function are local to the function.
In addition, your proposed code is strange. when you do a = f(), you are setting a to the return value of the function. Your function returns nothing, so you can't hope to access anything through the return value. It is possible to return the inner function directly:
def f():
def g():
return "blah"
return g
>>> func = f()
>>> func()
'blah'
And this can indeed be useful. But there isn't a generic way to access things inside the function from outside except by modifying global variables (which is usually a bad idea) or returning the values. That's how functions work: they take inputs and return outputs; they don't make their innards available to the outside word.
To call B with the syntax you want, use:
def A():
def B():
print("I'm B")
A.B = B
return A
a = A()
a.B()
A.B()
How can I tell if a class instance method and function are the same?
I have a simple class that uses a decorator:
#decorate_class
class Hello:
#decorate_func
def world(self):
return
And these are my decorators:
# A global variable
global_func = None
def decorate_func(func):
global_func = func
return func
def decorate_class(clazz):
print clazz.__dict__["world"] == global_func
return clazz
The above returns False, possible because type(func) in decorate_func is function, but in decorate_class it is instancemethod. But printing both of them gives me:
<function world at 0x7f490e59ce60>
As in, the same memory address. How do I compare them to know that they are the same function? Is comparing by the memory address safe (and correct)?
Your problem here is actually your use of global_func.
If you change decorate_class to:
def decorate_class(clazz):
print global_func, clazz.__dict__["world"] == global_func
return clazz
You'll see that global_func is None.
To fix this, explicitly declare global_func as global in decorate_func:
def decorate_func(func):
global global_func
global_func = func
return func
And everything will work.
This is (basically) because Python assumes that, if you assign to a variable in a function, that variable is assumed to be local to that function, unless it is explicitly declared to be global.
Here's what I need:
Let's say I have this decorator:
def deco(func):
def decoret(*args, **kwargs):
print(func.__locals__) # I know __locals__ is not valid, but I need something like this
return decoret
#deco
def func():
test1 = 123
test2 = 456
func()
I want to fetch a list of all local variables (as if I was calling locals() inside the function), so I would be able to access a dictionary with test1 and test2 values inside the decorator's decoret function.
I know I can do this by using Python inspect module, but I wasn't able to trace the right frame to get the function.
Also, I'm using Python 3.2 CPython.
There are no locals in a function until it's executed. The only things available to you when it's decorated are what is there when it's defined.
d = 'd'
def a(d=d):
b = 'b'
c = 'c'
print a.__dict__
# {}
print a.b
# AttributeError: 'function' object has no attribute 'b'
print dir(a)
# Doesn't print anything
Actually, I found a way to circumvent and implement this using a trace from sys.
Take a look a this snippet:
def Property(function):
keys = 'fget', 'fset', 'fdel'
func_locals = {'doc':function.__doc__}
def probeFunc(frame, event, arg):
if event == 'return':
locals = frame.f_locals
func_locals.update(dict((k,locals.get(k)) for k in keys))
sys.settrace(None)
return probeFunc
sys.settrace(probeFunc)
function()
return property(**func_locals)
Took this from a snippet of code located at http://code.activestate.com/recipes/410698/
Also, take a look on this stackoverflow topic: Python: static variable decorator
I want to do the following in python:
def func1():
var1 = "something"
def func2():
print var1
What is the correct mode to do this ? I've not found in documentation at all
PS. If possible, it's not my plan to make that 'var1' a global variable.
Thanks.
I assume you don't want to pass the variable as a parameter between the function calls. The normal way to share state between functions would be to define a class. It may be overkill for your particular problem, but it lets you have shared state and keep it under control:
class C:
def func1(self):
self.var1 = "something"
def func2(self):
print self.var1
foo = C()
foo.func1()
foo.func2()
No, it is not possible to do things like that. This is because of something called "scope". You can either create a module-level variable or place it in an OOP construct.
Well your func2() is trying to print a variable in the scope of another function. You can either
Return the value of var1 when calling func1 (eg. def func2(): print func1() }
Call func2 from func1 and pass the value of var1
You could try something like
def func1():
var1 = "something"
return var1
def func2():
print func1()
If you need func1 to do more things than just define var1, then maybe what you need is to define a class and create objects? See http://docs.python.org/tutorial/classes.html
You could try:
filename.py:
def func1():
var1 = "something"
def func2():
var = __ import__('filename').var1
print var