I'd like to use Python f-string for its syntactical simplicity, compared to string.Template() or other approach. However, in my application, the string is loaded from file, and the values of the variable can only be provided later.
If there a way to invoke fstring functionality separate from the string definition? Hopefully code below will better explain what I hope to achieve.
a = 5
s1 = f'a is {a}' # prints 'a is 5'
a = 5
s2 = 'a is {a}'
func(s2) # what should be func equivalent to fstring
By using eval() and passing either locals() or any arbitrary dict as the second positional locals argument, you can calculate an f-string dynamically on the fly with any combination of inputs.
def fstr(fstring_text, locals, globals=None):
"""
Dynamically evaluate the provided fstring_text
"""
locals = locals or {}
globals = globals or {}
ret_val = eval(f'f"{fstring_text}"', locals, globals)
return ret_val
Sample usage:
format_str = "{i}*{i}={i*i}"
i = 2
fstr(format_str, locals()) # "2*2=4"
i = 4
fstr(format_str, locals()) # "4*4=16"
fstr(format_str, {"i": 12}) # "10*10=100"
Use str.format().
Preferably, be explicit about passing arguments to it. But as a stopgap measure, you can use locals() to pass a dict of local (function-defined) variables to the formatting function:
foo = 'bar'
print('Foo is actually {foo}'.format(**locals()))
You can of course copy globals() to a local dict, and merge locals() to it, and use it to more closely emulate the f-string approach.
you can format it this way. pass in a dictionary of possible values for a and map it to your string.
dictionary = {
'a':[5,10,15]
}
def func(d):
for i in range(3):
print('a is {{a[{0}]}}'.format(i).format_map(d))
func(dictionary)
print:
a is 5
a is 10
a is 15
Here's what you were looking for:
pip install fstring
from fstring import fstring
x = 1
y = 2.0
plus_result = "3.0"
print fstring("{x}+{y}={plus_result}")
# Prints: 1+2.0=3.0
Here you go:
In [58]: from functools import partial
In [59]: def func(var_name, a):
...: return var_name + f' is {a}'
...:
In [60]: f = partial(func, 'a')
In [61]: f(5)
Out[61]: 'a is 5'
I am surprised why nobody answered with lambda:
foobar = lambda x: f"Foobar is {x}"
foobar(5)
> "Foobar is 5"
Related
This question already has answers here:
Python using getattr to call function with variable parameters
(3 answers)
Closed 1 year ago.
I have create a sample function where I want to pass all the keys in dict third_party to eval statement.
Using itemgetter is not possible as dictionary key are variable.
def sample(third_party):
'''
:param third_party: is a dictionary number of keys and exact keys name varies
'''
#Types can be of multiple type, using if/else not possible
#type will always a key
tp_type = third_party['type']
if tp_type[-1] == 's':
type_execution = tp_type + '_s'
else:
type_execution = tp_type + 's'
#How to destructure dictionary into eval command as function arguments
eval_statement = "inital.constant.command" + type_execution + ".create("**third_party")"
eval(eval_statement)
Short answer: there's no syntactical sugar for what you're trying to do, as far as I'm aware.
Here's one way you can achieve your desired result though:
args = ", ".join(f"{k}={v}" for k, v in third_party.items())
eval_statement = f"inital.constant.command{type_execution}.create({args})"
That said, it's not really clear why you need to use eval(). Note that using eval() is generally considered bad practice so I strongly recommend reconsidering your approach to this problem.
For instance, if third_party["type"] returns the actual name of an attribute of the initial.constant object, whatever it is, you could simply do
exec_type = third_party["type"]
func = getattr(initial.constant, f"command{exec_type}")
func.create(**third_party)
Here's a simple demo:
In [1]: class A:
...: def f(self, x):
...: return x**2
...:
...: def g(self, x):
...: return x**3
...:
In [2]: a = A()
In [3]: getattr(a, "f")
Out[3]: <bound method A.f of <__main__.A object at 0x0000019A291D3790>>
In [4]: f = getattr(a, "f")
In [5]: f(3)
Out[5]: 9
But without knowing what your data look like, and what the objects you're working with look like I can't say for sure.
I was using a lambda statement to perform math, and happened to repeatedly use one certain value. Therefore I was wondering if it was possible to assign and use a variable within a lambda statement.
I have tried things like:
a = lambda n:(b=3+2*n) #[my math here]
However this just raises errors, and I was wondering if there was a way to do this.
Nope, you can't. Only expressions allowed in lambda:
lambda_expr ::= "lambda" [parameter_list]: expression
lambda_expr_nocond ::= "lambda" [parameter_list]: expression_nocond
You could, however, define a second lambda inside the lambda and immediately call it with the parameter you want. (Whether that's really better might be another question.)
>>> a = lambda n: ((3+2*n), n*(3+2*n)) # for reference, with repetition
>>> a(42)
(87, 3654)
>>> a2 = lambda n: (lambda b: (b, n*b))(3+2*n) # lambda inside lambda
>>> a2(42)
(87, 3654)
>>> a3 = lambda n: (lambda b=3+2*n: (b, n*b))() # using default parameter
>>> a3(42)
(87, 3654)
Of course, both the outer and the inner lambda can have more than one parameter, i.e. you can define multiple "variables" at once. The benefit of this approach over, e.g., defining a second lambda outside of the first is, that you can still also use the original parameters (not possible if you invoked a with b pre-calculated) and you have to do the calculation for b only once (other than repeatedly invoking a function for the calculation of b within a).
Also, inspired by the top answer to the linked question, you could also define one or more variables as part of a list comprehension or generator within the lambda, and then get the next (first and only) result from that generator or list:
>>> a4 = lambda n: next((b, n*b) for b in [3+2*n])
>>> a4(42)
(87, 3654)
However, I think the intent behind the lambda-in-a-lambda is a bit clearer. Finally, keep in mind that instead of a one-line lambda, you could also just use a much clearer three-line def statement...
Also, starting with Python 3.8, there will be assignment expressions, which should make it possible to write something like this. (Tested with Python 3.8.10.)
>>> a5 = lambda n: ((b := 3+2*n), n*b)
You can just pass your lambda an argument which passes it along to another argument if you wish:
>>> b = lambda x: 3 + 2*x
>>> a = lambda y: y * b(y)
>>> a(1)
5
>>> a(2)
14
You can create 2 different lambda functions and pass one to the other. For example,
b = lambda x: 3+2*x
a = lambda y: [my math here using variable b(y)]
I've cooked up this recipe for python 3.8+ using PEP572 Assignment Expressions to assign arbitrary variables and execute arbitrary expressions.
# python 3.8b1
lambda a: (
(bool(b:=a**2) or 1)
and (bool(c:=a-b) or 1)
and not print(f'compute: {a} + {b} + {c}')
and (
(ret:=a + b + c) or ret)
)
)
tst(0)
# prints: "compute: 0 + 0 + 0"; returns: 0
tst(1)
# prints: "compute: 1 + 1 + 0"; returns: 2
tst(8)
# prints: "compute: 8 + 64 + -56"; returns: 16
So the pattern is:
lambda: [*vars]: (
(bool(a:=[expr(*vars)]) or 1)
and (bool([expr]) or 1)
and bool([always true expr])
and not bool([always false expr])
and (
# parentheses required so `result:=` doesn't capture the `or result` part
(result:=[result expr]) or result
)
)
This may be simplified if you know the truthiness of any particular expression.
That being said, if you want to assign a variable to reuse inside a lambda, you probably should consider writing a normal function.
Im no expert at this, but the way i did it was by modifying globals() or locals()
like this:
lambda: globals().__setitem__('some_variable', 'some value')
or if it's inside a function:
lambda: locals().__setitem__('some_variable', 'some value')
you could also use update() instead of __setitem__() if you wanted to, but that's a bit redundant.
i hope that after 4 years my late answer will be useful
Python has setattr function to set attribute of given object. You can use it in your lambda expression.
setattr is useful when you want to programmatically-correctly (sorry) set some class or class' instance. It is not used frequently because it is easier to assign variables directly with = expression. But for lambdas... It is a salvation.
Also, iterables that support settign item (such as list), you can use <iter>.__setitem__.
Option 1. If you know the name of variable you're assigning.
x = lambda nameofvar, value: setattr(__builtins__, nameofvar, value)
# abc does not exist right now. Assigning and setting it to 10
x('abc', 10)
print(abc) # output: 10
alt, if you want to set object's attribute:
class MyClass:
my_attr = False
def __init__(self, value):
self.value = value
myinstance = MyClass(25)
x = lambda obj, nameofvar, value: setattr(obj, nameofvar, value)
short_x = lambda nameofvar, value: setattr(MyClass, nameofvar, value)
# ^^^ this one works only for MyClass' attributes.
print(MyClass.my_attr) # output: False
x(MyClass, 'my_attr', True) # Changing MyClass' my_attr's value
print(MyClass.my_attr) # output: True
x(MyClass, 'my_attr2', 5) # Assigning new attribute to MyClass
print(MyClass.my_attr2) # output: 5
short_x('my_attr2', 123) # Setting MyClass' my_attr2 to 123
print(MyClass.my_attr2) # output: 123
print(myinstance.value) # output: 25
x(myinstance, 'value', 500)
print(myinstance.value) # output: 500
Option 2. Make a custom class and turn variable into its instance.
class Value:
def __init__(self, value):
self.value = value
x = lambda var, newvalue: setattr(var, 'value', newvalue)
a = Value(15)
print(a.value) # output: 15
x(a, 25)
print(a.value) # output: 25
Option 3. To set object's item.
lst = [15, 30, 45, 60, 75, 90]
x = lambda iterable, item, value: iterable.__setitem__(item, value)
print(lst) # output: [15, 30, 45, 60, 75, 90]
x(lst, 2, 1000)
print(lst) # output: [15, 30, 1000, 60, 75, 90]
You can instead use a bit of creativity, for example if you want to do some evaluation to an equation and assign the result to a variable it can be done like this:
class Results:
res = 0
clas= Results()
setattr(clas, 'res', 3+2*4)
print(clas.res)
You could rewrite this in a oop way, like this, maybe you are using an oop structure anyways so you could integrate it in there.
class example:
def __init__(self):
self.a = None
object = example()
a = lambda n:(setattr(object, "a", 3+2*n)) #[my math here]
a(2)
print(object.a)
Output:
7
A problem meeted in rewriting a python program.
I move some previous global variables into a dictionay, so I have to rewrite the functions which have used those variables.
For example,
#old one
a, b = 1, 2
def func(c):
print a+b+c
#new one
d = dict(a=1,b=2)
def func(c,d):
a = d['a']
b = d['b']
print a+b+c
As the dictionary d is large, so I'm seeking a something like this
d = dict(a=1,b=2)
def func(c,d):
locals().update(d)
print a+b+c
I have tried __dict__.update(d), however __dict__ can't be accessed directly.
Or for key,value in d.items():
setattr(obj,key,value)
is possible? If yes, how to set the obj to the function itself?
You can't create local variables programmatically in that way.
Instead, just use the dictionary directly by accessing its keys.
What you could do instead is to evaluate your expression using the dictionary as the local variables:
def func(c,d):
print eval('a+b+c',globals(),dict(d,c=c))
func(3,dict(a=1,b=2))
You could use in clause of an exec statement. In the in clause you may provide namespace(s) for Python to search when executing a string. Documentation
For example:
>>> d = dict(a=1, b=2)
>>> def func(c,d):
exec 'print a+b+c' in d, locals()
>>> func(5,d)
8
I'm trying to define variable inside function. vars() shows variable is created, but gives me NameError: exception. What am I doing wrong?
def a(str1):
vars() [str1] = 1
print vars()
print b
a('b')
output:
{'str1': 'b', 'b': 1}
exception:
NameError: global name 'b' is not defined
You're invoking undefined behaviour. From the documentation of vars():
Note The returned dictionary should not be modified: the effects on the corresponding symbol table are undefined.
Other answers give possible solutions.
Your code works for me. Perhaps you should try an alternative approach:
exec(str1 + '=1')
This will execute b=1
If you don't understand why a construct doesn't work, neither will the next person who has to read your code. If you mean
b = 1
you should say that. In this case vars() gives you access to the function local dictionary so your code is equivalent to
def a():
b = 1
where b is local to a and evaporates when it goes out of scope upon exit from a.
premature optimization is the root of many people's attempt to second-guess Python
from itertools import izip
import timeit
import msw.wordlist
def zip_list(p):
"""construct a dictionary of length 100 from a list of strings"""
return dict(zip(p[:100], p[100:]))
def izip_list(p):
"""as zip_list but avoids creating a new list to feed to dict()"""
return dict(izip(p[:100], p[100:]))
def pass_list(p):
"""take 100 elements of a list and do nothing"""
for i in p[:100]:
pass
def exec_pass_list(p):
"""exec() a no-op 100 times"""
for i in xrange(100):
exec('pass')
# returns a list of 64'000 unique lowercase dictionary words for tests
words = msw.wordlist.Wordlist()
words.shuffle()
words = words[:200]
print 'words', words[:5], '...'
for func in ['zip_list', 'izip_list', 'pass_list', 'exec_pass_list']:
t = timeit.Timer('%s(words)' % func,
'from __main__ import words, %s' % func)
print func, t.repeat(number=10**5)
which yields:
words ['concatenated', 'predicament', 'shtick', 'imagine', 'stationing'] ...
zip_list [1.8603439331054688, 1.8597819805145264, 1.8571949005126953]
izip_list [1.5500969886779785, 1.5501470565795898, 1.5536530017852783]
pass_list [0.26778006553649902, 0.26837801933288574, 0.26767921447753906]
exec_pass_list [74.459679126739502, 75.221366882324219, 77.538936853408813]
I didn't bother trying implement whatever the OP was trying to do because being 50 times slower to not construct a dictionary sort makes further testing kinda stupid.
I have a variable x in python. How can i find the string 'x' from the variable. Here is my attempt:
def var(v,c):
for key in c.keys():
if c[key] == v:
return key
def f():
x = '321'
print 'Local var %s = %s'%(var(x,locals()),x)
x = '123'
print 'Global var %s = %s'%(var(x,locals()),x)
f()
The results are:
Global var x = 123
Local var x = 321
The above recipe seems a bit un-pythonesque. Is there a better/shorter way to achieve the same result?
Q: I have a variable x in python. How can i find the string 'x' from the variable.
A: If I am understanding your question properly, you want to go from the value of a variable to its name. This is not really possible in Python.
In Python, there really isn't any such thing as a "variable". What Python really has are "names" which can have objects bound to them. It makes no difference to the object what names, if any, it might be bound to. It might be bound to dozens of different names, or none.
Consider this example:
foo = 1
bar = foo
baz = foo
Now, suppose you have the integer object with value 1, and you want to work backwards and find its name. What would you print? Three different names have that object bound to them, and all are equally valid.
print(bar is foo) # prints True
print(baz is foo) # prints True
In Python, a name is a way to access an object, so there is no way to work with names directly. You might be able to search through locals() to find the value and recover a name, but that is at best a parlor trick. And in my above example, which of foo, bar, and baz is the "correct" answer? They all refer to exactly the same object.
P.S. The above is a somewhat edited version of an answer I wrote before. I think I did a better job of wording things this time.
I believe the general form of what you want is repr() or the __repr__() method of an object.
with regards to __repr__():
Called by the repr() built-in function
and by string conversions (reverse
quotes) to compute the “official”
string representation of an object.
See the docs here: object.repr(self)
stevenha has a great answer to this question. But, if you actually do want to poke around in the namespace dictionaries anyway, you can get all the names for a given value in a particular scope / namespace like this:
def foo1():
x = 5
y = 4
z = x
print names_of1(x, locals())
def names_of1(var, callers_namespace):
return [name for (name, value) in callers_namespace.iteritems() if var is value]
foo1() # prints ['x', 'z']
If you're working with a Python that has stack frame support (most do, CPython does), it isn't required that you pass the locals dict into the names_of function; the function can retrieve that dictionary from its caller's frame itself:
def foo2():
xx = object()
yy = object()
zz = xx
print names_of2(xx)
def names_of2(var):
import inspect
callers_namespace = inspect.currentframe().f_back.f_locals
return [name for (name, value) in callers_namespace.iteritems() if var is value]
foo2() # ['xx', 'zz']
If you're working with a value type that you can assign a name attribute to, you can give it a name, and then use that:
class SomeClass(object):
pass
obj = SomeClass()
obj.name = 'obj'
class NamedInt(int):
__slots__ = ['name']
x = NamedInt(321)
x.name = 'x'
Finally, if you're working with class attributes and you want them to know their names (descriptors are the obvious use case), you can do cool tricks with metaclass programming like they do in the Django ORM and SQLAlchemy declarative-style table definitions:
class AutonamingType(type):
def __init__(cls, name, bases, attrs):
for (attrname, attrvalue) in attrs.iteritems():
if getattr(attrvalue, '__autoname__', False):
attrvalue.name = attrname
super(AutonamingType,cls).__init__(name, bases, attrs)
class NamedDescriptor(object):
__autoname__ = True
name = None
def __get__(self, instance, instance_type):
return self.name
class Foo(object):
__metaclass__ = AutonamingType
bar = NamedDescriptor()
baaz = NamedDescriptor()
lilfoo = Foo()
print lilfoo.bar # prints 'bar'
print lilfoo.baaz # prints 'baaz'
There are three ways to get "the" string representation of an object in python:
1: str()
>>> foo={"a":"z","b":"y"}
>>> str(foo)
"{'a': 'z', 'b': 'y'}"
2: repr()
>>> foo={"a":"z","b":"y"}
>>> repr(foo)
"{'a': 'z', 'b': 'y'}"
3: string interpolation:
>>> foo={"a":"z","b":"y"}
>>> "%s" % (foo,)
"{'a': 'z', 'b': 'y'}"
In this case all three methods generated the same output, the difference is that str() calls dict.__str__(), while repr() calls dict.__repr__(). str() is used on string interpolation, while repr() is used by Python internally on each object in a list or dict when you print the list or dict.
As Tendayi Mawushe mentiones above, string produced by repr isn't necessarily human-readable.
Also, the default implementation of .__str__() is to call .__repr__(), so if the class does not have it's own overrides to .__str__(), the value returned from .__repr__() is used.