Trying to understand Python loop using underscore and input - python

One more tip - if anyone is learning Python on HackerRank, knowing this is critical for starting out.
I'm trying to understand this code:
stamps = set()
for _ in range(int(input())):
print('underscore is', _)
stamps.add(raw_input().strip())
print(stamps)
Output:
>>>2
underscore is 0
>>>first
set(['first'])
underscore is 1
>>>second
set(['second', 'first'])
I put 2 as the first raw input. How does the function know that I'm only looping twice? This is throwing me off because it isn't the typical...for i in xrange(0,2) structure.
At first my thinking was the underscore repeats the last command in shell. So I added print statements in the code to see the value of underscore...but the values just show the 0 and 1, like the typical loop structure.
I read through this post already and I still can't understand which of those 3 usages of underscore is being used.
What is the purpose of the single underscore "_" variable in Python?
I'm just starting to learn Python so easy explanations would be much appreciated!

ncoghlan's answer lists 3 conventional uses for _ in Python:
To hold the result of the last executed statement in an interactive
interpreter session. This precedent was set by the standard CPython
interpreter, and other interpreters have followed suit
For translation lookup in i18n (imported from the corresponding C
conventions, I believe), as in code like:
raise forms.ValidationError(_("Please enter a correct username"))
As a general purpose "throwaway" variable name to indicate that part
of a function result is being deliberately ignored, as in code like:
label, has_label, _ = text.partition(':')
Your question is which one of these is being used in the example in your code. The answer would be that is a throwaway variable (case 3), but its contents are printed here for debugging purposes.
It is however not a general Python convention to use _ as a loop variable if its value is used in any way. Thus you regularly might see:
for _ in range(10):
print("Hello world")
where _ immediately signals the reader that the value is not important and that the loop is just repeated 10 times.
However in a code such as
for i in range(10):
do_something(i)
where the value of the loop variable is used, it is the convention to use a variable name such as i or j instead of _.

For anyone that is trying to understand how underscore and input works in a loop - after spending quite sometime debugging and printing - here's the code that made me understand what was going on.
for _ in range(int(raw_input())):
print raw_input()
User input:
2
Dog
Cat
Output:
# no output despite entering 2, but 2 is set as range - loops 2 times
Dog
Cat
Bonus - notice how there's an int() conversion for the first line in the for loop?
The first input is 2, so int() converts that just fine. You can tell the first line of code is being ignored now because putting the second input, 'Dog', through int() would yield an error. Can't words into integer numbers.

The underscore is like a normal variable in your program.

Your code
stamps = set()
for _ in range(int(raw_input())):
print 'underscore is', _
stamps.add(raw_input().strip())
print stamps
is exactly equivalent to this:
how_many_loops = int(raw_input()) # asked only once.
stamps = set()
for i in range(how_many_loops):
print 'loop count is', i
stamps.add(raw_input().strip())
print stamps
Because whatever you put in range() has to be calculated before the loop starts, so the first int(raw_input()) is asked only once. If you use something like for i in range(very_expensive_list) it will take a bunch of time then start the loop.

Related

How does this line of code allow [end=" "] to apply in between of the letters?

So, I was studying basic things about Python. I encountered print function that basically prints something.
I learned that I could use [end=""] to end the print function.
For example,
my_job = 'hacker'
print(my_job, end="")
Basically gives me,
hacker
Another example, using the same values as above,
print(my_job, end="test")
Basically gives me,
hackertest
However, I then saw a cool thread in this site about how does the [end=""] function really works. I then noticed #Ritesh Karwa post this code,
myjob = 'hacker'
for c in myjob: print(c, end=" ")
Basically gave him,
h a c k e r
I know that the space inside the "" in the [end=] allowed the output to have spaces, but just how did that work? I mean, removing the [for c in myjob:] and only using the print function, the output became,
hacker
What is the mechanism behind this [for c in myjob:] that allowed the [end=] to apply spaces in between of the letters, resulting into this output,
h a c k e r
I wanted to ask #Ritesh Karwa directly through comments, but I don't have enough reputation. I'm not confident that I asked my question clearly, but I did my best. Thank you in advance for the helpful answers. I'm also using Python 3.xx
In Python, strings are also iterators (i.e. you can create a loop that will access them character by character). In this case:
for c in myjob:
is creating a loop where c will in turn have the value of each individual character in myjob.
If you then just did print(c) in the loop you would end up with
h
a
c
k
e
r
What the end=' ' is doing is replacing the default \n (newline) character that would normally force each print statement to print on a separate line as above and instead printing the contents of end=' ' (i.e. a space) after each print. That's giving you
h a c k e r
One thing you often have to remember after using end= is that the next print (which may be completely unrelated) will resume directly after the previous print, so would appear on the same line. People often would use a separate print() to print a newline so the next, unrelated print statement starts on a new line.
myjob is a string object, therefore an iterable. That means, that you can for example apply for loops such as for letter in myjob to iterate over all letters in the string.
As you have seen the optional end parameter of print replaces the standard end, which is a new line character with the one specified. So in this case, each occurrence in your for loop, the next letter is printed followed by a space. If you don't specify an end you will see that each letter would be printed to a new line.
end=“” removes the invisible new line (\n) that gets added at the end of a printing action.
Useful for for loops if you don’t want to get your results on separate lines.

triple-quoted strings comments crash simple python program

I found this strange problem when I trying to add comments to my code. I used the triple-quoted strings to comment but the program crashed by giving the following error:
IndentationError: unexpected indent
When I use # to comment the triple-quoted strings, everything works normally. Does anyone know the reason behind this error and how I could fix it?
My Code:
#This programs show that comments using # rather than """ """
def main():
print("let's do something")
#Try using hashtag to comment this block to get code working
'''
Note following block gives you a non-sense indent error
The next step would be to consider how to get all the words from spam and ham
folder from different directory. My suggestion would be do it twice and then
concentrate two lists
Frist think about the most efficient way
For example, we might need to get rid off the duplicated words in the beginning
The thoughts of writing the algorithem to create the dictionary
Method-1:
1. To append all the list from the email all-together
2. Eliminate those duplicated words
cons: the list might become super large
I Choose method-2 to save the memory
Method-2:
1. kill the duplicated words in each string
2. Only append elements that is not already in the dictionary
Note:
1. In this case, the length of feature actually was determined by the
training cohorts, as we used the different English terms to decide feature
cons: the process time might be super long
'''
def wtf_python(var1, var2):
var3 = var1 + var2 + (var1*var2)
return var3
wtfRst1 = wtf_python(1,2)
wtfRst2 = wtf_python(3,4)
rstAll = { "wtfRst1" : wtfRst1,
"wtfRst2" : wtfRst2
}
return(rstAll)
if __name__ == "__main__":
mainRst = main()
print("wtfRst1 is :\n", mainRst['wtfRst1'])
print("wtfRst2 is :\n", mainRst['wtfRst2'])
The culprit:
Move the comments inside the function definition:
The reason:
Since the triple-quote strings are valid python exp, they should be treated like-wise, i.e. inside the function scope.
Hence:
def main():
print("let's do something")
#Try using hashtag to comment this block to get code working
'''
Note following block gives you a non-sense indent error
The next step would be to consider how to get all the words from spam and ham
folder from different directory. My suggestion would be do it twice and then
concentrate two lists
Frist think about the most efficient way
For example, we might need to get rid off the duplicated words in the beginning
The thoughts of writing the algorithem to create the dictionary
Method-1:
1. To append all the list from the email all-together
2. Eliminate those duplicated words
cons: the list might become super large
I Choose method-2 to save the memory
Method-2:
1. kill the duplicated words in each string
2. Only append elements that is not already in the dictionary
Note:
1. In this case, the length of feature actually was determined by the
training cohorts, as we used the different English terms to decide feature
cons: the process time might be super long
'''
def wtf_python(var1, var2):
var3 = var1 + var2 + (var1*var2)
return var3
wtfRst1 = wtf_python(1,2)
wtfRst2 = wtf_python(3,4)
rstAll = { "wtfRst1" : wtfRst1,
"wtfRst2" : wtfRst2
}
return(rstAll)
if __name__ == "__main__":
mainRst = main()
print("wtfRst1 is :\n", mainRst['wtfRst1'])
print("wtfRst2 is :\n", mainRst['wtfRst2'])
OUTPUT:
let's do something
wtfRst1 is :
5
wtfRst2 is :
19
You should push the indentation level of you triple-quote strings one tag to the right.
Although triple-quote strings are often used as comments, they are normal python expressions, so they should follow the language's syntax.
Triple quoted strings as comments must be valid Python strings. Valid Python strings must be properly indented.
Python sees the multi-line string, evaluates it, but since you don't assign a variable to it the string gets thrown away in the next line.

Python for-loop to print a triangle

This code was given to me by my professor, and prints a triangle of *s:
def printTriangle(size):
for i in range(0,size):
for j in range(0,i+1):
print "*",
print
This is my failed attempt to code an inverse of the triangle:
def printInvertedTriangle(size):
for i in range(size,0):
for j in range(size,i-1):
print "*",
print
I have tried this many different ways, but this is how I think it should be, and it only gives me blank space before the program ends.
My understanding is that this is how his works:
for i in range(start,finish):
for j in range(start,step):
print "*",
print
Can anyone explain to me why the first block my professor gave me works, and why mine prints blank space? I thought I understood his loop; so what was I doing wrong in mine? What should it look like? I want something based off of his for loop. His goes against what I've been reading in Python tutorials in that he has only (start,step), whereas the tutorials say it goes (start,stop,step).
I got started in programming with JS, and thought that some simple Python loops would be a walk in the park...
Thanks a lot for any and all help!! #noob
def printInvertedTriangle(size):
**for i in range(size,0):**
for j in range(size,i-1):
print "*",
print
Your error of having white space shown I believe is as a result of line two. Since this index is counting how many times to step through lines, this needs to still run through x amount of iterations by ranging from (0,size).
In the second for loop, as the lines increase from 1 to 2 to 3 ...etc use variable i and the max (size) to build the reverse triangle.
Try this:
def printReverseTriangle(size):
for i in range(0,size):
for j in range(i,size):
print "*",
print
The reason your script outputs nothing is your range doesn't work.
As we can see in the interpreter:
>>> range(10,0)
[]
It outputs an empty list.
One way to accomplish what you want is to use the reversed() builtin to reverse the list.
for i in reversed(range(0,size)):
for j in range(0,i+1):
To help you in the future, try to use the interpreter more to check the output of things.
You can open any python module in interactive mode, which runs the program and then lets you use the interpreter afterward.
python -i script.py
Here is a program that I had to make for my weekend assignment. It gives a pretty decent reverse triangle as well.
def reverse_triangle(n):
r=n/2+1
for i in range(r-1,0,-1):
print" "*(r-i)," *"*i
def main():
n=input('Enter the size=')
reverse_triangle(n)
main()
Note: In this bit " *"*i I put the space before the asterisk because my PC's version of Python 2.7 does not print the pattern symmetrically if the space is not added. You can try it with the space or without it and check if it works for you.

How to split a string of Python source code into Python "statements"?

Given a string s containing (syntactically valid) Python source code, how can I split s into an array whose elements are the strings corresponding to the Python "statements" in s?
I put scare-quotes around "statements" because this term does not capture exactly what I'm looking for. Rather than trying to come up with a more accurate wording, here's an example. Compare the following two ipython interactions:
In [1]: if 1 > 0:
......: pass
......:
In [2]: if 1 > 0
File "<ipython-input-1082-0b411f095922>", line 1
if 1 > 0
^
SyntaxError: invalid syntax
In the first interaction, after the first [RETURN] statement, ipython processes the input if 1 > 0: without objection, even though it is still incomplete (i.e. it is not a full Python statement). In contrast, in the second interaction, the input is not only incomplete (in this sense), but also not acceptable to ipython.
As a second, more complete example, suppose the file foo.py contains the following Python source code:
def print_vertically(s):
'''A pretty useless procedure.
Prints the characters in its argument one per line.
'''
for c in s:
print c
greeting = ('hello '
'world'.
upper())
print_vertically(greeting)
Now, if I ran the following snippet, featuring the desired split_python_source function:
src = open('foo.py').read()
for i, s in enumerate(split_python_source(src)):
print '%d. >>>%s<<<' % (i, s)
the output would look like this:
0. >>>def print_vertically(s):<<<
1. >>> '''A pretty useless procedure.
Prints the characters in its argument one per line.
'''<<<
2. >>> for c in s:<<<
3. >>> print c<<<
4. >>>greeting = ('hello '
'world'.
upper())<<<
5. >>>print_vertically(greeting)<<<
As you can see, in this splitting, for c in s: (for example) gets assigned to its own item, rather being part of some "compound statement."
In fact, I don't have a very precise specification for how the splitting should be done, as long as it is done "at the joints" (like ipython does).
I'm not familiar with the internals of the Python lexer (though almost certainly many people on SO are :), but my guess is that you're basically looking for lines, with one important exception : paired open-close delimiters that can span multiple lines.
As a quick and dirty first pass, you might be able to start with something that splits a piece of code on newlines, and then you could merge successive lines that are found to contain paired delimiters -- parentheses (), braces {}, brackets [], and quotes '', ''' ''' are the ones that come to mind.

exec in Python 3

To take the number of test cases and output all the input numbers, I can do the following in Python 2.5
exec"print input();"*input()
How to do it in Python 3, in shortest possible way?
Your obfuscated code works just fine in Python 3 too, once you have adapted for the changes, which can trivially be done by running the code through 2to3.
exec("print(input());"*eval(input()))
(Although eval should in this case be replaced with int() as that's what you want.)
Obviously, this is all ridicolous, why are you using exec and multiplication of strings instead of loops?
for ignored in range(int(input())):
print(input())
You can also do it with a list expression:
[print(input()) for _ in range(int(input()))]
Although most people would say (and I would agree) that using list expressions for it's side effects or to loop is generally bad form. List expressions should be used to create lists.
This is a piece of clear and self-documenting code that does the same:
num_integers = int(input('How many integers do you want to input? '))
for x in range(num_integers):
print(input('Integer {}: '.format(x)))
Is there a reason you can't use a loop?
for _ in xrange(input()):
print input()
exec, like print, is a function call in Python 3. Wrap the string in parentheses.

Categories

Resources