I am creating a string, to print the fields in a list, . the fields should be separated by ';', code snippet looks like this( simplified code, not actual )
list = ["abc","xyz","pqr"]
str = "print " + "list[0]" + ";" + "list[2]" # This is dynamically generated
exec (str)
My problem here is, with exec statement, it prints only "xyz" , because of the semi colon. what is the best way to solve this, so that the exec statement prints "xyz;pqr"
You are generating the following code:
print list[0];list[2]
Note that the ; is not quoted. Since a ; is used by Python to separate multiple simple statements on a line, Python executes the print list[0] first, then list[2] (which ends up doing nothing).
You'd have to generate this code instead:
print list[0] + ';' + list[2]
which you could do with:
str = "print " + "list[0]" + " + ';' + " + "list[2]"
However, you should not be using code generation at all. Use standard Python methods to join or format a string. You could use str.format():
print '{};{}'.format(list[0], list[2])
or you could use str.join():
print ';'.join([list[0], list[2]])
If you must vary what code is executed based on some other variables, try to avoid exec still. You could use from __future__ import print_function or encapsulate the print statement in a new function, then call functions dynamically. You can always use a dispatch table to map a string to a function to call, for example.
Try this:
str = "print" + "list[0]" + "';'" + "list[2]"
or
str = "print" + "list[0]" + "/;" + "list[2]"
The problem here is that Python optionally allows semicolons to delimit two separate statements (Compound statements). So when you use exec on the evaluated statement print "abc";"xyz", Python thinks they are two separate statements, hence, only printing "abc".
You could use single quotes around the semicolon to show that it is a string and concatenate them with their surrounding strings:
# Refrain from using list and str as they are built-ins
l = ["abc", "xyz", "pqr"]
s = "print " + "l[0]" + "+';'+" + "l[2]"
exec(s)
Related
I am trying to enumerate a list of of dictionary definitions which are strings and remove the curly braces. The definitions in the list are taken from a json (dictionary api) which is why i am using join to remove the curly brackets.
When I try doing them at the same time it gives a "type error: sequence item 0: expected str instance, tuple found". I have tried joining first and then enumerating but that comes with an error too.
I don't believe I can use a for loop because I am assigning all 3 definitions to a single variable (to use in tkinter) and using a for loop would only show definition 3, also because I am not printing the results.
Example:
definitions = [{definition1},{definition2},{definition3}]
I want to make it so that it shows:
result = 1. definition1
2. definition2
3. definition3
I have achieved the same result by doing:
result = "1. " + definitions[0] + "\n" + "2. " + definitions[1] + "\n" + "3. " + definitions[2]
but would rather be able to do it in a way that doesn't require me to type out everything manually
In Python, [{'definition1'}, {'definition2'}, {'definition3'}] is not a list of dictionaries, it is a list of sets.
So first you need to review How to extract the member from single-member set in python? to understand how to get the members out of each set object.
Then you can use the enumerate built-in function to get an iterable matching up objects in the list with their position in the list, an f-string to form each line of the output, a list comprehension to collect the lines into a list, and then string.join() to combine the lines into a single output string:
definitions = [{'definition1'},{'definition2'},{'definition3'}]
out = '\n'.join([f'{n}. {list(d)[0]}' for n, d in enumerate(definitions, start=1)]))
print(out)
Result:
1. definition1
2. definition2
3. definition3
use enumerate + join can do the trick
result = ""
for idx, definition in enumerate(defintions):
result += f"{idx + 1}: {' '.join(definition.values())} \n"
if the definition is a set use
result += f"{idx + 1}: {' '.join(definition)} \n"
I'd like to specify a string with both line continuation and catenation characters. this is really useful if I'm echoing a bunch of related values. Here is a simple example with only two parameters:
temp = "here is\n"\
+"\t{}\n"\
+"\t{}".format("foo","bar")
print(temp)
here's what I get:
here is
{}
foo
And here is what I expect:
here is
foo
bar
What gives?
You can try something like this :
temp = ("here is\n"
"\t{}\n"
"\t{}".format("foo","bar"))
print(temp)
Or like :
# the \t have been replaced with
# 4 spaces just as an example
temp = '''here is
{}
{}'''.format
print(temp('foo', 'bar'))
vs. what you have:
a = "here is\n"
b = "\t{}\n"
c = "\t{}".format("foo","bar")
print( a + b + c)
str.format is called before your strings are concatenated. Think of it like 1 + 2 * 3, where the multiplication is evaluated before the addition.
Just wrap the whole string in parentheses to indicate that you want the strings concatenated before calling str.format:
temp = ("here is\n"
+ "\t{}\n"
+ "\t{}").format("foo","bar")
Python in effect sees this:
Concatenate the result of
"here is\n"
with the resuslt of
"\t{}\n"
with the result of
"\t{}".format("foo","bar")
You have 3 separate string literals, and only the last one has the str.format() method applied.
Note that the Python interpreter is concatenating the strings at runtime.
You should instead use implicit string literal concatenation. Whenever you place two string literals side by side in an expression with no other operators in between, you get a single string:
"This is a single" " long string, even though there are separate literals"
This is stored with the bytecode as a single constant:
>>> compile('"This is a single" " long string, even though there are separate literals"', '', 'single').co_consts
('This is a single long string, even though there are separate literals', None)
>>> compile('"This is two separate" + " strings added together later"', '', 'single').co_consts
('This is two separate', ' strings added together later', None)
From the String literal concatenation documentation:
Multiple adjacent string or bytes literals (delimited by whitespace), possibly using different quoting conventions, are allowed, and their meaning is the same as their concatenation. Thus, "hello" 'world' is equivalent to "helloworld".
When you use implicit string literal concatenation, any .format() call at the end is applied to that whole, single string.
Next, you don't want to use \ backslash line continuation. Use parentheses instead, it is cleaner:
temp = (
"here is\n"
"\t{}\n"
"\t{}".format("foo","bar"))
This is called implicit line joining.
You might also want to learn about multiline string literals, where you use three quotes at the start and end. Newlines are allowed in such strings and remain part of the value:
temp = """\
here is
\t{}
\t{}""".format("foo","bar")
I used a \ backslash after the opening """ to escape the first newline.
The format function is only being applied to the last string.
temp = "here is\n"\
+"\t{}\n"\
+"\t{}".format("foo","bar")
Is doing this:
temp = "here is\n" + "\t{}\n"\ + "\t{}".format("foo","bar")
The key is that the .format() function is only happening to the last string:
"\t{}".format("foo","bar")
You can obtain the desired result using parentheses:
temp = ("here is\n"\
+"\t{}\n"\
+"\t{}").format("foo","bar")
print(temp)
#here is
# foo
# bar
i = 0
while i < 10:
print('print("Hello world '+ str (i*9)+'")')
i = i + 1
I was practicing loop and I wonder why I have to put + after STR(1*9) ??
print('print("Hello world '+ str (i*9)'")') and Why this code has syntax error?
(no plus sign)
I tried put code print(print("Hello world"+str(i*9))) to not use + but I got
Hello world0
None
Hello world9
None
Hello world18
None
To concatenate two string together you need the + operator to tell the python interpreter to specify its some_string plus some_other_string.
Alternatively if you dont like using the + operator you can use .format() like so;
while i < 10:
print("Hello World {0}".format(i*9))
i = i + 1
The string to be inserted goes inside the curly braces. I used 0 inside the curlies because you can add others to your string incrementing the numbers and adding another paramater to the format function.
A + concatenates strings in python. So you need it. Python does not know how to interpret two variables next to each other without , or + or else between them. '")' is also considered a variable in programming context.
https://gcc.gnu.org/onlinedocs/cpp/Stringification.html allows to stringify argument (before evaluation), which is useful for debugging. How would we do it in python?
eg:
def prettyprint(a):
#requires special function stringify
print(stringify('a') + ':' + str(a));
def test():
prettyprint(1+2)
# will print: 1+2:3
I don't think there is a way to do this without using strings. The C preprocessor really only processes text, so stringify is placing the expression in quotes and the rest is eval
def prettyprint(a):
print( a + ':' + str( eval(a) ) )
>>> prettyprint('1+2')
1+2:3
If you don't use strings, then the expression will be evaluated before the call and prettyprint has no way to figure out how the 3 it received came to be.
I have a program that prints out strings from an array like this:
for x in strings
print x,
Which works fine, the strings all print on the same line which is what I want, but then I also have to print out a string that isn't part of the array on a new line. Like this:
for x in strings:
print x,
print second_name
Which ends up all printing on the same line. I want second_name to print on a newline though, how do I do this?
Use the newline character \n:
print '\n' + second_name
I personally think it would be best to use str.join here:
print " ".join(strings)
print second_name
The for-loop just seems like overkill.
The most direct solution is that if you used "print" without final newline in a cycle, add it after this cycle; so the code will look like
for x in strings:
print x,
print ## this terminates the first output line
print second_name
This is kind of the most proper usage of print "API" according to its concepts.
OTOH the answer by K DawG does essentialy the same in other way, putting the default ending '\n' at beginning of the next "print", and, stream nature of stdout makes results of these two variants identical.
NB your construct isn't portable directly to Python3. Python2's print adds a space before each argument unless output isn't at beginning of line. Python3's separator is applied between arguments, but not before the first one in a line. So this manner (cloned from BASIC) isn't perspective and should be replaced with an own manner, like:
out = ''
for x in strings:
out += ' ' + x
print(out[1:])
print(second_name)
but, " ".join(strings) is generally faster and more clear to read.