"for i in True,False:" Python, explanation needed - python

I hope I can ask here for an explanation not just a solution to problem.
So I know how this works:
for i in range(10):
//blocks of code
It goes from i =0 all the way up to i = 9, so it the blocks of code executes 10 times. My question is what does this do:
for i in True,False:
//block of code
Does this run just once ? Or two times ? Or does the blocks of code use the i as True/False or 1/0 ?
I hoe someone can clarify this for me. Thanks !

The True,False is a tuple, equivalent to (True, False). That tuple has a length of two, so the block of code runs twice.
As for whether it runs as booleans or integers, that depends on how you use i. bool is a subclass of int in Python, so it will normally act as a boolean, but you will be able to do mathematical operations with it as it is basically just another representation of an integer.

In Python, the for keyword is really a "foreach". It iterates over the objects you give to it.
range() returns a list (in Python 2.x), so for i in range(3): iterates over the integers in the list. In Python 3.x range() returns an iterator, so for i in range(3): iterates over the integers yielded up by the iterator. Either way, i is set to integers from the range, one at a time.
Python has tuples, which are usually written like this: (True, False)
That's a tuple with two elements. The first is True and the second is False.
But in Python, you don't actually need the parentheses for a tuple; a series of values separated by commas is also a tuple. Thus this is a tuple equivalent to the first one: True, False
It's tricky to make a length-1 tuple in Python. You still need the comma, so it looks weird. Here's a length-1 tuple: 0,
This looks weird but it's legal: a loop that will run exactly once, because we pass a length-1 tuple to for:
for i in 0,:
print i
This will print 0 and terminate.

for ... in ... loops basically cycle through every element in what's called an iterable object. Iterable objects include lists, dicts, tuples, etc. range(x) returns the list [0,1,2,3,...,(x-1)], for example, so
for i in range(10):
//blocks of code
is really the same thing as
for i in [0,1,2,3,4,5,6,7,8,9]:
//blocks of code
Hence, you can think of
for i in True,False:
//block of code
as being interpreted as
for i in [True,False]:
//block of code

Short answer: it runs two times. The first time, i==True, and the second time, i==False.
You need to know how for loops work and what a tuple is for this to make sense. A for loop just... well... loops over an iterable. You could rewrite what you have a couple different ways:
# The parentheses here don't do anything different from what you had, actually.
# But it makes it more clear that you're making a tuple and iterating over it.
for i in (True, False):
// block of code
Equivalently, you can loop over a list:
for i in [True, False]:
// block of code
You'll get exactly the same results this way, you're just looping through a list instead of a tuple.

Related

Why do i get <map object at 0x0389DCD0> when using map

What i have understood so far from the map function is that it applies a given function to each item in an iterable and returns the list of the result.
def square(num):
return num**2
list_num = [1,2,3,4]
considering the above function and the list of numbers as an example.
if we: list(map(square,list_num)) we will get as an output [1,4,9,16].
now comes the part that i am not able to find a sensible explenation of, if i
print(map(square,list_num)) i will get as an output <map object at 0x038B0290>.
My question is, Why am i getting the memory location and not a list when i use the print() function or when use map(square,list_num).
map doesn't return a list. It returns a map object that lazily produces results as needed:
print(type(map(int, [1])))
<class 'map'>
It also doesn't override the stringify method which would produce pretty-printed results. That may be because that would require forcing the entire list to be evaluated, and if that's acceptable in your program, you probably shouldn't be using map in the first place; unless you're debugging, in which case use of list is probably fine unless you're dealing with an infinite list.
If you want a full-element print out, explicitly force it by placing it in a list before printing as you saw, or use a strict list production method like a list comprehension.

Detect empty list vs list of empty strings

I am new to Python, and I have searched for solution for detecting empty list. Say we have an empty string, like:
a = ''
if not a:
print('a is empty')
This works fine. However, my problem arises when:
a = ['','','']
if not a:
print('a is empty')
This one does not work. What is the Pythonic way of detecting a which I guess is a list containing empty strings in the above case?
Thanks in advance for your comments and suggestions.
A list is only empty if it has no members. It has members, but they're empty, it still has members, so it's still truthy.
If you want to test whether all of the members of a list are empty, you can write it like this:
if all(not element for element in a):
print('a is made of empty things')
The all function should be pretty obvious. The argument to it might not be. It's a generator expression—if you've never seen one, first read about list comprehensions, then iterators and the following two sections.
Or you can turn it around and test whether not any of the members are not empty:
if not any(a):
print('a is made of empty things')
The double negative seems a bit harder to understand. But on the other hand, it means you don't need to understand a generator expression (because (element for element in a) is just the same thing as a, so we can keep it simple).
(And, as PM 2Ring points out, this one probably a little faster, although probably not enough to matter for most uses.)

Understanding Python Maps()

So I am trying to figure out how Python's map() function works as a way to speed up my program a little bit. From my basic understanding it looks like you can use map() to replace certain instances where you'd use a for loop. What I'm curious about is can you change something like:
loopNum = 25
for i in range (loopNum):
self.doSomething()
To:
loopNum = 25
map(self.doSomething(), range(loopNum))
Additionally, in the above example, would I be able to forego that loopNum variable, and in the map just have map(something, 25)?
No, you can't as map(function, iterable) applies function to each element of the iterable. If you simply want to execute some functionn times, just use a loop.
Note that iterable must be (surprise!) an iterable, not a number.
map is roughly the equivalent of this for loop:
# my_map(func, iter1, iterN...)
def my_map(func, *iteables)
for x, y,... in zip(iter1, iter2,iterN...):
yield func(x,y,...)
What you're doing in your code is just like this:
my_map(self.doSomething(), range(loopNum))
self.dSomething() must return a function or a callable object or this obviously doesn't work. This is because, whatever object you pass into the func argument of my_map function will be called then in addition to passing the right number of arguments to func, func must be a callable object as well :-)
*You must iterate over the iterable returned by map to obtain the results, otherwise, you would just get an iterable object without tangible work.
I want to add to this question that map() is virtually never the right tool in Python. Our BDFL himself, wanted to remove it from Python 3, together with lambdas and, most forcefully reduce.
In almost all cases where you feel tempted to use map() take a step back and try to rewrite your code using list comprehension instead. For your current example, that would be:
my_list = [self.doSomething() for i in range(loopNum)]
or
my_generator = (self.doSomething() for i in range(loopNum))
to make it a generator instead.
But for this to make any sense at all, self.doSomething() should probably take the variable i as an input. After all you are trying to map the values in your range to something else.

making python code block with loop faster

Is there a way I can implement the code block below using map or list comprehension or any other faster way, keeping it functionally the same?
def name_check(names, n_val):
lower_names = names.lower()
for item in set(n_val):
if item in lower_names:
return True
return False
Any help here is appreciated
A simple implementation would be
return any(character in names_lower for character in n_val)
A naive guess at the complexity would be O(K*2*N) where K is the number of characters in names and N is the number of characters in n_val. We need one "loop" for the call to lower*, one for the inner comprehension, and one for any. Since any is a built-in function and we're using a generator expression, I would expect it to be faster than your manual loop, but as always, profile to be sure.
To be clear, any short-circuits, so that behaviour is preserved
Notes on Your Implementation
On using a set: Your intuition to use a set to reduce the number of checks is a good one (you could add it to my form above, also), but it's a trade-off. In the case that the first element short circuits, the extra call to set is an additional N steps to produce the set expression. In the case where you wind up checking each item, it will save you some time. It depends on your expected inputs. If n_val was originally an iterable, you've lost that benefit and allocated all the memory up front. If you control the input to the function, why not just recommend it's called using lists that don't have duplicates (i.e., call set() on its input), and leave the function general?
* #Neopolitan pointed out that names_lower = names.lower() should be called out of the loop, as your original implementation called it, else it may (will?) be called repeatedly in the generator expression

When to use "while" or "for" in Python

When I should use a while loop or a for loop in Python? It looks like people prefer using a for loop (for brevity?). Is there any specific situation which I should use one or the other? Is it a matter of personal preference? The code I have read so far made me think there are big differences between them.
Yes, there is a huge difference between while and for.
The for statement iterates through a collection or iterable object or generator function.
The while statement simply loops until a condition is False.
It isn't preference. It's a question of what your data structures are.
Often, we represent the values we want to process as a range (an actual list), or xrange (which generates the values) (Edit: In Python 3, range is now a generator and behaves like the old xrange function. xrange has been removed from Python 3). This gives us a data structure tailor-made for the for statement.
Generally, however, we have a ready-made collection: a set, tuple, list, map or even a string is already an iterable collection, so we simply use a for loop.
In a few cases, we might want some functional-programming processing done for us, in which case we can apply that transformation as part of iteration. The sorted and enumerate functions apply a transformation on an iterable that fits naturally with the for statement.
If you don't have a tidy data structure to iterate through, or you don't have a generator function that drives your processing, you must use while.
while is useful in scenarios where the break condition doesn't logically depend on any kind of sequence. For example, consider unpredictable interactions:
while user_is_sleeping():
wait()
Of course, you could write an appropriate iterator to encapsulate that action and make it accessible via for – but how would that serve readability?¹
In all other cases in Python, use for (or an appropriate higher-order function which encapsulate the loop).
¹ assuming the user_is_sleeping function returns False when false, the example code could be rewritten as the following for loop:
for _ in iter(user_is_sleeping, False):
wait()
The for is the more pythonic choice for iterating a list since it is simpler and easier to read.
For example this:
for i in range(11):
print i
is much simpler and easier to read than this:
i = 0
while i <= 10:
print i
i = i + 1
for loops is used
when you have definite itteration (the number of iterations is known).
Example of use:
Iterate through a loop with definite range: for i in range(23):.
Iterate through collections(string, list, set, tuple, dictionary): for book in books:.
while loop is an indefinite itteration that is used when a loop repeats
unkown number of times and end when some condition is met.
Note that in case of while loop the indented body of the loop should modify at least one variable in the test condition else the result is infinite loop.
Example of use:
The execution of the block of code require that the user enter specified input: while input == specified_input:.
When you have a condition with comparison operators: while count < limit and stop != False:.
Refrerences: For Loops Vs. While Loops, Udacity Data Science, Python.org.
First of all there are differences between the for loop in python and in other languages.
While in python it iterates over a list of values (eg: for value in [4,3,2,7]), in most other languages (C/C++, Java, PHP etc) it acts as a while loop, but easier to read.
For loops are generally used when the number of iterations is known (the length of an array for example), and while loops are used when you don't know how long it will take (for example the bubble sort algorithm which loops as long as the values aren't sorted)
Consider processing iterables. You can do it with a for loop:
for i in mylist:
print i
Or, you can do it with a while loop:
it = mylist.__iter__()
while True:
try:
print it.next()
except StopIteration:
break
Both of those blocks of code do fundamentally the same thing in fundamentally the same way. But the for loop hides the creation of the iterator and the handling of the StopIteration exception so that you don't need to deal with them yourself.
The only time I can think of that you'd use a while loop to handle an iterable would be if you needed to access the iterator directly for some reason, e.g. you needed to skip over items in the list under some circumstances.
For loops usually make it clearer what the iteration is doing. You can't always use them directly, but most of the times the iteration logic with the while loop can be wrapped inside a generator func. For example:
def path_to_root(node):
while node is not None:
yield node
node = node.parent
for parent in path_to_root(node):
...
Instead of
parent = node
while parent is not None:
...
parent = parent.parent
while loop is better for normal loops
for loop is much better than while loop while working with strings, like lists, strings etc.
If your data is dirty and it won't work with a for loop, you need to clean your data.
For me if your problem demands multiple pointers to be used to keep
track of some boundary I would always prefer While loop.
In other cases it's simply for loop.

Categories