Posted on Leave a comment

string.join(list) vs list.join(string) | Why Python’s Creators Chose The Former

If you’re like me, you may have asked yourself the following question:

Why is it string.join(list) instead of list.join(string) in Python? 🙄

The join method works with any iterable, not just with lists. Therefore, you’d have to implement it in hundreds of classes instead of just one (in the string class). Additionally, join() works only on a string delimiter and with an iterable of strings. Thus, it’s specific to strings and shouldn’t be allowed to be applied on, say, a list of integers.

Let’s divide the world into REALITY and FANTASY.

REALITY: You probably know the string.join(list) method in Python to concatenate all strings in the list using string as a delimiter:

# REALITY:
lst = ['a', 'b', 'c']
print('-'.join(lst))
# a-b-c

FANTASY: Many coders find this confusing, wouldn’t it be more intuitive to use list.join(string) rather than string.join(list)?

# FANTASY WORLD:
lst = ['a', 'b', 'c']
print(lst.join('-'))
# a-b-c

This option of joining a list to a string would feel more object-oriented: you want to join the list and not the string, after all!

So, what are the thought processes behind Python’s creators? Why did they decide to create a join() method on the string rather than the list type?

In this article, I’ve compiled the pro and con arguments from various sources. You can find a detailed list of the sources below.

Argument 1: One Method to Join ‘Em All

You can join any iterable such as a list, tuple, dictionary, or set. But the delimiter must be a string. Thus, you have two options:

  • Require that each iterable implements its own join method (such as __str__).
  • Implement only one join method that works on each iterable.

The latter is far less work for the language creators, and less confusing for the programmer.

# FANTASY WORLD:
['a', 'b', 'c'].join('-')
('a', 'b', 'c').join('-')
{'a', 'b', 'c'}.join('-')
...
# a-b-c

In the fantasy world, you have many implementations of basically the same method.

# FANTASY WORLD:
['a', 'b', 'c'].join('-')
('a', 'b', 'c').join('-')
{'a', 'b', 'c'}.join('-')
...
# a-b-c

This would be confusing as every single iterable must implement the same method. Either there would be a lot of redundant code, or the method must be implemented on the iterable object which leads us to the next argument:

Argument 2: Explicit is Better Than Implicit

If you type into your Python shell the two words import this, it’ll print the “Zen of Python”:

The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
...

Go ahead and try it yourself, I’ll wait:

The join() method can only join iterables if they contain strings:

lst = [1, 'b', 'c']
print('-'.join(lst))
# TypeError: sequence item 0: expected str instance, int found

Python will throw a TypeError, if you try to join an iterable that contains at least one non-string element.

Say, we live in FANTASY WORLD and the iterable type implements a join method that’s valid (among others) for all container types such as lists. This would be the only alternative that makes sense and doesn’t add lots of redundant code to the Python library.

This would mean that all iterables containing arbitrary elements could be joined to a string! Even if the elements in the iterable are not of type string. Even if they are absurd data types you created just to confuse Python.

You may ask: so what? But the problem is that Python would have to use an implicit string conversion scheme in case the objects are not of type string. The default string representation is often unreadable or not suitable to appear in a concatenation. Surely, this would add lots and lots of confusion.

For example: what does it, semantically, mean to join a list of integers? Adding them? Concatenating the string representations? Averaging them? There’s no clear answer and any implicit choice would lead to confusion. Explicit is better than implicit!

Note: There’s another problem with implementing a join method on the iterable level! The iterable is not a type but an interface for any type that defines an __iter__ method. Thus, it comes back to requiring all iterables to implement their custom join which is complicated and messy.

Argument 3: Unexpected Dependency of Iterables From String and Unicode

Using list.join() was actually proposed by Skip Montanaro, one of Python’s creators:

On Fri, 11 Jun 1999, Skip Montanaro wrote: It occurred to me just a few minutes after sending my previous message that
it might make sense to make string.join a method for lists and tuples.
They'd obviously have to make the same type checks that string.join does.
as in:
['spam!', 'eggs!'].join() 'spam! eggs!'
?

But David replied that he didn’t like the implications from the generalization of join(): the reduce() function:

I like the notion, but I think it would naturally migrate towards
genericity, at which point it might be called "reduce", so that: ['spam!', 'eggs!'].reduce() 'spam!eggs!' ['spam!', 'eggs!'].reduce(' ') 'spam! eggs!' [1,2,3].reduce()
6 # 1 + 2 + 3 [1,2,3].reduce(10)
26 # 1 + 10 + 2 + 10 + 3 note that string.join(foo) == foo.reduce(' ')
and string.join(foo, '') == foo.reduce()
--david

You can see that this leads to unclear semantics if you have a list of integers. Do we reduce a list of integers by summing them up or concatenating them? What if you pass the value 10 as a separator?

Guido, Python’s benevolent dictator for life, replied (highlights by me):

>>> On Fri, 11 Jun 1999, Skip Montanaro wrote:
>>> It occurred to me just a few minutes after sending my previous message that
>>> it might make sense to make string.join a method for lists and tuples.
>>> They'd obviously have to make the same type checks that string.join does.
>>> as in:
>>> ['spam!', 'eggs!'].join()
>>> 'spam! eggs!' Note that this is not as powerful as string.join(); the latter works
on any sequence, not just on lists and tuples. (Though that may not
be a big deal.) I also find it slightly objectionable that this is a general list
method but only works if the list contains only strings; Dave Ascher's
generalization to reduce() is cute but strikes me are more general
than useful, and the name will forever present a mystery to most
newcomers. Perhaps join() ought to be a built-in function?
--Guido van Rossum (home page: http://www.python.org/~guido/)

To summarize this conversation, Guido had two counter arguments:

  • The join() method works on all iterables and not only on lists and tuples.
  • The method must be a general list method but works only if the list contains strings.

The final note is interesting though: join() could have been built-in function, too!

Where to Go From Here?

Enough theory, let’s get some practice!

To become successful in coding, you need to get out there and solve real problems for real people. That’s how you can become a six-figure earner easily. And that’s how you polish the skills you really need in practice. After all, what’s the use of learning theory that nobody ever needs?

Practice projects is how you sharpen your saw in coding!

Do you want to become a code master by focusing on practical code projects that actually earn you money and solve problems for people?

Then become a Python freelance developer! It’s the best way of approaching the task of improving your Python skills—even if you are a complete beginner.

Join my free webinar “How to Build Your High-Income Skill Python” and watch how I grew my coding business online and how you can, too—from the comfort of your own home.

Join the free webinar now!

Sources

I combined web resources, email communications, and my own thoughts to write this comprehensive guide. I’m confident that the tutorial covers the real sources—but we’ll never know for 100%, don’t we?

  1. https://stackoverflow.com/questions/493819/why-is-it-string-joinlist-instead-of-list-joinstring
  2. https://www.edureka.co/community/3899/python-join-why-is-string-join-list-instead-list-join-string
  3. https://www.edureka.co/community/12487/python-join-why-is-string-join-list-instead-list-join-string
  4. https://intellipaat.com/community/225/python-join-why-is-it-string-join-list-instead-of-list-join-string
  5. https://www.wyzant.com/resources/answers/689501/python-join-why-is-it-string-join-list-instead-of-list-join-string
  6. https://www.quora.com/Why-is-it-string-join-list-instead-of-list-join-string
  7. https://mail.python.org/pipermail/python-dev/1999-June/095366.html
Posted on Leave a comment

How to Use Python’s Join() on a List of Objects (Not Strings)?

The most Pythonic way to concatenate a list of objects is the expression ''.join(str(x) for x in lst) that converts each object to a string using the built-in str(...) function in a generator expression. You can concatenate the resulting list of strings using the join() method on the empty string as a delimiter. The result is a single string value that’s the concatenation of the objects’ string representations.

Writing Pythonic code is at the heart of being an effective coder—and if you choose the wrong ways of solving a problem, you’ll open yourself up for criticism and struggles throughout your programming career. So, what’s the most Pythonic way of solving the following problem?

Problem: Given a list of objects. How to concatenate the string representations of those objects?

Example: You have the following list of objects.

class Obj: def __init__(self, val): self.val = val def __str__(self): return str(self.val) lst = [Obj(0), Obj(1), Obj(2), Obj(4)]

You want to obtain the following result of concatenated string representations of the objects in the list.

0124

Want to play? Run the following interactive code shell:

Exercise: Run the interactive code snippet. Which method do you like most?

Method 1: Join + List Comprehension + Str

This method uses three Python features.

First, the string.join(iterable) method expects an iterable of strings as input and concatenates those using the string delimiter. You can read more about the join() function in our ultimate blog guide.

Second, list comprehension is the Pythonic way to create Python lists in a single line. You use the syntax [expression + statement].

  • In the expression, you define how each element should be modified before adding it into a new list.
  • In the statement, you define which elements to modify and add to the list in the first place.

You can read more about list comprehension in the detailed Finxter guide on the topic.

Third, the str(...) function converts any Python object into a string representation. If you define your custom objects, you should overwrite the __str__() method to customize how exactly your objects are represented as strings.

Combining those three features results in the following simple solution to concatenate the string representations of a list of objects.

print(''.join([str(x) for x in lst]))
# 0124

But there’s a slight simplification lurking around. Read on to learn which!

Method 2: Join + Generator Expression + Str

The previous method has shown a quite effective way to concatenate the string representations of some objects using the join() function of Python strings. As the join() function expects a list of strings, you need to convert all objects x into plain strings using the str(x) function.

Concatenate string representations of list of objects with join() function and generator expression.

However, there’s no need to create a separate list in which you store the string representations. Converting one object at a time is enough because the join function needs only an iterable as an input—and not necessarily a Python list. (All Python lists are iterables but not all iterables are Python lists.)

To free up the memory, you can use a generator expression (without the square brackets needed to create a list):

print(''.join(str(x) for x in lst))
# 0124

In contrast to Method 1, this ensures that the original list does not exist in memory twice—once as a list of objects and once as a list of string represenations of those exact objects. Therefore, this method can be considered the most Pythonic one.

Method 3: Join + Generator Expression + Custom String Representation

A slight modification of the previous version is to use your own custom string representation—rather than the one implemented by the __str__ method.

print(''.join(str(x.val) for x in lst))
# 0124

This gives you some flexibility how you can represent each object for your specific application.

Method 4: Join + Map + Lambda

The map() function transforms each tuple into a string value, and the join() method transforms the collection of strings to a single string—using the given delimiter '--'. If you forget to transform each tuple into a string with the map() function, you’ll get a TypeError because the join() method expects a collection of strings.

Lambda functions are anonymous functions that are not defined in the namespace (they have no names). The syntax is: lambda <argument name(s)> : <return expression>. You’ll see an example next, where each function argument is mapped to its string representation.

print(''.join(map(lambda x: str(x), lst)))
# 0124

This method is a more functional programming style—and some Python coders prefer that. However, Python’s creator Guido van Rossum preferred list comprehension over functional programming because of the readability. That’s why Methods 1-3 should be preferred in general.

If you absolutely want to take functional programming, use the next version:

Method 5: Join + Map + Str

There’s no need to use the lambda function to transform each list element to a string representation—if there’s a built-in function that’s already doing exactly this: the str(...) function you’ve already seen!

print(''.join(map(str, lst)))
# 0124

Because of its conciseness and elegance, passing the str function name as a function argument into the map function is the most Pythonic functional way of solving this problem.

Method 6: Simple Loop + Str (Naive)

Sure, you can also solve the problem in a non-Pythonic way by using a simple for loop and build up the string:

s = ''
for x in lst: s += str(x)
print(s)
# 0124

But that’s not only less concise, it’s also less efficient. So, a master coder in Python would never use such a method!

If you want to become a Python master coder, check out my free in-depth Python email course. Join tens of thousands of ambitious Python coders and become a Python master the automatic way!

Where to Go From Here?

Enough theory, let’s get some practice!

To become successful in coding, you need to get out there and solve real problems for real people. That’s how you can become a six-figure earner easily. And that’s how you polish the skills you really need in practice. After all, what’s the use of learning theory that nobody ever needs?

Practice projects is how you sharpen your saw in coding!

Do you want to become a code master by focusing on practical code projects that actually earn you money and solve problems for people?

Then become a Python freelance developer! It’s the best way of approaching the task of improving your Python skills—even if you are a complete beginner.

Join my free webinar “How to Build Your High-Income Skill Python” and watch how I grew my coding business online and how you can, too—from the comfort of your own home.

Join the free webinar now!

Posted on Leave a comment

Python Join List of DataFrames

To join a list of DataFrames, say dfs, use the pandas.concat(dfs) function that merges an arbitrary number of DataFrames to a single one.

When browsing StackOverflow, I recently stumbled upon the following interesting problem. By thinking about solutions to those small data science problems, you can improve your data science skills, so let’s dive into the problem description.

Problem: Given a list of Pandas DataFrames. How to merge them into a single DataFrame?

Example: You have the list of Pandas DataFrames:

df1 = pd.DataFrame({'Alice' : [18, 'scientist', 24000], 'Bob' : [24, 'student', 12000]})
df2 = pd.DataFrame({'Alice' : [19, 'scientist', 25000], 'Bob' : [25, 'student', 11000]})
df3 = pd.DataFrame({'Alice' : [20, 'scientist', 26000], 'Bob' : [26, 'student', 10000]}) # List of DataFrames
dfs = [df1, df2, df3]

Say, you want to get the following DataFrame:

 Alice Bob
0 18 24
1 scientist student
2 24000 12000
0 19 25
1 scientist student
2 25000 11000
0 20 26
1 scientist student
2 26000 10000

You can try the solution quickly in our interactive Python shell:

Exercise: Print the resulting DataFrame. Run the code. Which merging strategy is used?

Method 1: Pandas Concat

This is the easiest and most straightforward way to concatenate multiple DataFrames.

import pandas as pd df1 = pd.DataFrame({'Alice' : [18, 'scientist', 24000], 'Bob' : [24, 'student', 12000]})
df2 = pd.DataFrame({'Alice' : [19, 'scientist', 25000], 'Bob' : [25, 'student', 11000]})
df3 = pd.DataFrame({'Alice' : [20, 'scientist', 26000], 'Bob' : [26, 'student', 10000]}) # list of dataframes
dfs = [df1, df2, df3] df = pd.concat(dfs)

This generates the following output:

print(df) ''' Alice Bob
0 18 24
1 scientist student
2 24000 12000
0 19 25
1 scientist student
2 25000 11000
0 20 26
1 scientist student
2 26000 10000 '''

The resulting DataFrames contains all original data from all three DataFrames.

Method 2: Reduce + DataFrame Merge

The following method uses the reduce function to repeatedly merge together all dictionaries in the list (no matter its size). To merge two dictionaries, the df.merge() method is used. You can use several merging strategies—in the example, you use "outer":

import pandas as pd df1 = pd.DataFrame({'Alice' : [18, 'scientist', 24000], 'Bob' : [24, 'student', 12000]})
df2 = pd.DataFrame({'Alice' : [19, 'scientist', 25000], 'Bob' : [25, 'student', 11000]})
df3 = pd.DataFrame({'Alice' : [20, 'scientist', 26000], 'Bob' : [26, 'student', 10000]}) # list of dataframes
dfs = [df1, df2, df3] # Method 2
from functools import reduce
df = reduce(lambda df1, df2: df1.merge(df2, "outer"), dfs)

This generates the following output:

print(df) ''' Alice Bob
0 18 24
1 scientist student
2 24000 12000
3 19 25
4 25000 11000
5 20 26
6 26000 10000 '''

You can find a discussion of the different merge strategies here. If you’d use the parameter "inner", you’d obtain the following result:

 Alice Bob
0 scientist student

Where to Go From Here?

Enough theory, let’s get some practice!

To become successful in coding, you need to get out there and solve real problems for real people. That’s how you can become a six-figure earner easily. And that’s how you polish the skills you really need in practice. After all, what’s the use of learning theory that nobody ever needs?

Practice projects is how you sharpen your saw in coding!

Do you want to become a code master by focusing on practical code projects that actually earn you money and solve problems for people?

Then become a Python freelance developer! It’s the best way of approaching the task of improving your Python skills—even if you are a complete beginner.

Join my free webinar “How to Build Your High-Income Skill Python” and watch how I grew my coding business online and how you can, too—from the comfort of your own home.

Join the free webinar now!

Posted on Leave a comment

How to Get a List Slice with Arbitrary Indices in Python?

To extract elements with specific indices from a Python list, use slicing list[start:stop:step]. If you cannot use slicing because there’s no pattern in the indices you want to access, use the list comprehension statement [lst[i] for i in indices], assuming your indices are stored in the variable indices.

People always want to know the most Pythonic solution to a given problem. This tutorial shows you the most Pythonic solution(s) to the following problem:

Problem: How to extract elements with specific indices from a Python list?

Example: You’ve got the following elements.

lst = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']

You want to create a new list of elements with indices = [0, 2, 6] in the original list:

['a', 'c', 'g']
How to get elements with specific indices from a Python list?

You can get a quick overview of the most Pythonic methods in our interactive Python shell:

Exercise: Run the code shell. Now, try to access the element with index 7 as well in each of the given methods!

Method 1: List Comprehension

A simple, readable, and efficient way is to use list comprehension that’s a compact way of creating lists. The simple formula is [expression + context].

  • Expression: What to do with each list element?
  • Context: What elements to select? The context consists of an arbitrary number of for and if statements.

Here’s the code that creates a new list that contains the elements at specific indices (e.g., 0, 2, and 6) in the original list:

lst = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
indices = [0, 2, 6]
out = [lst[i] for i in indices]
print(out)
# ['a', 'c', 'g']

In most cases, this will be the best solution because you don’t need any library and it’s still short and readable. However, if you need to do this multiple times, it may be better to import the NumPy library:

Method 2: NumPy Array Indexing

Python’s library for numerical computations, NumPy, is one of the most powerful tools in your toolbelt—especially if you work as a data scientist. Here’s how you can use NumPy to access arbitrary indices, given a sequence of specific indices:

import numpy as np
lst = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
a = np.array(lst)
indices = [0, 2, 6] out = a[indices]

The output is:

print(out)
# ['a' 'c' 'g']

You see that NumPy indexing is far more powerful than Python indexing—it allows you to use arbitrary sequences as indices. Especially, if you need to do multiple of those numerical operations, you may want to import the NumPy library once and gain much in readability and conciseness.

Related resources:

Method 3: Itemgetter

The following method can be seen sometimes—using the itemgetter function from the operator module:

from operator import itemgetter
lst = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
indices = [0, 2, 6]
out = list(itemgetter(*indices)(lst))
print(out)
# ['a', 'c', 'g']

The code performs the following steps:

  • Call the itemgetter() function and pass the arguments 0, 2, and 6. We use the asterisk operator * to unpack the values from the indices variable into the itemgetter() function. Learn more about the asterisk operator in our detailed blog article.
  • This returns a new itemgetter function object.
  • Call the new itemgetter function object by passing the original list lst.
  • The new itemgetter function will now get a tuple of the items at positions 0, 2, and 6 in the original list lst.
  • Convert the tuple to a list using the list(...) built-in Python function.

Method 4: Manual Indices

Just for comprehensibility, I also want to point out the “naive” way of accessing a few elements in the original list and put them into a new list:

lst = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
out = [lst[0], lst[2], lst[6]]
print(out)
# ['a', 'c', 'g']

This is a perfectly valid and efficient approach if you have only a few elements to access. For more than, say, five indices, it quickly becomes unhandy though.

Method 5: Simple Loop

Here’s another approach that’s often used by coders who come from other programming languages such as Java or C++: using simple loops.

lst = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
indices = [0, 2, 6]
out = []
for i in indices: out.append(lst[i])
print(out)
# ['a', 'c', 'g']

While there’s nothing wrong with this, it looks somehow “brutal” to an advanced coder. If you’d use this method, it would be like shouting into the world that you’re not a very sophisticated Python coder. 😉

Nothing wrong with that—don’t get me wrong! But if you want to increase your level of sophistication in Python, join my free email academy with many Python email courses that will sharpen your skills! Have I already said that it’s free?

Join Python Email Academy!

Where to Go From Here?

Enough theory, let’s get some practice!

To become successful in coding, you need to get out there and solve real problems for real people. That’s how you can become a six-figure earner easily. And that’s how you polish the skills you really need in practice. After all, what’s the use of learning theory that nobody ever needs?

Practice projects is how you sharpen your saw in coding!

Do you want to become a code master by focusing on practical code projects that actually earn you money and solve problems for people?

Then become a Python freelance developer! It’s the best way of approaching the task of improving your Python skills—even if you are a complete beginner.

Join my free webinar “How to Build Your High-Income Skill Python” and watch how I grew my coding business online and how you can, too—from the comfort of your own home.

Join the free webinar now!

Posted on Leave a comment

How to Convert a List to a NumPy Array?

To convert a Python list to a NumPy array, use either of the following two methods:

  1. The np.array() function that takes an iterable and returns a NumPy array creating a new data structure in memory.
  2. The np.asarray() function that takes an iterable as argument and converts it to the array. The difference to np.array() is that np.asarray() doesn’t create a new copy in memory if you pass a NumPy array. All changes made on the original array are reflected on the NumPy array.

Exercise: Create array b from array a using both methods. Then change a value in array a. What happens at array b?

NumPy vs Python Lists

The Python built-in list data type is powerful. However, the NumPy array has many advantages over Python lists. What are they?

Advantages NumPy Advantages Python Lists
Multi-dimensional Slicing Library-Independent
Broadcasting Functionality Intuitive
Processing Speed Less Complicated
Memory Footprint Heterogeneous List Data Allowed
Many Convenience Methods Arbitrary Data Shape (Non-Square Matrix)

To read more about the advantages of a NumPy array over a Python list, read my detailed blog tutorial.

How to Convert a 1D Python List to a NumPy Array?

Problem: Given a one-dimensional Python list. How to convert it to a NumPy array?

Example: You have the following 1D Python list of integers.

lst = [0, 1, 100, 42, 13, 7]

You want to convert it into a NumPy array.

array([ 0, 1, 100, 42, 13, 7])

Method 1: np.array(…)

The simplest way to convert a Python list to a NumPy array is to use the np.array() function that takes an iterable and returns a NumPy array.

import numpy as np
lst = [0, 1, 100, 42, 13, 7]
print(np.array(lst))

The output is:

# [ 0 1 100 42 13 7]

This creates a new data structure in memory. Changes on the original list are not visible to the variable that holds the NumPy array:

lst = [0, 1, 100, 42, 13, 7]
a = np.array(lst)
lst.append(999)
print(a)
# [ 0 1 100 42 13 7]

The element 999 which is now part of list lst is not part of array a.

Method 2: np.asarray(…)

An alternative is to use the np.asarray() function that takes one argument—the iterable—and converts it to the NumPy array. The difference to np.array() is that it doesn’t create a new copy in memory IF you pass a NumPy array. All changes made on the original array are reflected on the NumPy array! So be careful.

lst = [0, 1, 100, 42, 13, 7]
a = np.array(lst)
b = np.asarray(a)
a[0] = 99
print(b)
# [ 99 1 100 42 13 7]

The array b is created using the np.asarray() function, so if you change a value of array a, the change will be reflected on the variable b (because they point to the same object in memory).

[Video] How to Convert a List of Lists to a NumPy Array?

Convert List of Lists to 2D Array

Problem: Given a list of lists in Python. How to convert it to a 2D NumPy array?

Example: Convert the following list of lists

[[1, 2, 3], [4, 5, 6]]

into a NumPy array

[[1 2 3] [4 5 6]]

Solution: Use the np.array(list) function to convert a list of lists into a two-dimensional NumPy array. Here’s the code:

# Import the NumPy library
import numpy as np # Create the list of lists
lst = [[1, 2, 3], [4, 5, 6]] # Convert it to a NumPy array
a = np.array(lst) # Print the resulting array
print(a) '''
[[1 2 3] [4 5 6]] '''

Try It Yourself: Here’s the same code in our interactive code interpreter:

<iframe height="700px" width="100%" src="https://repl.it/@finxter/numpylistoflists?lite=true" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe>

Hint: The NumPy method np.array() takes an iterable as input and converts it into a NumPy array.

Convert a List of Lists With Different Number of Elements

Problem: Given a list of lists. The inner lists have a varying number of elements. How to convert them to a NumPy array?

Example: Say, you’ve got the following list of lists:

[[1, 2, 3], [4, 5], [6, 7, 8]]

What are the different approaches to convert this list of lists into a NumPy array?

Solution: There are three different strategies you can use. (source)

(1) Use the standard np.array() function.

# Import the NumPy library
import numpy as np # Create the list of lists
lst = [[1, 2, 3], [4, 5], [6, 7, 8]] # Convert it to a NumPy array
a = np.array(lst) # Print the resulting array
print(a) '''
[list([1, 2, 3]) list([4, 5]) list([6, 7, 8])] '''

This creates a NumPy array with three elements—each element is a list type. You can check the type of the output by using the built-in type() function:

>>> type(a)
<class 'numpy.ndarray'>

(2) Make an array of arrays.

# Import the NumPy library
import numpy as np # Create the list of lists
lst = [[1, 2, 3], [4, 5], [6, 7, 8]] # Convert it to a NumPy array
a = np.array([np.array(x) for x in lst]) # Print the resulting array
print(a) '''
[array([1, 2, 3]) array([4, 5]) array([6, 7, 8])] '''

This is more logical than the previous version because it creates a NumPy array of 1D NumPy arrays (rather than 1D Python lists).

(3) Make the lists equal in length.

# Import the NumPy library
import numpy as np # Create the list of lists
lst = [[1, 2, 3], [4, 5], [6, 7, 8, 9]] # Calculate length of maximal list
n = len(max(lst, key=len)) # Make the lists equal in length
lst_2 = [x + [None]*(n-len(x)) for x in lst]
print(lst_2)
# [[1, 2, 3, None], [4, 5, None, None], [6, 7, 8, 9]] # Convert it to a NumPy array
a = np.array(lst_2) # Print the resulting array
print(a) '''
[[1 2 3 None] [4 5 None None] [6 7 8 9]] '''

You use list comprehension to “pad” None values to each inner list with smaller than maximal length.

Related Articles

Where to Go From Here?

Enough theory, let’s get some practice!

To become successful in coding, you need to get out there and solve real problems for real people. That’s how you can become a six-figure earner easily. And that’s how you polish the skills you really need in practice. After all, what’s the use of learning theory that nobody ever needs?

Practice projects is how you sharpen your saw in coding!

Do you want to become a code master by focusing on practical code projects that actually earn you money and solve problems for people?

Then become a Python freelance developer! It’s the best way of approaching the task of improving your Python skills—even if you are a complete beginner.

Join my free webinar “How to Build Your High-Income Skill Python” and watch how I grew my coding business online and how you can, too—from the comfort of your own home.

Join the free webinar now!

Posted on Leave a comment

Python Join List Slice

To join and replace all strings in a list lst between start index 1 and end index 5, use the one-liner lst[1:5] = [''.join(lst[1:5])]. This solution is based on slice assignment that selects the slice you want to replace on the left and the values to replace it on the right side of the assignment.

Problem: Given a list of strings. How to join all strings in a given list slice and replace the slice with the joined string?

Example:You start with the following list:

lst = ['i', 'l', 'o', 'v', 'e', 'u']

You want to join the slice ['l', 'o', 'v', 'e'] with start index 1 and end index 4 (included) and replace it in the list to obtain the result:

# Output: ['i', 'love', 'u']

You can get a quick overview of all three methods in the following interactive Python shell. If you’re short on time—method 1 using slice assignment is the most Pythonic solution!

Exercise: Modify the code so that only elements with start index 2 and end index 4 (included) are replaced by the joined string!

Method 1: Slice Assignment

Slice assignment is a little-used, beautiful Python feature to replace a slice with another sequence. Select the slice you want to replace on the left and the values to replace it on the right side of the equation.

Here’s how you can join and replace all strings in a list slice (between indices 1 and 5) in a single line of Python code:

# Method 1: Slice Assignments
lst = ['i', 'l', 'o', 'v', 'e', 'u']
lst[1:5] = [''.join(lst[1:5])]
print(lst)
# ['i', 'love', 'u']

The one-liner lst[1:5] = [''.join(lst[1:5])] performs the following steps:

  • Select the slice to be replaced on the left-hand side of the equation with lst[1:5]. Read more about slicing on my Finxter blog tutorial.
  • Create a list that replaces this slice on the right-hand side of the equation with [...].
  • Select the slice of string elements to be joined together ('l', 'o', 'v', 'e') with lst[1:5].
  • Pass this slice into the join function to create a new string with all four characters 'love'.
  • This string replaces all four selected positions in the original list.

If you love the power of Python one-liners, check out my new book with the same name “Python One-Liners” on Amazon (published in 2020 with San Francisco’s high-quality NoStarch publishing house).

Method 2: List Concatenation + Slicing + Join

A simpler but quite readable method is to use simple list concatenation. Read more on my Finxter blog tutorial to master all different ways to concatenate lists in Python.

# Method 2: List Concatenation + Join
lst = ['i', 'l', 'o', 'v', 'e', 'u']
lst = lst[:1] + [''.join(lst[1:5])] + lst[5:]
print(lst)
# ['i', 'love', 'u']

This approach uses three slicing calls to select (or create) three lists. Then, it glues them together using the + operator. This approach has the slight disadvantage that a new list is created in memory (rather than working on the old list). Thus, it’s slightly less memory-friendly as the first method.

Method 3: Naive

This method is what a non-Python coder (maybe coming from Java or C++) would use. It’s NOT the recommended way though.

# Method 3: Naive
lst = ['i', 'l', 'o', 'v', 'e', 'u']
new = ''
for i in range(1,5): new += lst[i]
lst = lst[:1] + [new] + lst[5:]
print(lst)
# ['i', 'love', 'u']

Instead of selecting the slice of strings to be joined using slicing, the coder creates a string variable new and adds one character at-a-time. This is very inefficient as many different strings are created—each time one adds one more character to the string.

Where to Go From Here?

Enough theory, let’s get some practice!

To become successful in coding, you need to get out there and solve real problems for real people. That’s how you can become a six-figure earner easily. And that’s how you polish the skills you really need in practice. After all, what’s the use of learning theory that nobody ever needs?

Practice projects is how you sharpen your saw in coding!

Do you want to become a code master by focusing on practical code projects that actually earn you money and solve problems for people?

Then become a Python freelance developer! It’s the best way of approaching the task of improving your Python skills—even if you are a complete beginner.

Join my free webinar “How to Build Your High-Income Skill Python” and watch how I grew my coding business online and how you can, too—from the comfort of your own home.

Join the free webinar now!

Posted on Leave a comment

Python Join List Pairs

Given a list of strings. Join the first with the second string, the second with the third, and so on. The one-liner [lst[i] + lst[i+1] for i in range(0, len(lst), 2)] solves the problem by using the range function to iterate over every other index i=0, 2, 4, 5, ... to concatenate the i-th and the i+1-th elements in a list comprehension expression with lst[i] + lst[i+1].

You may already know the normal join function in Python:

Intro: Python Join

Problem: Given a list of elements. How to join the elements by concatenating all elements in the list?

Example: You want to convert list ['learn ', 'python ', 'fast'] to the string 'learn python fast'.

Quick Solution: to convert a list of strings to a string, do the following.

  • Call the ''.join(list) method on the empty string '' that glues together all strings in the list and returns a new string.
  • The string on which you call the join method is used as a delimiter between the list elements.
  • If you don’t need a delimiter, just use the empty string ''.

Code: Let’s have a look at the code.

lst = ['learn ', 'python ', 'fast']
print(''.join(lst))

The output is:

learn python fast

However, what if you want to do something different. Rather than joining all strings in the list to a single string, you want to join the strings in the list in pairs.

Problem: Python Join List Pairs

Problem: Given a list of strings. Join the first with the second string, the second with the third, and so on.

Example: Let’s consider the following minimal example:

['x', 'y', 'v', 'w']

Is there any simple way to pair the first with the second and the third with the fourth string to obtain the following output?

['xy', 'vw']

Note that the length of the strings in the list is variable so the following would be a perfectly acceptable input:

['aaaa', 'b', 'cc', 'dddd', 'eee', 'fff'] 

You can play with all three methods before diving into each of them:

Exercise: What’s the most Pythonic method?

Method 1: Zip() + List Comprehension

You can use the following smart one-liner solution

lst = ['aaaa', 'b', 'cc', 'dddd', 'eee', 'fff']
out = [x + y for x,y in zip(lst[::2], lst[1::2])]
print(out)
# ['aaaab', 'ccdddd', 'eeefff']

The one-liner uses the following strategy:

  • Obtain two slices lst[::2] and lst[1::2] of the original list over every other element starting from the first and the second elements, respectively. If you need to refresh your slicing skills, check out my detailed blog article.
  • Zip the two slices to a sequence of tuples using the zip(...) function. This aligns the first with the second elements from the original list, the third with the forth, and so on. To refresh your zip() skills, check out my blog tutorial here.
  • Use list comprehension to iterate over each pair of values x,y and concatenate them using list concatenation x+y. For a refresher on list comprehension, check out this free tutorial—and for a refresher on list concatenation, check out this one.

Method 2: Iterator + List Comprehension

You can also use an iterator to accomplish this:

lst = ['aaaa', 'b', 'cc', 'dddd', 'eee', 'fff']
it = iter(lst)
out = [x + next(it, '') for x in it] print(out)
# ['aaaab', 'ccdddd', 'eeefff']

Here’s the idea:

  • Create an iterator object it using the built-in function iter().
  • Use list comprehension to go over each element in the iterator.
  • Concatenate each element with the return value of calling the next() function on the iterator. This ensures that the iterator moves one position further iterating over the list. So, the next element x won’t be a duplicate.

Method 3: Use List Comprehension with Indexing

This method is the most straightforward one for Python beginners:

lst = ['aaaa', 'b', 'cc', 'dddd', 'eee', 'fff']
out = [lst[i] + lst[i+1] for i in range(0, len(lst), 2)]
print(out)
# ['aaaab', 'ccdddd', 'eeefff']

The idea is simply to use the range function to iterate over every other index i=0, 2, 4, 5, ... to access the i-th and the i+1-th elements at the same time in the expression statement of list comprehension (to concatenate those with lst[i] + lst[i+1]).

Where to Go From Here?

Enough theory, let’s get some practice!

To become successful in coding, you need to get out there and solve real problems for real people. That’s how you can become a six-figure earner easily. And that’s how you polish the skills you really need in practice. After all, what’s the use of learning theory that nobody ever needs?

Practice projects is how you sharpen your saw in coding!

Do you want to become a code master by focusing on practical code projects that actually earn you money and solve problems for people?

Then become a Python freelance developer! It’s the best way of approaching the task of improving your Python skills—even if you are a complete beginner.

Join my free webinar “How to Build Your High-Income Skill Python” and watch how I grew my coding business online and how you can, too—from the comfort of your own home.

Join the free webinar now!

Posted on Leave a comment

How to Merge Lists into a List of Tuples? [6 Pythonic Ways]

Merge Lists to List of Tuples

The most Pythonic way to merge multiple lists l0, l1, ..., ln into a list of tuples (grouping together the i-th elements) is to use the zip() function zip(l0, l1, ..., ln). If you store your lists in a list of lists lst, write zip(*lst) to unpack all inner lists into the zip function.

l1 = [1, 2, 3]
l2 = [4, 5, 6]
l = list(zip(l1, l2))
print(l)
# [(1, 4), (2, 5), (3, 6)]

The proficient use of Python’s built-in data structures is an integral part of your Python education. This tutorial shows you how you can merge multiple lists into the “column” representation—a list of tuples. By studying these six different ways, you’ll not only understand how to solve this particular problem, you’ll also become a better coder overall.

Problem: Given a number of lists l1, l2, …, ln. How to merge them into a list of tuples (column-wise)?

Example: Say, you want to merge the following lists

l0 = [0, 'Alice', 4500.00]
l1 = [1, 'Bob', 6666.66]
l2 = [2, 'Liz', 9999.99]

into a list of tuples

[(0, 1, 2), ('Alice', 'Bob', 'Liz'), (4500.0, 6666.66, 9999.99)]

This tutorial shows you different ways to merge multiple lists into a list of tuples in Python 3. You can get a quick overview in our interactive Python shell:

Exercise: Which method needs the least number of characters?

Method 1: Zip Function

The most Pythonic way that merges multiple lists into a list of tuples is the zip function. It accomplishes this in a single line of code—while being readable, concise, and efficient.

The zip() function takes one or more iterables and aggregates them to a single one by combining the i-th values of each iterable into a tuple. For example, zip together lists [1, 2, 3] and [4, 5, 6] to [(1,4), (2,5), (3,6)].

Here’s the code solution:

l0 = [0, 'Alice', 4500.00]
l1 = [1, 'Bob', 6666.66]
l2 = [2, 'Liz', 9999.99] print(list(zip(l0, l1, l2)))

The output is the following list of tuples:

[(0, 1, 2), ('Alice', 'Bob', 'Liz'), (4500.0, 6666.66, 9999.99)]

Note that the return value of the zip() function is a zip object. You need to convert it to a list using the list(...) constructor to create a list of tuples.

If you have stored the input lists in a single list of lists, the following method is best for you!

Method 2: Zip Function with Unpacking

You can use the asterisk operator *lst to unpack all inner elements from a given list lst. Especially if you want to merge many different lists, this can significantly reduce the length of your code. Instead of writing zip(lst[0], lst[1], ..., lst[n]), simplify to zip(*lst) to unpack all inner lists into the zip function and accomplish the same thing!

lst = [[0, 'Alice', 4500.00], [1, 'Bob', 6666.66], [2, 'Liz', 9999.99]]
print(list(zip(*lst)))

This generates the list of tuples:

[(0, 1, 2), ('Alice', 'Bob', 'Liz'), (4500.0, 6666.66, 9999.99)]

I’d consider using the zip() function with unpacking the most Pythonic way to merge multiple lists into a list of tuples.

Method 3: List Comprehension

List comprehension is a compact way of creating lists. The simple formula is [expression + context].

  • Expression: What to do with each list element?
  • Context: What elements to select? The context consists of an arbitrary number of for and if statements.

The example [x for x in range(3)] creates the list [0, 1, 2].

Related Article: You can read more about list comprehension in my ultimate guide on this blog.

You can use a straightforward list comprehension statement [(l0[i], l1[i], l2[i]) for i in range(len(l0))] to merge multiple lists into a list of tuples:

l0 = [0, 'Alice', 4500.00]
l1 = [1, 'Bob', 6666.66]
l2 = [2, 'Liz', 9999.99] print([(l0[i], l1[i], l2[i]) for i in range(len(l0))])

The output produces the merged list of tuples:

[(0, 1, 2), ('Alice', 'Bob', 'Liz'), (4500.0, 6666.66, 9999.99)]

This method is short and efficient. It may not be too readable for you if you’re a beginner coder—but advanced coders usually have no problems understanding this one-liner. If you love to learn everything there is about one-liner Python code snippets, check out my new book “Python One-Liners” (published with San Francisco Publisher NoStarch in 2020).

Method 4: Simple Loop

Sure, you can skip all the fancy Python and just use a simple loop as well! Here’s how this works:

l0 = [0, 'Alice', 4500.00]
l1 = [1, 'Bob', 6666.66]
l2 = [2, 'Liz', 9999.99] lst = []
for i in range(len(l0)): lst.append((l0[i], l1[i], l2[i]))
print(lst)

The output is the merged list of tuples:

[(0, 1, 2), ('Alice', 'Bob', 'Liz'), (4500.0, 6666.66, 9999.99)]

Especially coders who come to Python from another programming language such as Go, C++, or Java like this approach. They’re used to writing loops and they can quickly grasp what’s going on in this code snippet.

You can visualize the execution of this code snippet in the interactive widget:

Exercise: Click “Next” to see how the memory usage unfolds when running the code.

Method 5: Enumerate

The enumerate() method is considered to be better Python style in many scenarios—for example, if you want to iterate over all indices of a list. In my opinion, it’s slightly better than using range(len(l)). Here’s how you can use enumerate() in your code to merge multiple lists into a single list of tuples:

l0 = [0, 'Alice', 4500.00]
l1 = [1, 'Bob', 6666.66]
l2 = [2, 'Liz', 9999.99] lst = []
for i,x in enumerate(l0): lst.append((x,l1[i],l2[i]))
print(lst)

The output is the list of tuples:

[(0, 1, 2), ('Alice', 'Bob', 'Liz'), (4500.0, 6666.66, 9999.99)]

Still not satisfied? Let’s have a look at functional programming.

Method 6: Map + Lambda

With Python’s map() function, you can apply a specific function to each element of an iterable. It takes two arguments:

  • Function: In most cases, this is a lambda function you define on the fly. This is the function which you are going to apply to each element of an…
  • Iterable: This is an iterable that you convert into a new iterable where each element is the result of the applied map() function.

The result is a map object. What many coders don’t know is that the map() function also allows multiple iterables. In this case, the lambda function takes multiple arguments—one for each iterable. It then creates an iterable of tuples and returns this as a result.

Here’s how you can create a list of tuples from a few given lists:

l0 = [0, 'Alice', 4500.00]
l1 = [1, 'Bob', 6666.66]
l2 = [2, 'Liz', 9999.99] lst = list(map(lambda x, y, z: (x, y, z), l0, l1, l2))
print(lst)

The output is the merged list of tuples:

[(0, 1, 2), ('Alice', 'Bob', 'Liz'), (4500.0, 6666.66, 9999.99)]

This is both an efficient and readable way to merge multiple lists into a list of tuples. The fact that it isn’t well-known to use the map() function with multiple arguments doesn’t make this less beautiful.

Where to Go From Here?

Enough theory, let’s get some practice!

To become successful in coding, you need to get out there and solve real problems for real people. That’s how you can become a six-figure earner easily. And that’s how you polish the skills you really need in practice. After all, what’s the use of learning theory that nobody ever needs?

Practice projects is how you sharpen your saw in coding!

Do you want to become a code master by focusing on practical code projects that actually earn you money and solve problems for people?

Then become a Python freelance developer! It’s the best way of approaching the task of improving your Python skills—even if you are a complete beginner.

Join my free webinar “How to Build Your High-Income Skill Python” and watch how I grew my coding business online and how you can, too—from the comfort of your own home.

Join the free webinar now!

Posted on Leave a comment

Python Join List Range: A Helpful Guide

If the search phrase “Python Join List Range” brought you here, you’re having most likely one of the following problems:

  1. You don’t know how to concatenate two range() iterables, or
  2. You want to use .join() to create a string from a range() iterable—but it doesn’t work.

In any case, by reading this article, I hope that you’ll not only answer your question, you’re also become a slightly better (Python) coder by understanding important nuances in the Python programming language.

But let’s first play with some code and get an overview of the two solutions, shall we?

Exercise: Can you accomplish both objectives in a single line of Python code?

Python Join List Range

Concatenate Two range() Iterables

Problem: How to create a new list by concatenating two range() iterables?

Example: You want to concatenate the following two range() iterables

range(1,5) + range(5,10)

Your expected result is:

[1, 2, 3, 4, 5, 6, 7, 8, 9]

Developing the Solution: The result of the range(start, stop, step) function is an iterable “range” object:

>>> range(10)
range(0, 10)
>>> type(range(10))
<class 'range'>

Unfortunately, you cannot simply concatenate two range objects because this would cause a TypeError—the + operator is not defined on two range objects:

>>> range(1, 5) + range(5, 10)
Traceback (most recent call last): File "<pyshell#2>", line 1, in <module> range(1, 5) + range(5, 10)
TypeError: unsupported operand type(s) for +: 'range' and 'range'

Thus, the easiest way to concatenate two range objects is to do the following.

  • Convert both range objects to lists using the list(range(...)) function calls.
  • Use the list concatenation operator + on the resulting objects.
l = list(range(1, 5)) + list(range(5, 10))
print(l)
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

There are other ways to concatenate lists—and a more efficient one is to use the itertools.chain() function.

from itertools import chain
l = chain(range(1, 5), range(5, 10))
print(list(l))
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

This has the advantage that you work purely on iterables rather than lists. There’s no need to waste computational cycles to create a list object if you need it only to concatenate it to another list object. By avoiding the superfluous list creation, you win in performance (at the costs of adding another library to your code).

You can see how the first version creates multiple list objects in memory in the interactive memory visualizer:

Exercise: How many list objects are there in memory after the code terminates?

Use .join() to Create a String From a range() Iterable

Problem: Given a range object—which is an iterable of integers—how to join all integers into a new string variable?

Example: You have the following range object:

range(10)

You want the following string:

'0123456789'

Solution: To convert a range object to a string, use the string.join() method and pass the generator expression str(x) for x in range(...) to convert each integer to a string value first. This is necessary as the join function expects an iterable of strings and not integers. If you miss this second step, Python will throw a TypeError:

print(''.join(range(10))) '''
Traceback (most recent call last): File "C:\Users\xcent\Desktop\code.py", line 2, in <module> print(''.join(range(10)))
TypeError: sequence item 0: expected str instance, int found '''

So, the correct way is to convert each element to a string using the generator expression str(x) for x in range(...) inside the join(...) argument list. Here’s the correct code that joins together all integers in a range object in the most Pyhtonic way:

print(''.join(str(x) for x in range(10))) '0123456789'

You can use different delimiter strings if you need to:

print('-'.join(str(x) for x in range(10))) '0-1-2-3-4-5-6-7-8-9'

Related articles:

Where to Go From Here?

Enough theory, let’s get some practice!

To become successful in coding, you need to get out there and solve real problems for real people. That’s how you can become a six-figure earner easily. And that’s how you polish the skills you really need in practice. After all, what’s the use of learning theory that nobody ever needs?

Practice projects is how you sharpen your saw in coding!

Do you want to become a code master by focusing on practical code projects that actually earn you money and solve problems for people?

Then become a Python freelance developer! It’s the best way of approaching the task of improving your Python skills—even if you are a complete beginner.

Join my free webinar “How to Build Your High-Income Skill Python” and watch how I grew my coding business online and how you can, too—from the comfort of your own home.

Join the free webinar now!

Posted on Leave a comment

The Most Pythonic Way to Join a List in Reverse Order

The most efficient method to join a list of Python strings in reverse order is to use the Python code ''.join(l[::-1]). First, reverse the list l using slicing with a negative step size l[::-1]. Second, glue together the strings in the list using the join(...) method on the empty string ''.

Problem: Given a list of strings. How to join the strings in reverse order?

Example: You want to join the following list

l = ['n', 'o', 'h', 't', 'y', 'p']

to obtain the joined string in reverse order

python

Let’s get a short overview on how to accomplish this.

Solution Overview: You can try the three methods in our interactive Python shell.

Next, we’ll dive into each method separately.

Method 1: Join + Slicing

The first and most Pythonic method to reverse and join a list of strings is to use slicing with a negative step size.

You can slice any list in Python using the notation list[start:stop:step] to create a sublist starting with index start, ending right before index stop, and using the given step size—which can also be negative to slice from right to left. If you need a refresher on slicing, check out our detailed Finxter blog tutorial or our focused book “Coffee Break Python Slicing”.

Here’s the first method to reverse a list of strings and join the elements together:

l = ['n', 'o', 'h', 't', 'y', 'p'] # Method 1
print(''.join(l[::-1]))
# python

The string.join(iterable) method joins the string elements in the iterable to a new string by using the string on which it is called as a delimiter.

You can call this method on each list object in Python. Here’s the syntax:

string.join(iterable)

Argument Description
iterable The elements to be concatenated.

Related articles:

Method 2: Join + reversed()

The second method is also quite Pythonic: using the reversed() built-in function rather than slicing with a negative step size. I’d say that beginners generally prefer this method because it’s more readable to them—while expert coders prefer slicing because it’s more concise and slightly more efficient.

l = ['n', 'o', 'h', 't', 'y', 'p']
print(''.join(reversed(l)))
# python

The join method glues together all strings in the list—in reversed order!

Method 3: Simple Loop

The third method is the least Pythonic one: using a loop where it’s not really needed. Anyways, especially coders coming from other programming languages like Java or C++ will often use this approach.

l = ['n', 'o', 'h', 't', 'y', 'p'] s = ''
for x in reversed(l): s += x
print(s)
# python

However, there are several disadvantages. Can you see them?

  • The code is less concise.
  • The code is less efficient because of the repeated string concatenation. Each loop execution causes the creation of a new string, which is highly inefficient.
  • The code requires the definition of two new variables x and s and introduces a higher level of complexity.

You can see this in our interactive memory visualizer:

Exercise: click “Next” to see the memory objects used in this code snippet!

Related articles:

Where to Go From Here?

Enough theory, let’s get some practice!

To become successful in coding, you need to get out there and solve real problems for real people. That’s how you can become a six-figure earner easily. And that’s how you polish the skills you really need in practice. After all, what’s the use of learning theory that nobody ever needs?

Practice projects is how you sharpen your saw in coding!

Do you want to become a code master by focusing on practical code projects that actually earn you money and solve problems for people?

Then become a Python freelance developer! It’s the best way of approaching the task of improving your Python skills—even if you are a complete beginner.

Join my free webinar “How to Build Your High-Income Skill Python” and watch how I grew my coding business online and how you can, too—from the comfort of your own home.

Join the free webinar now!