Python

Python tuple

Python built-in types – Tuples

Tuple is a python built-in data structure which holds a sequence of values, and the values can be in any data type. If you write a hundred lines of python code, it is almost impossible to avoid it in your code, as it comes in implicitly or explicitly from your variable assignment and iteration to return values of your method. In this article, I will be sharing with you where and how the tuples will be possibly used in your code.

Variable assignment with Tuple

You may have written the code in the below way to assign the values to variables in one line. The left side is the tuple of variables, and the right side is the tuple of values/expressions.

sort_by_name, sort_by_date = True, False
#output : sort_by_name True, sort_by_date False
key, val = "20200601" , "Mon"
#output : key '20200601', val 'Mon'

Sometimes if you want to swap the values of two variables, you do not need to create a temp variable for swapping. The below will do a perfect job to swap the value for key, val variables.

key, val = val, key
#output: key 'Mon', val '20200601'

Traverse the elements of a sequence

If you want to iterate through each of the elements in a sequence and meanwhile get the index of the element, you can do it by below code:

for idx, label in enumerate('ABCDEFG'):
    print(idx, label)

#output: 0, A
#1, B
#...

When iterating a dictionary, the iterms method returns a list of tuples, and each tuple is the key and value pair, e.g.:

company_info = {"name" : "Alibaba", "headquarter" : "Hangzhou, China", "founded" : "4 April 1999"}
for key, val in company_info.items():
    print(f"{key} : {val}")

If you have checked my another post – How to swap the key and value in a python dictionary, it is just an extension to the above.

Iterate multiple sequences at one time with zip

If you use the built-in zip function to iterate multiple sequences at one time, it actually returns an iterator of tuples. See the below example:

names = ["Alibaba", "Amazon", "Google"]
countries = ["China", "USA", "USA"]
years = ["1999", "1996", "1998"]
for rec in zip(names, countries, years):
    print(rec)

#output:
#('Alibaba', 'China', '1999')
#('Amazon', 'USA', '1996')
#('Google', 'USA', '1998')

Return multiple values from function

Normally a function can only returns 1 value, but with tuple, you can return multiple values even in different data types. (technically speaking, it is still 1 value but tuple type)

e.g. The python built-in method divmod:

quotient, remainder = divmod(10, 3)
print(quotient, remainder)
#output: 3 1

You can also define your own function to return multiple values like below:

def split_email(email):
    user_name, company_site = email.split("@")
    return user_name, company_site


split_email("contact@codeforests.com")
#output: ('contact', 'codeforests.com')

With this example, I am going to wrap up my article for this topic. If you have any questions or comments, please share in the below.

 

python unpack objects

Python how to unpack tuple, list and dictionary

There are various cases that you want to unpack your python objects such as tuple, list or dictionary into individual variables, so that you can easily access the individual items. In this article I will be sharing with you how to unpack these different python objects and how it can be useful when working with the *args and **kwargs in the function.

Let’s get started.

Unpack python tuple objects

Let’s say we have a tuple object called shape which describes the height, width and channel of an image, we shall be able to unpack it to 3 separate variables by doing below:

shape = (500, 300, 3)
height, width, channel = shape
print(height, width, channel)

And you can see each item inside the tuple has been assigned to the individual variables with a meaningful name, which increases the readability of your code. Below is the output:

500 300 3

It’s definitely more elegant than accessing each items by index, e.g. shape[0], shape[1], shape[2].

What if we just need to access a few items in a big tuple which has many items? Here we need to introduce the _ (unnamed variable) and * (unpack arbitrary number of items)

For example,  if we just want to extract the first and the last item from the below tuple, we can let the rest of the items go into a unnamed variable.

toto_result = (4,11,14,23,28,47,24)
first, *_, last = toto_result
print(first, last)

So the above will give the below output:

4 24

If you are curious what is inside the “_”, you can try to print it out. and you would see it’s actually a list of the rest of items between the first and last item.

[11, 14, 23, 28, 47]

The most popular use case of the packing and unpacking is to pass around as parameters to function which accepts arbitrary number of arguments (*args). Let’s look at an example:

def sum(*numbers):
    total = 0
    for n in numbers:
        total += n
    return total

For the above sum function, it accepts any number of arguments and sum up the values. The * here is trying to pack all the arguments passed to this function and put it into a tuple called numbers. If you are going to sum up the values for all the items in toto_result, directly pass in the toto_result would not work.

toto_resut = (4,11,14,23,28,47,24)
#sum(toto_result) would raise TypeError

So what we can do is to unpack the items from the tuple then pass it the sum function:

total = sum(*toto_resut)
print(total)
#output should be 151

Unpack python list objects

Unpacking the list object is similar to the unpacking operations on tuple object. If we replace the tuple to list in the above example, it should be working perfectly.

shape = [500, 300, 3]
height, width, channel = shape
print(height, width, channel)
#output shall be 500 300 3

toto_result = [4,11,14,23,28,47,24]
first, *_, last = toto_result
print(first, last)
#output shall be 4 24

total = sum(*toto_resut) 
print(total) 
#output should be also 151

Unpack python dictionary objects

Unlike the list or tuple, unpacking the dictionary probably only useful when you wants to pass the dictionary as the keyword arguments into a function (**kwargs).

For instance, in the below function, you can pass in all your keyword arguments one by one.

def print_header(**headers):
    for header in headers:
        print(header, headers[header])

print_header(Host="Mozilla/5.0", referer = "https://www.codeforests.com")

Or if you have a dictionary like below, you can just unpack it and pass to the function:

headers = {'Host': 'www.codeforests.com', 'referer' : 'https://www.codeforests.com'}
print_header(**headers)

It will generate the same result as previously, but the code is more concise.

Host www.codeforests.com
referer https://www.codeforests.com

With this unpacking operator, you can also combine multiple dictionaries as per below:

headers = {'Host': 'www.codeforests.com', 'referer' : 'https://www.codeforests.com'}
extra_header = {'user-agent': 'Mozilla/5.0'}

new_header = {**headers, **extra_header}

The output of the new_header will be like below:

{'Host': 'www.codeforests.com',
 'referer': 'https://www.codeforests.com',
 'user-agent': 'Mozilla/5.0'}

Conclusion

The unpacking operation is very usefully especially when dealing with the *args and **kwargs. There is one thing worth noting on the unamed variable (_) which I mentioned in the previous paragraph. Please use it with caution, as if you notice, the python interactive interpreter also uses _ to store the last executed expression. So do take note on this potential conflict. See the below example:

codeforests interactive interpreter conflicts

As per always, welcome any comments or questions.

How to read and write configuration (.ini) file in python

There are several file formats you can use for your configuration file, the most commonly used format are .ini, .json and .yaml. In this article, I will sharing with you how to read/write your configurations in the .ini file formats.

Read .ini file

Below is a example of the ini file, you can define the sections (e.g. [LOGIN]) as much as you want to separate the different configuration info.

[LOGIN]
user = admin
#Please change to your real password
password = admin

[SERVER]
host = 192.168.0.1
port = 8088

In python, there is already a module configparser to read an parse the information from the ini file int dictionary objects. Assume you have saved above as config.ini file into your current folder, you can use the below lines of code to read.

import configparser

config = configparser.ConfigParser()		
config.read("config.ini")
login = config['LOGIN']
server = config['SERVER']

You can assign each of the sections into a separate dictionary for easier accessing the values. The output should be same as below:

codeforests read ini file

Note that the line starting with # symbol (or ; ) will be taken as comment line and omitted when parsing the keys and values.

Also all the values are taken as string, so you will need to do your own data type conversion after you read it.

Write .ini file

Now let’s see how we can write to an ini file.

You will still need this configparser library, and the idea is that you need to set the keys and values into the configparser object and then save it into a file.

config = configparser.ConfigParser()
if not config.has_section("INFO"):
    config.add_section("INFO")
    config.set("INFO", "link", "www.codeforests.com")
    config.set("INFO", "name", "ken")

with open("example.ini", 'w') as configfile:
    config.write(configfile)

And this would create the example.ini file with below content:

[INFO]
link = www.codeforests.com
name = ken

I have created another two separate articles to cover the .json and .yaml format, please have a look if you are interested.

As per always, welcome any comments or questions.

python dictionary keyerror

Handling the KeyError for python dictionary

python dictionary KeyError

The KeyError is quite commonly seen when dealing with the dictionary objects. when trying to access the dictionary while the key does not exists, then this error will be showing up. Usually to avoid this error, we will need to check if the key exists before accessing the value.

For instance, you can check if the key “country” exists in my_dict and then check if the values is “SGP” like the below. But the code does not look elegant.

my_dict = {"name" : "National University of Singapore", "address" : "21 Lower Kent Ridge Rd Singapore", "contact": "68741616"}
if my_dict.get("country") and my_dict["country"] == "SGP":
    print(f"country code is {my_dict['country']}")

You may also see someone uses the below way to make the code more concise. To pass in a default value if the key does not exists:

if my_dict.get("country", "") == "SGP":
    print(f"country code is {my_dict['country']}")

The Zen of Python tells us

Explicit is better than implicit.

So the above code actually does not follow this principal. If you go through the python documentation for dictionary, there is indeed a way to get the value of the key and meanwhile setting a default value if the key is new to the dictionary. Below code shows how it works:

if my_dict.setdefault("country", "") == "SGP":
    print(f"country code is {my_dict['country']}")

By doing the above, the key “country” will be added into the my_dict with a default value if the key does not exists previously, and then return the value of this key.

To extend the above setdefault method, if the value is a list of objects, you can also use this method to initialize it and then set the value.

my_dict.setdefault("faculty", []) # use list or set()
my_dict["faculty"].append("Arts")
my_dict["faculty"].append("Computer Science")

 

As per always, welcome for any comments or questions.