The goal is to try and access any function's sub functions. I've looked around and I'm not too sure there is a way to do it. When I've tried using
functions = [name for name, obj in inspect.getmembers(sys.modules[__name__], inspect.isfunction)]
which returns the functions in some module (in the above __name__==__main__). When I have used that method, it doesn't return any sub functions. However I'd like to access sub functions that look something like
def f(x):
def y(x):
return x += 3
def z(x):
return x**2 - 1
x += y(x)
x += z(x)
return x
So it seems to me like there should be some way to access them with a magic method of f or some attribute of f. I have a hard time believing that those sub functions aren't stored as some attribute of f, but I have no idea.
In the end, what I need to do is to iterate through the sub functions of some function, so I thought the solution would look something like
for subfunc in f.__method_that_returns_subfuncs__():
if 'my_string' == subfunc.__name__:
out = subfunc(args)
I just need to be able to compare a string to a subfunction name then call that subfunction.
Thanks
There's no implicit list of functions to iterate over. You need to define it yourself. Simply functions can be assigned directly to a list by defining them with lambda expressions; more complex functions will need to be defined first, then added. Examples of each:
def f(x):
funcs = []
def y(x):
return x += 3
f.append(y)
f.append(lambda x: x**2 - 1)
for func in funcs:
x = func(x)
return x
If you care about the name, you can access it via the function object's __name__ attribute.
for func in funcs:
if func.__name__ == "some_func":
x = func(x)
Related
Over here, the main function is g(x) and the helper function is h(). I noticed I can get the output for g(3), simply by binding x=3 and then doing any of the three
print(g(x))
g(x)
z=g(x)
But on the other hand, I noticed h() is outputted only when I type "print(h())". Are my observations correct or did I make a mistake? And also what is the logic behind this weird discrimination?
I like to think of it this way. Usually, if you had a line like "5" or "x=5", python doesn't give an output of 5. But functions have been given a special feature where they are invoked in any of the 3 ways. It's only that this special feature is being 'withdrawn' in the case of helper functions
The code you have written is equivalent to this:
def g(x):
def h():
any_name_you_want = 'abc'
return any_name_you_want
x += 1
print("in g(x)", x)
print(h())
return x
You cannot assign to a non-local variable inside a function. When Python creates the namespace for h, x is local to h because the assignment requires python to add the namespace for x at runtime.
Hence your code is also equivalent to :
def g(x):
def h():
return 'abc'
x += 1
print("in g(x)", x)
print(h())
return x
To get a sense of what is happening, run the following and then read up on UnboundLocalError:
def g(x):
def h():
x = x
return x
x += 1
print("in g(x)", x)
print(h())
return x
I'm learning Python right now and I am just trying to get to grips with all of the syntax options.
Currently, the only thing that I can't seem to google up is what to do if I for some reason want to define a function which contains multiple other defines.
While I understand what to do if there's only 1 define inside the the larger define (val = f()(3,4) returns 7 if you exclude the second def below), I don't know how to correctly use the function below.
If it's possible, what is the syntax for a def function with an arbitrary amount of defined functions within it?
Code:
def f():
def x(a,b):
return a + b
return x
def y(c,d):
return c + d
return y
val = f()(3,4)(5,6)
print(val)
I expected the above to return either (7,11) or 11. However, it returns 'int object is not callable'
When you write val = f()(3,4)(5,6), you want f to return a function that also returns a function; compare with the simpler multi-line call:
t1 = f()
t2 = t1(3,4)
val = t2(5,6)
The function f defines and returns also has to define and return a function that can be called with 2 arguments. So, as #jonrsharpe said, you need more nesting:
def f():
def x(a, b):
def y(c, d):
return c + d
return y
return x
Now, f() produces the function named x, and f()(3,4) produces the function named y (ignoring its arguments 3 and 4 in the process), and f()(3,4)(5,6) evaluates (ultimately) to 5 + 6.
I'm newbie in Python, but the second time I encouter this problem.
Problem:
In some libraries there are functions with arguments. Sometimes there is argument as function, like this:
def somefun(fun):
x = [1,2,3]
z = fun(x)
return z
And I want to pass there some other function like this:
def func(x,y):
return x*y
which have more than one argument. I want to make one argument static, so somefun except func as argument.
Finally I want to make some kind of cycle where I can change static arg.
Something like this:
for i in xrange(1,9):
somefun(func(i,*))
Please do not offer me to change any functions. They are from library and it's not very comfortable to change them.
Thanks a lot!
You can use lambda statement:
somefun(lambda x: func(i, x))
It sure sounds like you are looking for functools.partial. From the docs:
functools.partial(func, *args, **keywords)
Return a new partial object which when called will behave like func called with the positional arguments args and keyword arguments keywords.
In your example, you could pass partial(func, 10) as the argument to somefun. Or you could create the partial objects and use them in a loop:
for i in xrange(1,9):
somefun(partial(func, i))
My solution with decorator
from functools import wraps
import numpy as np
def p_decorate(f):
#wraps(f)
def wrapped(*args):
z = f(*args)
return z
return wrapped
#p_decorate
def myfunc(a,b):
"""My new function"""
z = np.dot(a,b)
return z
x = [1,2,3]
y = [4,2,0]
r = myfunc(x,y)
print (r)
print (myfunc.__name__)
print (myfunc.__doc__)
You can change myfunc as you wish.You can also insert more function layers.Without the use of this decorator factory,you would lose the name of myfunc and the docstring.
I have the following structure (which might need a rework but to me this feels natural):
def get(baseVar):
if type(baseVar) == GeneratorType:
yield from baseVar
else:
yield baseVar
def multiply(baseVar):
if type(baseVar) == GeneratorType:
for item in baseVar:
yield item*2
else:
yield baseVar*2
funcs = {'get' : get, 'multiply' : multiply}
result = 10
for f in funcs:
result = funcs[f](result)
print(list(result))
Another approach would be (but this isn't dynamic at all) that performance wise works like i want it to, where an iterator object is passed to each functions thus gaining more momentum (theoretically) out of the functions:
for result in multiply(get(10)):
...
How can i nest multiple yield functions in a row and pass the generator object without hard-coding the function names, getattr?
I'm not sure, what you want to do. If you have different functions, that work on single elements, use map:
def get(x):
return x
def multiply(x):
return x*2
print(list(map(multiply,map(get,[10]))
How would you like to get the names of you function? From external source, then your dict is the correct way, from internal, then you can use the functions directly:
funcs = (get, multiply)
result = [10]
for f in funcs:
result = map(funcs,result)
I am new to python. This might be a simple question, but if I have many functions that are dependent on each other how would I access lists from one function to use in another.
So...
def function_1():
list_1=[]
def function_2():
list_2= [2*x for x in list_1]
def function_3():
list_3= [x * y for x, y in zip(list_1, list_2)]
That is not the exact code but that is the idea of my problem. I would just put them all together in one function but I need them to be separate.
The correct way to do this would be to use a class. A class is an object that has internal variables (in your case, the three lists), and methods (functions that can access the internal methods). So, this would be:
class Foo(object):
def __init__(self, data=None):
self.list_1 = data if not data is None else []
def function_2():
self.list_2 = [2 * x for x in self.list_1]
And so on. For calling it:
foo = Foo() # list_1 is empty
foo2 = Foo([1,2,3]) # list_1 is not empty
foo2.function_2()
print foo2.list_2
# prints [2, 4, 6]
Make them arguments and return values:
def function_1():
return []
def function_2(list_1):
return [2*x for x in list_1]
def function_3(list_1, list_2):
return [x * y for x, y in zip(list_1, list_2)]
(this suggests that function_1 isn't much worth having...)
The exact way will depend on exactly how you want things to work, but here is a simple example:
def function_1():
return []
def function_2():
return [2*x for x in function_1()]
def function_3():
return [x * y for x, y in zip(function_1(), function_2())]
The key point is that functions do not generally just "do" things, they return things. If you have a value in one function that you want to use in another function, the first function should return that value. The second function should call the first function, and use its return value.
Functions are basically black boxes -- the outside world doesn't really know what goes on inside or what variables exist there. From the outside, other code only sees what goes in (the function's arguments) and what goes out (its return value).
So if your function computes some value that is to be used elsewhere, it should be returned as the result of the function.
E.g.,
def square(x):
return x * x
Takes a number, computes its square, and returns it.
Then you could do:
print(square(5))
and it will print 25.
So in your case you can return the lists and use them in the other functions, as the other answers showed:
def function_1():
return []
def function_2():
return [2*x for x in function_1()]
def function_3():
return [x * y for x, y in zip(function_1(), function_2())]