For loops are likely to be one of the first concepts that a new Python programmer will pick up. This is for good reason because for loops can do a lot of things with data without getting crafty. However, often it can be easy to get your mind stuck in the world of simple iteration and not take advantage of some of the more efficient and concise methods of iteration and tricks to apply to for loops. Using these tricks can not only make your for loops faster, but can also make your code more concise and open up a new door for potential looping opportunities in Python.
(python logo courtesy of http://python.org)
One tool I have found really valuable in my experience is the ability to loop through two arrays at once. This is something noticeably more difficult in other languages, and something I really appreciate the ease of in Python. In order to loop through two arrays at once, we simply use the zip() method.
for first,second in zip(array1,array2):
print(first)
print(second)
A good example to demonstrate this is by counting with a list of even and a list of odd integers:
odds = [1,3,5,7,9]
evens = [2,4,6,8,10]
for oddnum, evennum in zip(odds,evens):
print(oddnum)
print(evennum)
And our output would be:
1
2
3
4
5
6
7
8
9
10
Though it might seem rather basic, there are a lot of interesting things you can do with a classic C style for loop.
for i in range(10):
print(i)
if i == 3:
i.update(7)
The C lovers among us might be thinking that this isn’t necessarily a C-style for loop, but this is the closest you can get without writing your own iteration method. Fortunately, I enjoy wasting my time, so I decided to write a new iterator to get as close to a classic C loop as possible:
class forrange:
def __init__(self, startOrStop, stop=None, step=1):
if step == 0:
raise ValueError('forrange step argument must not be zero')
if not isinstance(startOrStop, int):
raise TypeError('forrange startOrStop argument must be an int')
if stop is not None and not isinstance(stop, int):
raise TypeError('forrange stop argument must be an int')
if stop is None:
self.start = 0
self.stop = startOrStop
self.step = step
else:
self.start = startOrStop
self.stop = stop
self.step = step
def __iter__(self):
return self.foriterator(self.start, self.stop, self.step)
class foriterator:
def __init__(self, start, stop, step):
self.currentValue = None
self.nextValue = start
self.stop = stop
self.step = step
def __iter__(self): return self
def next(self):
if self.step > 0 and self.nextValue >= self.stop:
raise StopIteration
if self.step < 0 and self.nextValue <= self.stop:
raise StopIteration
self.currentValue = forrange.forvalue(self.nextValue, self)
self.nextValue += self.step
return self.currentValue
class forvalue(int):
def __new__(cls, value, iterator):
value = super(forrange.forvalue, cls).__new__(cls, value)
value.iterator = iterator
return value
def update(self, value):
if not isinstance(self, int):
raise TypeError('forvalue.update value must be an int')
if self == self.iterator.currentValue:
self.iterator.nextValue = value + self.iterator.step
The enumerate method in Python allows Python to number list indices as they are coming out of the array. To demonstrate this, I’ll make a three-element list:
l = [5,10,15]
Now we can access our array indices like this:
l[1]
10
l[0]
5
l[2]
15
When enumerating through these lists, we will get the index position of the dim, along with the dim, smashed together into a new variable. Notice the type of the new variable.
Python will automatically put these indices into a tuple, which I think is strange. I would certainly prefer to receive the results in a one-element Python dictionary. Fortunately, we could always turn our enumerates into a Python dictionary with Python’s
“ easy as Py”
type assertion!
data = dict(enumerate(l))
Which would give us:
>>> data
{0: 5, 1: 10, 2: 15}
The sort method is an essential method for anyone dealing with copious amount of data, as a Data Scientist often should. Sorting works how expected, with strings being sorted in alphabetical order from the letter A to the letter B, and sorting integers and doubles ascending from -∞. An important note to make about this function is that it will not work with lists containing strings and integers or floats.
l = [15,6,1,8]
for i in sorted(l):
print(i)
1
6
8
15
We can also do the inverse by setting the reverse parameter to False:
for i in sorted(l,reverse = True):
print(i)
15
8
6
1
And for the last parameter available to us, we can use a key. A key is a function that is applied to each dim inside of a given loop. For this, I like to use lambda, which will create an anonymous, but still callable, function.
l.sort(key=lambda s: s[::-1])
A function that will definitely help the performance side of things when working with heaps of data is the filter function. The filter function does exactly what you’d expect, and filters out data prior to iterating over it. This can be useful when you only want to have an effect on data in a certain range without ever having to apply a condition to it.
people = [{"name": "John", "id": 1}, {"name": "Mike", "id": 4}, {"name": "Sandra", "id": 2}, {"name": "Jennifer", "id": 3}]
for person in filter(lambda i: i["id"] % 2 == 0, people):
... print(person)
...
{'name': 'Mike', 'id': 4}
{'name': 'Sandra', 'id': 2}
Ideally, applying these methods to your Python code will make it not only more concise, but also most likely faster. Taking advantage of these methods will give you iteration superpowers and make it far easier to go through massive amounts of data with iteration, which is sometimes not avoidable.
#python #programming