Last active
August 31, 2021 14:48
-
-
Save codefisher/9d7993ddbf404c505128 to your computer and use it in GitHub Desktop.
python examples
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# make number always be odd | |
number = count if count % 2 else count - 1 | |
# call function if object is not None | |
name = user.name() if user is not None else 'Guest' | |
print "Hello", name |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from collections import Counter | |
order_count = Counter(menu_item for name, menu_item in order) | |
print order_count | |
# output | |
# Counter({ | |
# 'Beer': 2, | |
# 'Steak': 2, | |
# 'Wine': 1, | |
# 'Veggie Burger': 1 | |
# }) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
with open('/some/file', 'r') as f: | |
line_count = Counter(f) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from collections import defaultdict | |
order = ( | |
('Mark', 'Steak'), | |
('Andrew', 'Veggie Burger'), | |
('James', 'Steak'), | |
('Mark', 'Beer'), | |
('Andrew', 'Beer'), | |
('James', 'Wine'), | |
) | |
group_order = defaultdict(list) | |
for name, menu_item in order: | |
group_order[name].append(menu_item) | |
print group_order | |
# output | |
# defaultdict(<type 'list'>, { | |
# 'James': ['Steak', 'Wine'], | |
# 'Andrew': ['Veggie Burger', 'Beer'], | |
# 'Mark': ['Steak', 'Beer'] | |
# }) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
order_count = defaultdict(int) | |
for name, menu_item in order: | |
order_count[menu_item] += 1 | |
print order_count | |
# output | |
# defaultdict(<type 'int'>, { | |
# 'Beer': 2, | |
# 'Steak': 2, | |
# 'Wine': 1, | |
# 'Veggie Burger': 1 | |
# }) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
teachers = { | |
'Andy': 'English', | |
'Joan': 'Maths', | |
'Alice': 'Computer Science', | |
} | |
# using a list comprehension | |
subjects = dict((subject, teacher) for teacher, subject in teachers.items()) | |
# using a dictionary comprehension | |
subjects = {subject: teacher for teacher, subject in teachers.items()} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
students = ('James', 'Andrew', 'Mark') | |
for i, student in enumerate(students): | |
print i, student | |
# output: | |
# 0 James | |
# 1 Andrew | |
# 2 Mark |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# some code | |
for file_name in file_list: | |
if is_build_file(file_name): | |
break | |
else: # no break | |
make_built_file() | |
# something else here |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# generator expression for the square of all the numbers | |
squares = (num * num for num in numbers) | |
# where you would likely get a memory problem otherwise | |
with open('/some/number/file', 'r') as f: | |
squares = (int(num) * int(num) for num in f) | |
# do something with these numbers |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
numbers = [1, 2, 3, 4, 5, 6, 7] | |
squares = [] | |
for num in numbers: | |
squares.append(num * num) | |
# with a list compression | |
squares = [num * num for num in numbers] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
numbers = [1, 2, 3, 4, 5, 6, 7] | |
# squares of all the odd numbers | |
squares = [num * num for num in numbers if num % 2] | |
# times even numbers by 2 and odd numbers by 3 | |
mul = [num * 3 if num % 2 else num * 2 for num in numbers] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
dict(zip(names, random_numbers())) | |
# output: {'James': 992, 'Andrew': 173, 'Mark': 329} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
names = ('James', 'Andrew', 'Mark') | |
for i, name in zip(random_numbers(), names): | |
print i, name | |
# output: | |
# 288 James | |
# 884 Andrew | |
# 133 Mark |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<p> | |
My programming language of preference is python for the simple reason that I feel I write better code faster with it then I do with other languages. However also has a lot of nice tricks and idioms to do things well. And partly as a reminder to myself to use them, and partly because I thought this might be of general interest I have put together this collection of some of my favourite idioms. I am also putting this on <a href="https://gist.github.com/codefisher/9d7993ddbf404c505128">gist.github.com</a> so that anyone that wants to contribute there own things can, and I will try and keep this post up to date. | |
</p> | |
<h2>enumerate</h2> | |
<p> | |
A fairly common thing to do is loop over a list while also keeping track of what index we are up to. Now we could use a <code>count</code> variable, but python gives us a nicer syntax for this with the <code>enumerate()</code> function. | |
<script src="https://gist.github.com/codefisher/9d7993ddbf404c505128.js?file=enumerate.py"></script> | |
<h2>set</h2> | |
<p> | |
<a href="https://docs.python.org/2/library/sets.html"><code>set</code></a> is a useful little data structure, it is kind of like a list but each value in it is unique. There are some useful operations, besides creating a list of unique items, that we can do with it. For example let try some different ways of validating lists of input. | |
</p> | |
<script src="https://gist.github.com/codefisher/9d7993ddbf404c505128.js?file=set.py"></script> | |
<h2>Control statements</h2> | |
<h3>with</h3> | |
<p> | |
The <a href="https://docs.python.org/2/whatsnew/2.6.html#pep-343-the-with-statement"><code>with</code></a> statement is a useful when accessing anything that supports the context management protocol. Which means <code>open()</code> for example. It basically makes sure that any set up and clean up code, such as closing files, is run without having to worry about it. So for example to open a file: | |
</p> | |
<script src="https://gist.github.com/codefisher/9d7993ddbf404c505128.js?file=with.py"></script> | |
<h3>for ... else</h3> | |
<p> | |
This is a interesting bit of syntax, it allows you to run some code if the loop never reached the <code>break</code> statement. It basically replaces the need to keep a tracking variable for if you broke or not. Just looking over my code, here is a pseudo version of something I was doing. | |
</p> | |
<script src="https://gist.github.com/codefisher/9d7993ddbf404c505128.js?file=for_else.py"></script> | |
<h2>Conditional Expressions</h2> | |
<p> | |
Python allows for <a href="https://docs.python.org/3/reference/expressions.html#conditional-expressions">conditional expressions</a>, so instead of writing an <code>if .. else</code> with just one variable assignment in each branch, you can do the following: | |
</p> | |
<script src="https://gist.github.com/codefisher/9d7993ddbf404c505128.js?file=assignment.py"></script> | |
<p> | |
This one of the reasons I really like python. That above is very readable, compared to the teneray operator that looks like <code>a ? b : c</code> that exits in other languages. It always confuses me. | |
</p> | |
<h2>List Comprension</h2> | |
<p> | |
List comprehensions are supposed to replace building a list by looping and calling append. Compare the following. | |
</p> | |
<script src="https://gist.github.com/codefisher/9d7993ddbf404c505128.js?file=list_comprension.py"></script> | |
<p> | |
We can also make this more complicated, by adding in filtering or putting a conditional assignment in: | |
</p> | |
<script src="https://gist.github.com/codefisher/9d7993ddbf404c505128.js?file=list_comprension2.py"></script> | |
<h2>Generator</h2> | |
<p> | |
List comprehensions have one possible problem, and that is they build the list in memory right away. If your dealing with big data sets, that can be a big problem, but even with small lists, it is still extra overhead that might not be needed. If you are only going to loop over the results once it has no gain in building this list. So if you can give up being able to index into the result, and do other list operations, you can use a generator, which uses very similar syntax, but creates a lazy object, that computes nothing until you ask for a value. | |
</p> | |
<script src="https://gist.github.com/codefisher/9d7993ddbf404c505128.js?file=generator.py"></script> | |
<h2>yield</h2> | |
<p> | |
Generator expressions are great, but sometimes you want something, with similar properties, but not limited by the syntax that generators use. Enter the <code>yield</code> statement. So for example the below will create generator is an infinite series of random numbers. So as long as we continue to keep asking for another random number, it will happy supply one. | |
</p> | |
<script src="https://gist.github.com/codefisher/9d7993ddbf404c505128.js?file=random_numbers.py"></script> | |
<h2>dictionary comprehensions</h2> | |
<p> | |
One use for generators can be to build a dictionary, like in the first example below. This proved itself to be common enough that now there is even a new syntax for it. Both of these examples swap the keys and values of the dictionary. | |
</p> | |
<script src="https://gist.github.com/codefisher/9d7993ddbf404c505128.js?file=dictionary_comprehensions.py"></script> | |
<h2>zip</h2> | |
<p> | |
If you thought that generating an infinite number of random int was not that useful, well here I want to use it to show of another function that I like to use <code>zip()</code>. <code>zip()</code> takes a number of iterables, and joins the nth item of each into a tuple. So for example: | |
</p> | |
<script src="https://gist.github.com/codefisher/9d7993ddbf404c505128.js?file=names_random.py"></script> | |
<p> | |
So basically, it prints out all the names with a random number (from our random number generator from before) next to a name. Notice that <code>zip()</code> will stop as soon as it reaches the end of the shortest iterable. If that is not desired, the <a href="https://docs.python.org/2/library/itertools.html#itertools.izip_longest">itertools</a> module, has one that goes till the end of the longest. | |
</p> | |
<p> | |
We could also do something similar to get a <code>dict</code> of each name mapped to a random number like this. | |
</p> | |
<script src="https://gist.github.com/codefisher/9d7993ddbf404c505128.js?file=names_dict.py"></script> | |
<h2>itertools</h2> | |
<p> | |
I mentioned <a href="https://docs.python.org/2/library/itertools.html">itertools</a> before. If you have not looked at it before, it is worth reading thought, plus at the end there is a whole section of recipes on how to use the module to create even more interesting operators on iterables. | |
</p> | |
</p> | |
<h2>Collections</h2> | |
<p> | |
Python comes with a module that contains a number of container data types called Collections. Though I only want to look at two right, now it also has three more called <code>namedtuple()</code>, <code>deque</code> (a linked list like structure), and <code>OrderedDict</code>. | |
<h3>defaultdict</h3> | |
<p> | |
This is a data type that I use a fair bit. One useful case is when you are appending to lists inside a dictionary. If the your using a <code>dict()</code> you would need to check if the key exists before appending, but with <code>defaultdict</code> this is not needed. So for example. | |
</p> | |
<script src="https://gist.github.com/codefisher/9d7993ddbf404c505128.js?file=defaultdict.py"></script> | |
<p> | |
We could also count them like this. | |
</p> | |
<script src="https://gist.github.com/codefisher/9d7993ddbf404c505128.js?file=defaultdict_count.py"></script> | |
<h3>Counter</h3> | |
<p> | |
But the last example is kind of redundant, in that Collections already contains a class for doing this, called Counter. In this case, I need to first extract the second item from each <code>tuple</code>, for which I can use a generator expression. | |
</p> | |
<script src="https://gist.github.com/codefisher/9d7993ddbf404c505128.js?file=counter.py"></script> | |
<p> | |
Another, maybe better, example might be counting all the different lines that appear in a file. It becomes very simple. | |
</p> | |
<script src="https://gist.github.com/codefisher/9d7993ddbf404c505128.js?file=counter_file.py"></script> | |
<p> | |
If you enjoyed this post, or found it useful, please do leave a comment or share it on twitter etc. If people find this useful I will try and do some follow up posts explaining some things in more detail and with extra examples. | |
</p> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import random | |
def random_numbers(high=1000): | |
while True: | |
yield random.randint(0, high) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
colours = set(['red', 'green', 'blue', 'yellow', 'orange', 'black', 'white']) | |
# or using the newer syntax to declare the list. | |
input_values = {'red', 'black', 'pizza'} | |
# get a list off the valid colours | |
valid_values = input_values.intersection(colours) | |
print valid_values | |
# output set(['black', 'red']) | |
# get a list of the invalid colours | |
invalid_values = input_values.difference(colours) | |
print invalid_values | |
# output set(['pizza']) | |
# throw exception if there is something invalid | |
if not input_values.issubset(colours): | |
raise ValueError("Invalid colour: " + ", ".join(input_values.difference(colours))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
with open('/etc/passwd', 'r') as f: | |
print f.read() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment