The Rise and Fall of Hustle Culture

I saw an interesting post on LinkedIn the other day, and although I can’t find it again, it went something like this: 2010s: - 80 hour work weeks - “Rise and Grind” - You’re either hustling, or lazy…

Smartphone

独家优惠奖金 100% 高达 1 BTC + 180 免费旋转




Asterisks in Python

What They Are and How to Use Them

Most of us have encountered code like this (and some of us will be seeing it for their first time):

The first time I looked at it, I was quite puzzled. Isn’t asterisk (*) supposed to be the operator for multiplication? After some reading, I found out that * and **, when used before a variable, are known as prefix operators. They are also the representations of the infix operators for multiplication (*) and exponentiation (**), but we won’t be looking into that today.

We look exclusively into the prefix behavior of the operators, i.e., the * and ** operators that are used before a variable, as seen above. Two examples of usage of * are shown in the code above.
Asterisks can be used for the following purposes:

Even for the veterans (especially people who have recently migrated from Python 2 to 3), there are things to learn as Python has added new capabilities for these functions. Thus, I request everyone to go through the code blocks at least once to make sure you know the stuff.

When using a function call, we can use an asterisk (*) to unpack an iterable into the function call. For example:

The asterisk in the print function passes all the elements of the numbers list to the print function without us ever needing to know how many elements are present in the list. Quite useful when taking in user input as an iterable.

Here’s another useful (and a bit complicated) example:

The transpose function is first zipping all the rows (effectively turning them into column tuples) in the original matrix and then printing out their contents as a list of lists (matrix).

The ** operator does something similar, but with key-value pairs. It can be used to unpack a dictionary into a function call. Here’s an example:

As of Python 3.8, both * and ** can be used multiple times in a single function call:

The * operator can be used to capture an unlimited number of positional arguments given to a function. These arguments are captured into a tuple.

The function will take any number of positional arguments and convert them all into a single list:

Similarly, we can use the ** operator to capture any keyword arguments that are passed onto a given function.

The function above will capture the tag name and any number of attributes that you throw at it and then convert it into a well-formatted HTML tag. Here’s an example usage:

Arguments with names are called keyword arguments, and the other arguments are called positional arguments. Let’s first understand the difference between keyword and positional arguments. This part is a short detour before going into the primary use of asterisks. Feel free to skip this if you are already familiar with this.

Positional arguments are arguments passed onto a function that needs to be included in the proper position or order. I.e., the first positional argument must be provided first, followed by the second positional argument, and so on.

An example can be seen in Python’s complex function. The order in which you provide the numbers determines if they are real or imaginary parts. The real part needs to be provided as the first argument, followed by the imaginary part. For example,

Here, the relative positions of the arguments determine what the output will be, and thus, they are called positional arguments.

A keyword argument is provided as a key-value pair separated by an equals (=) sign. The general form of such arguments is function(keyword=value) .

Python’s complex function can also accept two keyword arguments, called real and imag. Keyword arguments are provided to functions after any required positional arguments. But the order of keyword arguments is not taken does not matter. Note this in the example:

Both the orders produce the same number. Now that we are clear about keyword and positional arguments let’s move on to the main topic.

Keyword-Only arguments are arguments that can only be specified by using keywords (they can’t be positionally specified). As we saw above, we can define the arguments real and imag of the complex function both by using keywords and also positionally.

Arguments defined after the * in a function will behave as keyword-only arguments. We can often have a combination of positional and keyword-only arguments in functions that we create. For example:

The last two arguments defined (val and truth) are keyword-only as they are defined after the asterisk (*) argument. They can not be assigned positionally. Trying to input the value 78 positionally for val will produce the following error:

Thus, we can use the above template to create functions that take in positional as well as keyword-only arguments.

Similarly, we can use just the asterisk in the beginning to create functions that do not take any positional or keyword arguments but take only keyword-only arguments.

If we try to just pass on any argument without the keyword, it will result in an error.

An excellent example of this is Python’s built-in sorted function. If you use help on sorted you can see this:

The arguments key and reverse are keyword-only arguments used in the function that can’t be passed on without a keyword.

Python 3 added this functionality, and it allows us to unpack the contents of a tuple into variables using the * operator.

It is also possible to use multiple asterisks by nested tuple unpacking, as shown below:

Say you have the given function:

It can be quite easily modified to:

which is more readable and efficient (compared to the two calls to list). The important thing is this method is not limited to creating lists. We can similarly use the * operator to create tuples and sets. Here is an example:

Note: It wasn’t that easy to accomplish the last thing we did in a single line. However, one had to depend on this obscure method that I found out some time ago:

Similar to what * does for lists or tuples, ** does the same for dictionaries. The same PEP448 introduced a better and shorter way of dumping key-value pairs from dictionaries in Python using **.

Using ** also allows us to add/update values while we copy a dictionary. For example:

Python’s * and ** aren’t just syntactic sugar used by fancy people. Some things that they do can be achieved by other means, but the alternatives generally tend to be cumbersome and resource inefficient. Whereas, there are some things (Keyword-Only arguments, passing unlimited arguments to functions) that can not be achieved by other means.

If you are new to Python or are concerned about how to remember all these uses, don’t be! These operators have different applications and you aren’t required to memorize all of them. Getting a feel for when you might be using one of them is generally enough. You can always use this article as a cheat sheet and refer back as many times as you like.

If you liked the article, give a clap (it’s free, and you can clap up to 50 times!), share, recommend, and respond to it. Your claps, shares, and responses encourage me to write more such articles.

Add a comment

Related posts:

Brutalismo y Nuevo Brutalismo.

El brutalismo nace del movimiento formalismo racionalista. El término Brutalismo surge del Béton Brut de Le Corbusier, que caracteriza a la Unité d’Habitation de Marsella. Este movimiento tuvo su…

8 Useful Tools For Crypto Trading

If you have invested in Cryptocurrencies, you know how thrilling the experience could be while trading, and sometimes it can be a hassle. You’ll need to start maintaining track of your investments…

How to Send the Perfect Email for an Event Invitation

There are certain things you can do when writing an event invitation email to maximize your chances of it getting opened and read. It would be a shame to spend so much time and energy on your event…