I'm trying to do something like this:
import threading
def func1(a,b):
def func2():
t=threading.Thread(target=func3)
return t
return func2
func2=func1(a,b)
func2()
I have a restriction(the language I'm using is python with some restricted functions) not to use the args parameter for the Thread function instead I want to pass a and b as parameters to func3. How can I do this using closures?
You can use a lambda:
t=threading.Thread(target=lambda: func3(a,b))
The values of a and b will be held in a closure, even after func1 exits.
Instead of a lambda, you can create a named function:
def thread_func():
func3(a,b)
t = threading.Thread(target=thread_func)
In the absence of lambda I might look into functools.partial. If that isn't allowed, you could probably do:
import threading
def func1(a,b):
def func2():
def func4():
return func3(a,b)
return threading.Thread(target=func4)
return func2
func2=func1(a,b)
func2()
Related
For instanse, I have the following code snippet:
def func1(num):
print(num)
def func2(num):
func1(num)
def func3(num):
func2(num)
func1(num)
def begin():
pass
def print_graph():
pass
def main():
begin()
func3(3)
print_graph()
Is there any simple way to print something like that:
func3(1)
func2(1)
func1(1)
func1(1)
I believe, that I have to use globals(), but I don't know, what I do next. It is some sort of study task, therefore I cant use any libraries.
I can go one better than #jme. Here's a version of his decorator that indents and dedents according to your location in the call stack:
import functools
# a factory for decorators
def create_tracer(tab_width):
indentation_level = 0
def decorator(f): # a decorator is a function which takes a function and returns a function
#functools.wraps(f)
def wrapper(*args): # we wish to extend the function that was passed to the decorator, so we define a wrapper function to return
nonlocal indentation_level # python 3 only, sorry
msg = " " * indentation_level + "{}({})".format(f.__name__, ", ".join([str(a) for a in args]))
print(msg)
indentation_level += tab_width # mutate the closure so the next function that is called gets a deeper indentation level
result = f(*args)
indentation_level -= tab_width
return result
return wrapper
return decorator
tracer = create_tracer(4) # create the decorator itself
#tracer
def f1():
x = f2(5)
return f3(x)
#tracer
def f2(x):
return f3(2)*x
#tracer
def f3(x):
return 4*x
f1()
Output:
f1()
f2(5)
f3(2)
f3(40)
The nonlocal statement allows us to mutate the indentation_level in the outer scope. Upon entering a function, we increase the indentation level so that the next print gets indented further. Then upon exiting we decrease it again.
This is called decorator syntax. It's purely 'syntactic sugar'; the transformation into equivalent code without # is very simple.
#d
def f():
pass
is just the same as:
def f():
pass
f = d(f)
As you can see, # simply uses the decorator to process the decorated function in some way, and replaces the original function with the result, just like in #jme's answer. It's like Invasion of the Body Snatchers; we are replacing f with something that looks similar to f but behaves differently.
If you're stuck on Python 2, you can simulate the nonlocal statement by using a class with an instance variable. This might make a bit more sense to you, if you've never used decorators before.
# a class which acts like a decorator
class Tracer(object):
def __init__(self, tab_width):
self.tab_width = tab_width
self.indentation_level = 0
# make the class act like a function (which takes a function and returns a function)
def __call__(self, f):
#functools.wraps(f)
def wrapper(*args):
msg = " " * self.indentation_level + "{}({})".format(f.__name__, ", ".join([str(a) for a in args]))
print msg
self.indentation_level += self.tab_width
result = f(*args)
self.indentation_level -= self.tab_width
return result
return wrapper
tracer = Tracer(4)
#tracer
def f1():
# etc, as above
You mentioned that you're not allowed to change the existing functions. You can retro-fit the decorator by messing around with globals() (though this generally isn't a good idea unless you really need to do it):
for name, val in globals().items(): # use iteritems() in Python 2
if name.contains('f'): # look for the functions we wish to trace
wrapped_func = tracer(val)
globals()[name] = wrapped_func # overwrite the function with our wrapped version
If you don't have access to the source of the module in question, you can achieve something very similar by inspecting the imported module and mutating the items it exports.
The sky's the limit with this approach. You could build this into an industrial-strength code analysis tool by storing the calls in some sort of graph data structure, instead of simply indenting and printing. You could then query your data to answer questions like "which functions in this module are called the most?" or "which functions are the slowest?". In fact, that's a great idea for a library...
If you don't want to use modify code, you can always use sys.settrace. Here is a simple sample:
import sys
import inspect
class Tracer(object):
def __init__(self):
self._indentation_level = 0
#property
def indentation_level(self):
return self._indentation_level
#indentation_level.setter
def indentation_level(self, value):
self._indentation_level = max(0, value)
def __enter__(self):
sys.settrace(self)
def __exit__(self, exc_type, exc_value, traceback):
sys.settrace(None)
def __call__(self, frame, event, args):
frameinfo = inspect.getframeinfo(frame)
filename = frameinfo.filename
# Use `in` instead of comparing because you need to cover for `.pyc` files as well.
if filename in __file__:
return None
if event == 'return':
self.indentation_level -= 1
elif event == 'call':
print "{}{}{}".format(" " * self.indentation_level,
frameinfo.function,
inspect.formatargvalues(*inspect.getargvalues(frame)))
self.indentation_level += 1
else:
return None
return self
Usage:
from tracer import Tracer
def func1(num):
pass
def func2(num):
func1(num)
def func3(num):
func2(num)
func1(num)
def main():
with Tracer():
func3(1)
And results:
func3(num=1)
func2(num=1)
func1(num=1)
func1(num=1)
How about using decorators to print a function's name when it is called? Something like this:
from functools import wraps
def print_on_entry(fn):
#wraps(fn)
def wrapper(*args):
print "{}({})".format(fn.func_name, ", ".join(str(a) for a in args))
fn(*args)
return wrapper
Then you can wrap each of your functions up:
func1 = print_on_entry(func1)
func2 = print_on_entry(func2)
func3 = print_on_entry(func3)
So that:
>>> func3(1)
func3(1)
func2(1)
func1(1)
1
func1(1)
1
Of course there are a lot of assumptions in the above code -- the arguments can be converted to strings, for example -- but you get the picture.
This might seem like a rather weird thing to do, but I was curious if it was possible to implicitly pass a variable down a call chain in Python without passing it as an argument. To better illustrate here is an example:
Here is the "normal" way:
def three(something):
print(something)
def two(something):
# ...
three(something)
def one(something):
# ...
two(something)
And here is what I want to be able to do:
def three():
# something is defined implicitly
print(something)
def two():
# ...
three()
def one(something):
# somehow define something inside a context
# for this activation
two()
For the purpose of this, one, two and three are not in the same class or even the same module.
You don't want to do this.
If you are really convinced that you want to torture yourself, then you could create a separate thread and run the call to one() in that thread. Then just use threading.local for the shared state.
You really don't want to do this.
Here's how you can use thread local storage:
import threading
state = threading.local()
def three():
# something is defined implicitly
print(state.something)
def two():
# ...
three()
def one(something):
# somehow define something inside a context
# for this activation
def inner():
state.something = something
two()
t = threading.Thread(target=inner)
t.start()
t.join()
if __name__=='__main__':
one(42)
one(24)
If you must, you can assign values to the function object itself. Ideally, both three() and two() would perform checks that would raise better exceptions than an AttributeError if 'something' is not set correctly.
def three():
print(three.something)
def two():
three.something = two.something
three()
def one(something):
two.something = something
two()
You could take advantage of lexical closures - define two() and three() within the definition of one().
>>> def one(something):
... def two():
... three()
... def three():
... print something
... two()
...
>>> one(1)
1
You can use __builtins__ to hold your "global variables".
>>> __builtins__.something = "Hello world!"
>>> def foo():
print something
>>> foo()
Hello world!
This can help you avoid passing variables explicitly.
This is a terrible hack. IMHO, you really don't need to do that.
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()
Can I call a function nested inside another function from the global scope in python3.2?
def func1():
def func2():
print("Hello")
return
return
Is ther a way to call func2() from outside func1()?
No, unless you return the function:
def func1():
def func2():
print("Hello")
return func2
innerfunc = func1()
innerfunc()
or even
func1()()
You want to use #larsmans' solution, but theoretically you can cut yourself into the code object of the locally accessible func1 and slice out the code object of func2 and execute that:
#!/usr/bin/env python
def func1():
def func2():
print("Hello")
# => co_consts is a tuple containing the literals used by the bytecode
print(func1.__code__.co_consts)
# => (None, <code object func2 at 0x100430c60, file "/tmp/8457669.py", line 4>)
exec(func1.__code__.co_consts[1])
# => prints 'Hello'
But again, this is nothing for production code.
Note: For a Python 2 version replace __code__ with func_code (and import the print_function from the __future__).
Some further reading:
http://web.archive.org/web/20081122090534/http://pyref.infogami.com/type-code
http://docs.python.org/reference/simple_stmts.html#exec
http://lucumr.pocoo.org/2011/2/1/exec-in-python/
This is based on eyquem's solution.
def func1():
global func2 # put it in global scope
def func2():
print("Hello")
Now you can invoke func2 directly.
But func1() would have to be called before you can call func2() otherwise it will not have been defined yet.
def func1():
def func2():
global fudu
fudu = func2
print("Hello")
func2()
func1()
fudu()
print 'fudu' in dir()
print 'func2' in dir()
result
Hello
Hello
True
False
Also:
def func1():
global func2
def func2():
print("Hello")
func2()
func1()
print 'func2' in dir()
func2()
result
Hello
True
Hello
What's the interest?
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