I am seeking to be able to use variables within the format() parentheses, in order to parameterize it within a function. Providing an example below:
sample_str = 'sample_str_{nvars}'
nvars_test = 'apple'
sample_str.format(nvars = nvars_test) #Successful Result: ''sample_str_apple''
But the following does not work -
sample_str = 'sample_str_{nvars}'
nvars_test_2 = 'nvars = apple'
sample_str.format(nvars_test_2) # KeyError: 'nvars'
Would anyone know how to do this? Thanks.
Many thanks for guidance. I did a bit more searching. For anyone who may run into the same problem, please see examples here: https://pyformat.info
sample_str = 'sample_str_{nvars}'
nvars_test_2 = {'nvars':'apple'}
sample_str.format(**nvars_test_2) #Successful Result: ''sample_str_apple''
First, I'd recommend checking out the string format examples.
Your first example works as expected. From the documentation, you are permitted to actually name the thing you are passing into {}, and then pass in a same-named variable for str.format():
'Coordinates: {latitude}, {longitude}'.format(latitude='37.24N', longitude='-115.81W')
# returns 'Coordinates: 37.24N, -115.81W'
Your second example doesn't work because you are not passing a variable called nvars in with str.format() - you are passing in a string: 'nvars = apple'.
sample_str = 'sample_str_{nvars}'
nvars_test_2 = 'nvars = apple'
sample_str.format(nvars_test_2) # KeyError: 'nvars'
It's a little more common (I think) to not name those curly-braced parameters - easier to read at least.
print('sample_str_{}'.format("apple")) should return 'sample_str_apple'.
If you're using Python 3.6 you also have access to Python's formatted string literals.
>>> greeting = 'hello'
>>> name = 'Jane'
>>> f'{greeting} {name}'
'hello Jane'
Note that the literal expects the variables to be already present. Otherwise you get an error.
>>> f'the time is now {time}'
NameError: name 'time' is not defined
Related
Suppose I have
x = 3
s = "f'12{x}4'"
How to consider s as f-string to print 1234, like writing print(f'12{x}4')
when I print s, it prints it as it as: f'12{x}4'
Remve the double quotations that should fix the issue because the f in a f string needs to be outside the actuall string
You are missing two concepts.
The first one, is how you tell python your string is an f-string. The way to do this, is by adding the character 'f' before the first quotation mark:
f"this will be a f-string"
Whatever you have between {}, it will be a previously defined variable:
x = "something"
f"this will be {x}"
Assuming you ask this because you can not use actual f-strings, but also don't want to pass the parameters explicitly using format, maybe because you do not know which parameter are in the not-really-an-f-string, and also assuming you don't want to use eval, because, well, eval.
You could pass the variables in the locals or globals scope to format:
>>> x = 3
>>> s = '12{x}4'
>>> s.format(**globals())
'1234'
>>> s.format(**locals())
'1234'
Depending on where s is coming from (user input perhaps?) This might still be a bit risky, though, and it might be better to define a dict of "allowed" variables and use that in format. As with globals and locals, any unused variables do not matter.
>>> vars = {"x": x, "y": y, "z": z}
>>> s.format(**vars)
Note that this does not give you the full power of f-strings, though, which will also evaluate expressions. For instance, the above will not work for s = '12{x*x}4'.
You'd do this -
x = 3
s = f'12{x}4'
This can also work.
x = 3
s = "12{}4"
print(s.format(x))
Just remove extra commas
s = f'12{x}4'
x = 3
s = '12{}4'.format(x)
or
x = 3
print('12%s4' %x)
I have some troubles understanding the way the format() method of string works.
Suppose that I set a string variable with keywords arguments:
s = '{hello} {person_name}'
I could either assign this value to another variable or print it. In the latter case, the result would be {hello} {person_name}.
I could also use the format() method while printing s and assign some values to the keywords:
print(s.format(hello='hello', person_name='Alice'))
In this case, the result is hello Alice. Of course, I could also assign it to a new variable.
My problem arises when I want to use format only on one keyword:
print(s.format(hello='hello'))
or
a = s.format(hello='hello')
Both of them throw an error:
KeyError: 'person_name'
I want to be able to run something like :
s = '{hello} {person_name}'
a = s.format(hello='hello')
if something:
b = a.format(person_name='Alice')
else:
b = a.format(person_name='Bob')
print(b)
Is something like this possible or should I set all keywords when I use format()?
In your use case, you might consider escaping the {person} in the string:
# double brace the person_name to escape it for the first format
s = '{hello} {{person_name}}'
a = s.format(hello='hello')
# a = 'hello {person_name}'
if something:
b = a.format(person_name='Alice')
# b = 'hello Alice'
else:
b = a.format(person_name='Bob')
# b = 'hello Bob'
print(b)
With this method however you will need to follow the explicit order in which you escaped your variables. i.e. you must assign hello first and then person_name. If you need to be flexible about the order of things, I would suggest using a dict to construct the variables before passing it altogether:
# dict approach
s = '{hello} {person_name}'
# determine the first variable
d = {'hello':'hello'}
... do something
d.update({'person': 'Alice'})
# unpack the dictionary as kwargs into your format method
b = s.format(**d)
# b = 'hello Alice'
This gives you a bit more flexibility on the order of things. But you must only call .format() once all the variables are provided in your dict (at least it must have a default value), otherwise it'll still raise an error.
If you want to be more fancy and want the ability to print the field names at the absence of the variable, you can make your own wrapper function as well:
# wrapper approach
# We'll make use of regex to keep things simple and versatile
import re
def my_format(message, **kwargs):
# build a regex pattern to catch words+digits within the braces {}
pat = re.compile('{[\w\d]+}')
# build a dictionary based on the identified variables within the message provided
msg_args = {v.strip('{}'): v for v in pat.findall(message)}
# update the dictionary with provided keyword args
msg_args.update(kwargs)
# ... and of course, print it
print(message.format(**msg_args))
s = 'Why {hello} there {person}'
my_format(s, hello='hey')
# Why hey there {person}
my_format(s, person='Alice')
# Why {hello} there Alice
You can determine the default display (at the absence of a variable) you want by modifying the v in dictionary comprehension.
As per PEP 3101 If the index or keyword refers to an item that does not exist, then an IndexError/KeyError should be raised.
But you can create your own custom formatter class like this.
from string import Formatter
class MyStringFormatter(Formatter):
def get_value(self, key, args, kwds):
try:
return super().get_value(key, args, kwds)
except KeyError:
return "{%s}" % key
fmt = MyStringFormatter()
DEMO
s = "{hello} {person_name}"
keywords = {'hello': 'hello'}
a = fmt.format(s, **keywords)
print(a)
# This will print hello {person_name}
something = False
if something:
person_name = {'person_name': 'Alice'}
else:
person_name = {'person_name': 'Bob'}
b = fmt.format(a, **person_name)
print(b)
# This will print `hello Bob` if `something` is False, 'hello Alice' otherwise.
Is something like this possible or should I set all keywords when I use format()?
PEP-3101 says:
If the index or keyword refers to an item that does not exist, then an IndexError/KeyError should be raised.
So yes, if you are going to use keywords you would have to specify them all.
I think you have to define all the keywords while using format().
I would suggest a different approach using *args:
def printHello(*args):
print(' '.join([arg for arg in args]))
printHello('hello', 'Alice')
# hello Alice
printHello('hello')
# hello
You can send any number of words into this function.
Is there a possibility (e.g. a built-in function) to convert a string to a char in python? For example, if I assign a value to the variable
p1=100
and then have the string
"p1",
is it possible to assign the value of p1 to a new variable t like
t=char("p1")
so that I get
print(t)->100 ?
Obviously, above mentioned solution does not work as it throws following error message:
NameError: name 'char' is not defined
Edit: The question is not about best practices: I know that I should do this with a dictionary, but what I am trying to do is to understand data types in Python and how to convert them. Convert a string to an integer is fairly easy, for example, so I was wondering if the same applies to string to char conversions.
The eval() command does solve the example's question, but it does not answer above mentioned problem. So I would edit the goal to
char("p11")=20
which should give me
print(p11) -> 20
No. Use a dictionary.
>>> names = {'p1': 100, 'p2': 200}
>>> t = names['p1']
>>> t
100
This will throw a KeyError if the name does not exist:
>>> t = names['p3']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'p3'
... but you can use dict.get and provide a default value:
>>> t = names.get('p3', 'default')
>>> t
'default'
where the default-default-value is None.
(By the way, this has nothing to do with converting strings to a char(acter?), your terminology is quite confusing.)
You're probably looking for eval(): https://docs.python.org/3.5/library/functions.html#eval
p1 = 100
print(eval('p1')) # prints 100
If you want to evaluate expressions you can also use exec()
p1 = 100
t = 'p1 += 99'
exec(t)
print(p1) # prints 199
But as other already pointed out, you should avoid it if possible.
timgeb provided a nice alternative with dictionaries for example.
If you want to turn a string into a global variable you could also do:
globals()['y'] = 5
print(y)
Note: when you run your code in a global scope (outside a function), you can also use locals()['y'] = 5 - but this will not work in a non-global scope!
if you want to change it into character then do not use "char"
in python the char is declared as chr
so you can go like:
chr(input('Enter here'))
I came up with this situation while writing code in python for my project and began to think on this problem.
The problem is given a string containing a function name with its arguments how do we get the arguments and the function name given the number of arguments in the function.
My first thought was:
s = 'func(a,b)'
index = s.find('(')
if(index != -1):
arg_list = s[index+1:-1].split(',')
func_name = s[:index]
But as I began to think more I realised what if function is specified within functions which has its own arguments?
func1(func2(a,b,c),func3(d,e))
With my above approach I will end up with right function name but arg_list will contain
["func2(a","b","c)","func3(","d","e)"]
How to generically solve this situation?
If your language looks sufficiently like Python, use ast.parse():
import ast
def parse(s):
tree = ast.parse(s)
print ast.dump(tree)
parse('f(a,b)')
All the information you need will be encoded in tree.
>>> import pyparsing as pyp
>>> def get_name_and_args(a_string):
index = a_string.find('(')
if index == -1:
raise Exception("No '(' found")
else:
root_function, a_string = a_string[:index], a_string[index:]
data = {}
data[root_function] = pyp.nestedExpr().parseString(a_string).asList()[0][0].split(',')
return data
>>> print get_name_and_args("func(a,b)")
{'func': ['a', 'b']}
This solves the simpler example you gave using the pyparsing module. I wasn't sure exactly how you wanted the output formatted, and it doesn't work for the nested example. However this should be enough to get you started
Is there a way to know, during run-time, a variable's name (from the code)?
Or do variable's names forgotten during compilation (byte-code or not)?
e.g.:
>>> vari = 15
>>> print vari.~~name~~()
'vari'
Note: I'm talking about plain data-type variables (int, str, list etc.)
Variable names don't get forgotten, you can access variables (and look which variables you have) by introspection, e.g.
>>> i = 1
>>> locals()["i"]
1
However, because there are no pointers in Python, there's no way to reference a variable without actually writing its name. So if you wanted to print a variable name and its value, you could go via locals() or a similar function. ([i] becomes [1] and there's no way to retrieve the information that the 1 actually came from i.)
Variable names persist in the compiled code (that's how e.g. the dir built-in can work), but the mapping that's there goes from name to value, not vice versa. So if there are several variables all worth, for example, 23, there's no way to tell them from each other base only on the value 23 .
Here is a function I use to print the value of variables, it works for local as well as globals:
import sys
def print_var(var_name):
calling_frame = sys._getframe().f_back
var_val = calling_frame.f_locals.get(var_name, calling_frame.f_globals.get(var_name, None))
print (var_name+':', str(var_val))
So the following code:
global_var = 123
def some_func():
local_var = 456
print_var("global_var")
print_var("local_var")
print_var("some_func")
some_func()
produces:
global_var: 123
local_var: 456
some_func: <function some_func at 0x10065b488>
here a basic (maybe weird) function that shows the name of its argument...
the idea is to analyze code and search for the calls to the function (added in the init method it could help to find the instance name, although with a more complex code analysis)
def display(var):
import inspect, re
callingframe = inspect.currentframe().f_back
cntext = "".join(inspect.getframeinfo(callingframe, 5)[3]) #gets 5 lines
m = re.search("display\s+\(\s+(\w+)\s+\)", cntext, re.MULTILINE)
print m.group(1), type(var), var
please note:
getting multiple lines from the calling code helps in case the call was split as in the below example:
display(
my_var
)
but will produce unexpected result on this:
display(first_var)
display(second_var)
If you don't have control on the format of your project you can still improve the code to detect and manage different situations...
Overall I guess a static code analysis could produce a more reliable result, but I'm too lazy to check it now
This will work for simple data types (str, int, float, list etc.)
def my_print(var_str) :
print var_str+':', globals()[var_str]
You can do it, it's just not pretty.
import inspect, sys
def addVarToDict(d, variable):
lineNumber = inspect.currentframe().f_back.f_lineno
with open(sys.argv[0]) as f:
lines = f.read().split("\n")
line = lines[lineNumber-1]
varName = line.split("addVarToDict")[1].split("(")[1].split(",")[1].split(")")[0].strip()
d[varName] = variable
d = {}
a=1
print d # {}
addVarToDict(d,a)
print d # {'a': 1}
I tried the following link from the post above with no success:
Googling returned this one.
http://pythonic.pocoo.org/2009/5/30/finding-objects-names
Just yesterday I saw a blog post with working code that does just this. Here's the link:
http://pyside.blogspot.com/2009/05/finding-objects-names.html
Nice easy solution using f-string formatting, which is native to Python 3.6 and later:
vari = 15
vari_name = f"{vari=}".split("=")[0]
print(vari_name)
Produces:
vari