How to use the values assigned to variables during string formatting? - python

So this works:
>>> x = 1
>>> y = 2
>>> "a={a}, b={b}, a+b={c}".format( a=x, b=y, c=x+y )
'a=1, b=2, a+b=3'
But this doesn't:
>>> "a={a}, b={b}, a+b={c}".format( a=x, b=y, c=a+b )
NameError: name 'a' is not defined
Is there any way to make the second one work? (Say for example that x and y are function calls and I don't want to recompute them during string formatting)

The most pythonic (readable, in this case) solution for this is not to use a lambda function, but to cache a and b before the format() call:
a = function_x()
b = function_y()
"a={a}, b={b}, a+b={c}".format(a=a, b=b, c=a+b)
You'll be thankful when looking at the code 6 months from now.

You can do it with lambda:
def x():
return 1
def y():
return 2
>>> "a={a},b={b}, a+b={c}".format(**(lambda a=x(),b=y():{'a':a,'b':b,'c':a+b})())
'a=1,b=2, a+b=3'
this lambda expression is equal to calling predefined function:
def twosumm(a, b):
return {'a':a, 'b':b, 'c': a+b}
>>> "a={a},b={b}, a+b={c}".format(**twosumm(x(), y()))
'a=1,b=2, a+b=3'
Im also think that it is better to use simple and readable solution and just call x() and y() to get results before formatiing:
>>> a, b = x(), y()
>>> "a={a},b={b}, a+b={c}".format(a=a, b=b, c=a+b)
'a=1,b=2, a+b=3'

x = 1
y = 2
def f(x,y):
return (x,y,x+y)
print "a={}, b={}, a+b={}".format( *f(x,y) )
# or
print "a={0[0]}, b={0[1]}, a+b={0[2]}".format( f(x,y) )
.
EDIT
I think your question is wrongly written and that induces blurry understanding of it, and then wrong answers.
x and y are not function calls. As they appear, they are just identifiers
If you evoke function calls, I think it is because, in fact, you wish to obtain the result of something like that:
"a={a}, b={b}, a+b={c}".format( a=f(), b=g(), c=f()+g() )
but without having to write c=f()+g() because it implies that f() and g() are each executed two times.
Firstly, it will forever be impossible in Python to write something like .format( a=x, b=y, c=a+b ) or .format( a=f(), b=g(), c=a+b ) where a and b in c=a+b will refer to the same objects as a and b in a=x and b=y.
Because any identifier at the left side of = is in the local namespace of format() while any identifier at the right side of = is in the namespace outside of the function format().
By the way, that's why the identifiers at the left are called parameters and the identifiers at the right are the identifiers of objects passed as arguments.
Secondly, if you want to avoid writing f() two times (one time as an alone argument and one time in the expression f()+g()), and the same for g(), that means you want to write each only one time, as alone argument.
So , if I understand you well, you essentially wish to write something like that:
"a={a}, b={b}, a+b={}".format( a=f(), b=g() )
With current method str.format , this expression with three replacement fields { } is evidently not correct.
No matter, let's redefine the method format ! And then it's possible to pass only two arguments to format().
def fx(): return 101
def fy(): return 45
class Pat(str):
def __init__(self,s):
self = s
def format(self,x,y):
return str.format(self,x,y,x+y)
p = Pat("a={}, b={}, a+b={}")
print 'p==',p
print p.format(fx(),fy())
result
p : a={}, b={}, a+b={}
a=101, b=45, a+b=146
We can even do more complex things:
from sys import exit
import re
def fx(): return 333
def fy(): return 6
class Pat(str):
def __init__(self,s):
for x in re.findall('(?<=\{)[^}]+(?=\})',s):
if x not in ('A','M'):
mess = " The replacement field {%s] isn't recognised" % x
exit(mess)
self.orig = s
self.mod = re.sub('\{[^}]*\}','{}',s)
def modif(self,R):
it = iter(R)
return tuple(sum(R) if x=='{A}'
else reduce(lambda a,b: a*b, R) if x=='{M}'
else next(it)
for x in re.findall('(\{[^}]*\})',self))
def format(self,*args):
return ''.join(self.mod.format(*self.modif(args)))
print Pat("a={}, b={}, a+b={A}").format(fx(),fy())
print '******************************************'
print Pat("a={}, b={}, c={}, a+b+c={A}").format(fx(),fy(),5000)
print '******************************************'
print Pat("a={}, b={}, a*b={M}").format(fx(),fy())
print '******************************************'
print Pat("a={}, b={}, axb={X}").format(fx(),fy())
result
a=333, b=6, a+b=339
******************************************
a=333, b=6, c=5000, a+b+c=5339
******************************************
a=333, b=6, a*b=1998
******************************************
Traceback (most recent call last):
File "I:\potoh\ProvPy\Copie de nb.py", line 70, in <module>
print Pat("a={}, b={}, axb={X}").format(fx(),fy())
File "I:\potoh\ProvPy\Copie de nb.py", line 51, in __init__
exit(mess)
SystemExit: The replacement field {X] isn't recognised

Related

how a function in python is getting called by just typing the name of function and not using brackets

First of all to find "lcm" of two numbers I made a function lcm(a, b). Then I thought of finding "hcf" too so I made a decorator decor and defined a function hcf(a, b) in it. And then I returned this function by just typing the name of the function and I didn't put brackets with it but it is still working. I cant understand why this function is working even though I didn't used brackets.
def decor(lcm_arg): # just to practice decorators
def hcf(a, b):
if a > b:
a, b = b, a
while True:
if b % a == 0:
print("hcf is", a)
break
else:
a, b = b % a, a
return lcm_arg(a, b)
return hcf # how hcf function is working without using brackets
#decor
def lcm(a, b):
if a > b:
a, b = b, a
for x in range(b, a*b+1, b):
if x % a == 0:
print("lcm is", x)
break
lcm(2, 4)
Output:
hcf is 2
lcm is 4
I don't think you understand decorators. Let's make a minimal example.
def my_decorator(some_function):
def new_function(*args, **kwargs):
'announces the result of some_function, returns None'
result = some_function(*args, **kwargs)
print('{} produced {}'.format(some_function.__name__, result))
return new_function # NO FUNCTION CALL HERE!
#my_decorator
def my_function(a, b):
return a + b
my_function(1, 2) # will print "my_function produced 3"
We have a simple function my_function which returns the sum of its two arguments and a decorator which will just print out the result of whatever function it decorates.
Note that
#my_decorator
def my_function(a, b):
return a + b
is equivalent to
def my_function(a, b):
return a + b
my_function = my_decorator(my_function)
Since my_decorator accepts a function as an argument (here we are giving it my_function) and returns a new function new_function (without calling it!), we effectively override my_function because we reassign the name to whatever my_decorator returns.
In action:
>>> my_function(1, 2)
my_function produced 3
Note that at every point in the example when a function is called, it happens with the parentheses-syntax. Here are all the function calls that happen in the first block of code I posted, in order:
my_decorator(my_function) is called and the return value is reassigned to the name my_function. This either happens through the # syntax or more explicitly in the equivalent code snippet.
my_function(1, 2) is called. At this point, my_function is the new_function that got returned by the decorator. Brain-parse it as new_function(1, 2).
Inside the body of new_function, the argument we gave to my_decorator is called (result = some_function(*args, **kwargs)) which happens to be the value of my_function before the reassignment that happened in step 1.
print is called.
If you want to understand how new_function is holding on to some_function despite my_decorator already having returned from its call, I suggest looking into the topics free variables and closures.
return hcf does not call the function because there are no parentheses, as you noticed. The decor function is used as a decorator which reassigns the name lcm to refer to the returned function. What I mean by this is that
#decor
def lcm(a, b):
// ...
is equivalent to
def lcm(a, b):
// ...
lcm = decor(lcm)
After this executes, lcm refers to the function hcf. So calling lcm(2, 4) now executes the code in hcf. I think the key here is to understand that at the line lcm(2, 4), lcm and hcf are two names which refer to the same function.

How to figure which returned values a function's call actually uses?

Given a function a, b = f(x), is there any (pythonic) way to determine which return arguments are actually used? As a pseudo-example, consider
def f(x):
c = common_helper_function(x)
a = a_complex_function(x,c)
b = another_complex_function(x,c)
return a, b
where each function call takes a while. If f is called e.g. as _, b = f(x), is there any way to detect the irrelevance of a inside f so a_complex_function(x,c) doesn't need to be called? Sure enough I could just write another function b(x) which omits that call, but is there another way to achieve this, similar to e.g. MATLAB's nargout mechanism?
Well I think if python would be lazy language, it could be possible, but your code should be changed like
def f(x):
c = common_helper_function(x)
return a_complex_function(x,c), another_complex_function(x,c)
In python, that it's not true
def test1():
print ' simple function'
return 1
print 'Calling simple function:'
_ = (lambda : test1())()
print 'Calling simple function again:'
_ = (lambda : test1())()
output:
Calling simple function:
simple function # evaluated once
Calling simple function again:
simple function # evaluated twice
To improve performance, I could suggest you to see two concepts:
Memoization - you can keep results of your functions call in the dictionary and not recalculate it once calculated it.
For memoization there's lru_cache decorator in functools module of python 3 (forpython 2.7 you can download functools32).
Here's an example
from functools32 import lru_cache
#lru_cache(maxsize=10)
def test2():
print ' cashed function'
return 1
print 'Calling cashed function:'
_ = (lambda : test2())()
print 'Calling cashed function again:'
_ = (lambda : test2())()
output:
Calling cashed function:
cashed function # evaluated once
Calling cashed function again:
# not evaluated twice
Lazy evaluation. Each result of the function evaluated once when trying to get result of the function and then stored. So in your case it's not evaluated until using variable where you stored function call result. For python 2.7 you can use lazy.py by Alberto Bertogli:
import lazy
#lazy.lazy
def test3():
print ' lazy function'
return 1
print 'Calling lazy function:'
b = (lambda : test3())()
print 'Calling cashed function again:'
b = (lambda : test3())()
print 'Trying to get results:'
print b
output:
Calling lazy function:
Calling cashed function again:
Trying to get results:
lazy function # evaluated
1

Creating a new function as return in python function?

I was wondering if it is possible in python to do the following:
def func1(a,b):
return func2(c,d)
What I mean is that suppose I do something with a,b which leads to some coefficients that can define a new function, I want to create this function if the operations with a,b is indeed possible and be able to access this outside of func1.
An example would be a simple fourier series, F(x), of a given function f:
def fourier_series(f,N):
...... math here......
return F(x)
What I mean by this is I want to creat and store this new function for later use, maybe I want to derivate it, or integrate or plot or whatever I want to do, I do not want to send the point(s) x for evaluation in fourier_series (or func1(..)), I simply say that fourier_series creates a new function that takes a variable x, this function can be called later outside like y = F(3)... if I made myself clear enough?
You should be able to do this by defining a new function inline:
def fourier_series(f, N):
def F(x):
...
return F
You are not limited to the arguments you pass in to fourier_series:
def f(a):
def F(b):
return b + 5
return F
>>> fun = f(10)
>>> fun(3)
8
You could use a lambda (although I like the other solutions a bit more, I think :) ):
>>> def func2(c, d):
... return c, d
...
>>> def func1(a, b):
... c = a + 1
... d = b + 2
... return lambda: func2(c,d)
...
>>> result = func1(1, 2)
>>> print result
<function <lambda> at 0x7f3b80a3d848>
>>> print result()
(2, 4)
>>>
While I cannot give you an answer specific to what you plan to do. (Looks like math out of my league.)
I can tell you that Python does support first-class functions.
Python may return functions from functions, store functions in collections such as lists and generally treat them as you would any variable.
Cool things such as defining functions in other functions and returning functions are all possible.
>>> def func():
... def func2(x,y):
... return x*y
... return func2
>>> x = func()
>>> x(1,2)
2
Functions can be assigned to variables and stored in lists, they can be used as arguments for other functions and are as flexible as any other object.
If you define a function inside your outer function, you can use the parameters passed to the outer function in the definition of the inner function and return that inner function as the result of the outer function.
def outer_function(*args, **kwargs):
def some_function_based_on_args_and_kwargs(new_func_param, new_func_other_param):
# do stuff here
pass
return some_function_based_on_args_and_kwargs
I think what you want to do is:
def fourier_series(f,N):
#...... math here......
def F(x):
#... more math here ...
import math #blahblah, pseudo code
return math.pi #whatever you want to return from F
if f+N == 2: #pseudo, replace with condition where f,N turn out to be useful
return F
else:
return None
Outside, you can call this like:
F = fourier_series(a,b)
if F:
ans = F(x)
else:
print 'Fourier is not possible :('
The important thing from Python's point of view are:
Yes, you can write a function inside a function
Yes, you can return a function from a function. Just make sure to return it using return F (which returns the function object) as compared to return F(x) which calls the function and returns the value
I was scraping through some documentation and found this.
This is a Snippet Like your code:
def constant(a,b):
def pair(f):
return f(a,b)
return pair
a = constant(1,2) #If You Print variable-> a then it will display "<function constant.
#<locals>.pair at 0x02EC94B0>"
pair(lambda a, b: a) #This will return variable a.
Now, constant() function takes in both a and b and return a function called "Anonymous Function" which itself takes in f, and calls f with a and b.
This is called "closures". Closures is basically an Instance of a Function.
You can define functions inside functions and return these (I think these are technically closures):
def make_f(a, b):
def x(a, b):
return a+b
return x(a, b)

Can a decorator be working with a lambda expression at runtime? [duplicate]

This question already has answers here:
How to apply decorators to lambdas?
(3 answers)
Closed 6 years ago.
def attrs(**kwds):
def decorate(f):
for k in kwds:
setattr(f, k, kwds[k])
return f
return decorate
#attrs(argument_types=(int, int,), returns=int)
def add(a, b):
return a + b
Here I need the add() can be with the ability to show its acceptable parameter type.
but can I do something like this in runtime?
ladd=[]
for x in range(0,10):
#attrs(argument_types=int, returns=int,default_parameter1 = x)
exp = lambda : add(a,x)
ladd.append(exp)
or
ladd=[]
for x in range(0,10):
#attrs(argument_types=int, returns=int,default_parameter1 = x)
addx = functools.partial(add, 2)
ladd.append(addx)
I need those function can be generated runtime with the "decoratored" parameter bind either
Well, here is the error information, I think above code can not work, but I never tried to paste it to python to test it...
>>> ladd=[]
>>> for x in range(0,10):
... #attrs(argument_types=int, returns=int,default_parameter1 = x)
... exp = lambda : add(a,x)
File "<stdin>", line 3
exp = lambda : add(a,x)
^
SyntaxError: invalid syntax
>>> ladd.append(exp)
File "<stdin>", line 1
ladd.append(exp)
^
IndentationError: unexpected indent
>>>
Decorator syntax is merely syntactic sugar, albeit one that directs people's thoughts into interesting directions.
#expr
def f(...):
...
is identical to
def f(...):
...
f = expr(f)
So you can just use attrs(argument_types=..., ...)(lambda: ...).
The # syntax is just syntactic sugar for calling the decorator with the next function as it's argument. This means that
#deco
def func(): pass
is the same as
def func(): pass
func = deco(func)
So what you want is simply:
ladd=[]
for x in range(0,10):
deco = attrs(argument_types=int, returns=int,default_parameter1 = x)
addx = functools.partial(add, 2)
# append the "decorated" function
ladd.append(deco(addx))

What does asterisk * mean in Python? [duplicate]

This question already has answers here:
What does ** (double star/asterisk) and * (star/asterisk) do for parameters?
(25 answers)
Closed 9 years ago.
Does * have a special meaning in Python as it does in C? I saw a function like this in the Python Cookbook:
def get(self, *a, **kw)
Would you please explain it to me or point out where I can find an answer (Google interprets the * as wild card character and thus I cannot find a satisfactory answer).
See Function Definitions in the Language Reference.
If the form *identifier is
present, it is initialized to a tuple
receiving any excess positional
parameters, defaulting to the empty
tuple. If the form **identifier is
present, it is initialized to a new
dictionary receiving any excess
keyword arguments, defaulting to a new
empty dictionary.
Also, see Function Calls.
Assuming that one knows what positional and keyword arguments are, here are some examples:
Example 1:
# Excess keyword argument (python 2) example:
def foo(a, b, c, **args):
print "a = %s" % (a,)
print "b = %s" % (b,)
print "c = %s" % (c,)
print args
foo(a="testa", d="excess", c="testc", b="testb", k="another_excess")
As you can see in the above example, we only have parameters a, b, c in the signature of the foo function. Since d and k are not present, they are put into the args dictionary. The output of the program is:
a = testa
b = testb
c = testc
{'k': 'another_excess', 'd': 'excess'}
Example 2:
# Excess positional argument (python 2) example:
def foo(a, b, c, *args):
print "a = %s" % (a,)
print "b = %s" % (b,)
print "c = %s" % (c,)
print args
foo("testa", "testb", "testc", "excess", "another_excess")
Here, since we're testing positional arguments, the excess ones have to be on the end, and *args packs them into a tuple, so the output of this program is:
a = testa
b = testb
c = testc
('excess', 'another_excess')
You can also unpack a dictionary or a tuple into arguments of a function:
def foo(a,b,c,**args):
print "a=%s" % (a,)
print "b=%s" % (b,)
print "c=%s" % (c,)
print "args=%s" % (args,)
argdict = dict(a="testa", b="testb", c="testc", excessarg="string")
foo(**argdict)
Prints:
a=testa
b=testb
c=testc
args={'excessarg': 'string'}
And
def foo(a,b,c,*args):
print "a=%s" % (a,)
print "b=%s" % (b,)
print "c=%s" % (c,)
print "args=%s" % (args,)
argtuple = ("testa","testb","testc","excess")
foo(*argtuple)
Prints:
a=testa
b=testb
c=testc
args=('excess',)
I only have one thing to add that wasn't clear from the other answers (for completeness's sake).
You may also use the stars when calling the function. For example, say you have code like this:
>>> def foo(*args):
... print(args)
...
>>> l = [1,2,3,4,5]
You can pass the list l into foo like so...
>>> foo(*l)
(1, 2, 3, 4, 5)
You can do the same for dictionaries...
>>> def foo(**argd):
... print(argd)
...
>>> d = {'a' : 'b', 'c' : 'd'}
>>> foo(**d)
{'a': 'b', 'c': 'd'}
All of the above answers were perfectly clear and complete, but just for the record I'd like to confirm that the meaning of * and ** in python has absolutely no similarity with the meaning of similar-looking operators in C.
They are called the argument-unpacking and keyword-argument-unpacking operators.
A single star means that the variable 'a' will be a tuple of extra parameters that were supplied to the function. The double star means the variable 'kw' will be a variable-size dictionary of extra parameters that were supplied with keywords.
Although the actual behavior is spec'd out, it still sometimes can be very non-intuitive. Writing some sample functions and calling them with various parameter styles may help you understand what is allowed and what the results are.
def f0(a)
def f1(*a)
def f2(**a)
def f3(*a, **b)
etc...
I find * useful when writing a function that takes another callback function as a parameter:
def some_function(parm1, parm2, callback, *callback_args):
a = 1
b = 2
...
callback(a, b, *callback_args)
...
That way, callers can pass in arbitrary extra parameters that will be passed through to their callback function. The nice thing is that the callback function can use normal function parameters. That is, it doesn't need to use the * syntax at all. Here's an example:
def my_callback_function(a, b, x, y, z):
...
x = 5
y = 6
z = 7
some_function('parm1', 'parm2', my_callback_function, x, y, z)
Of course, closures provide another way of doing the same thing without requiring you to pass x, y, and z through some_function() and into my_callback_function().

Categories