This repo is based on my article How to be fancy with Python. It includes small Python tricks that will make your life much much easier. I hope they also help you become a better Python programmer. It is available as a jupyter notebook so you can clone and run it yourself. I also post these small tricks on Linkedin with my own hashtag so make sure to follow me there. Also, if you know some tricks of your own, submit a pull request and I'll be more than happy to include it.
Table of contents:
Things to include: posts from linkedin
TAB
to indent code
SHIFT + TAB
to unindent code
To comment a bunch of code, select it and press CONTROL + /
To surround something with quotation marks or brackets around something, press SHIFT + "
or SHIFT + (
Usually in Python, we loop over things like this:
To do the same with multiple lists, use zip
And if you need indexes by any chance you can just do
The best part about Python is that you can accomplish so much in so less code. Take list comprehensions for example. If you want to create a list of numbers in a certain range you can easily do it as follows:
You can also apply conditions on it very easily.
One practical example of this is to convert a number to its digits.
This concept of applying a function to every element of the list reminds me of map
Just like lists, there are comprehensions for dictionaries and generators as well. We'll talk about generators later.
Let's start with dictionaries. First let's learn about something called operator.itemgetter
. It retreives every element of the specified index.
Say you have a list of lists like this
and you want to get the first element of every inner list. You can do so as follows
Cool right?
Let me give you one more example. You can use it with the key
argument in the sorted function.
See how it works?
Okay back to dictionaries. A basic dictionary comprehension would be to map every element to an index.
A good practice for such dictionaries is to also create the reverse mapping. Trust me, you'll need it later.
We want to be able to do grouping in dictionaries like this:
However, we don't want to write so much nested code. We can just use default_dicts for this.
I bet those comprehensions were a lot to take in. Let's move onto lighter stuff for a while
The * operator can be used to repeat strings. For example
Now you probably don’t want to print “Python is cool” a whole lot of times but you should use it for something like this
The * operator can also be used to unpack iterables like lists
We can also use it with function arguments when we don't know the number of arguments in advance
*args
is used for variable number of arguments and **kwargs
is used for named arguments
Something else you can do with functions is create partial functions. What are they?
Suppose we have a function to calculate simple interest. We can set default values for some parameters (from right to left).
However, we cannot set the default value of just p in this way.
We can do so using a partial function. In a partial function, we set default values for some arguments, left to right and then use that as a function. Let’s set a default value for just p.
Although partials work from left to right, we can also skip parameters in between by using named arguments.
Partials are mainly used when you want to fix a few parameters and experiment with the rest.
Test driven development means you write tests and then you write code to pass those tests. You can write mini-tests in Python using assert.
For example, you might want to make sure the shape of a certain object is what you expect it to be.
You can also write a custom error message after a comma. Writing these mini-tests will be super helpful in making sure parts of your code work as expected. It will also help you debug things efficiently.
If you haven't already stopped using strings for paths, stop right now!
Check out this article for more examples and explanations.
Having said that, os.walk is a really fast way of traversing a directory recursively.
We can use the yield keyword instead of return keyword in Python to create a generator. The advantage of using a generator is that is generates things on the fly and forgets them. This saves memory.
We can also create them using comprehensions
Proof that you can iterate over generators only once.
To search for 5 in nums it had to generate numbers from 0 to 5. Now it starts from 6.
If we want to know all the attributes and methods related to a particular object, we can use dir()
We can also check for attributes directly using hasattr
And we can check the type of a variable using isinstance. This is usually done to ensure the parameter passed to a function is of the correct type.
If you want to run a bunch of functions through every element in your data, chaining them can get clunky. And writing multiple funciton calls everytime is not efficient. For this you can create a pipeline with inner functions.
When we define classes in python we write a lot of self.something = something
. If our class takes a lot of parameters, this can soon become clunky. And it is also boring to type. We can very easily write a function to do this for us and call it inside our init.
You can use these if you want to test something on all or any values of an iterable.
You can assign the same value to multiple variables in Python as follows.
You can check if an object is callable in python using the callable keyword.
Membership checking in Python lists is a linear operation. You can use a set instead to make it faster. Set's are implemented as hash maps and will give you constant time.
You can use Python's itertools library to write nested for loops in one line
You can flatten lists in Python using sum(). You can also do this recursively
When you create a dictionary in Python, you might be using an if statement to check if a key is present. If it's not, you set a default value for that key, otherwise, you do something else. You can do the same using the .setdefault() method available with dictionaries in Python. However, an even cleaner way to do this is to use defaultdicts. Check out this example and then read the documentation
When an inherited class has * args or ** kwargs in its constructor, we want to replace those arguments with the arguments of the class it inherits from when showing the doc page or the help page. This is not the default behavior in Python. You can use the delegates function from this article to do so.
We are not advised to use from library import * because it can import a lot of unnecessary things. To avoid this, when writing a library, we can define __ all __. Then, only the things contained in __ all __ will be exported.
Those were some Python tricks that I believe would help everyone. Herea are some more links to keep you busy. Keep learning.
- A walkthru on writing better functions in Python
- Upgrading python lists
- How to be fancy with OOP in Python
- Some neat Jupyter tricks.
- Primer on Python decorators
- Primer on meta-classes in Python
These things are referred from various sources but quite a few of them are referred from fastai walkthrus