Uncategorized

Three Peculiarities of Python and why I use them.

Programming languages are tools we use to solve problems. Yet most programmers transition from one language to another expecting these tools (programming languages) to behave like their previous languages. i.e why does language X not behave like language ​​ Y . Well my answer to that is quite simple. If you transition from English to Ga,  you will obey the rules of  Ga if you wish to communicate effectively.  So don’t be too caught up in language wars and use the constructs if need be.

Below are three peculiarities I found when I started using python but in time I began to appreciate and use them.

 try … except … else

The first time I came across this I felt one of the laws of nature had been broken. Why would one use exception handling as a means for flow control? In time, I realised there are situations where you need code to run only if the block of code within the try does not fail and unlike the way I would handle it in other languages, I’ve come to love python’s approach.

An example of such a case is manipulating a database object if successfully retrieved.

Using try … catch … else

# using Python 3 and Django 🙂
# try ... except ... else example
import logging

logger = logging.getLogger(__name__)


def un_publish(blog_id)
    try:
        blog = Blog.objects.get(pk=blog_id, is_published=True)
    except Blog.DoesNotExist as e:
        logger.info("blog with id {} does not exist".format(blog_id))
        logger.error(e)
    else:
        blog.is_published=False
        blog.save()
        return blog



Using try … catch without else

# using Python 3 and Django 🙂
# try ... except ... example no else
import logging

logger = logging.getLogger(__name__)


def un_publish(blog_id)
    # in order to prevent the if blog condition from failing, blog must be defined either before the try block or in the except blog
    blog = None
    try:
        blog = Blog.objects.get(pk=blog_id, is_published=True)
    except Blog.DoesNotExist as e:
        logger.info("blog with id {} does not exist".format(blog_id))
        logger.error(e)

    if blog:
        blog.is_published=False
        blog.save()
        return blog

In the second code snippet you would realise there is more code, and the worst part is- as a developer I have to remember the state of blog in the whole process. Perhaps it’s just me but I’ve come to love the first approach 🙂 If you won’t take my word for it read this

Inner Functions

In most cases this peculiarity will be called differently, but for our purposes I’ll stick with inner functions
The very first time I came across this was whilst reading a colleagues code at work and I thought to myself, “wow you can do this in python!?”. I could not really find a use case for ever using this peculiarity in my code except when I was developing decorators. In some rare cases, you have a piece of code which repeats itself within a function and it’s only needed within that said function. You could use an inner function to solve this problem.

An example could be adding empty rows to a csv file based on specific conditions.

def generate_report(start_date, end_date):
    # do sales report stuff
    sales = Sale.objects.filter(start_date=start_date, end_date=end_date)
    number_of_empty_columns = [""]
    for sale in sales:
        if sale.number_of_items == 3:
            number_of_empty_columns = [""] * 3
        elif sale.number_of_items == 2:
            number_of_empty_columns = [""] * 2

In the code above, the number_of_empty_columns could be generated with a function and since this code will only be needed within the generate_report, there is no need to write this piece of code outside the generate_report.

def generate_report(start_date, end_date):

    def gen_empty_strings(number):
        """
            This method generates a list of empty strings based on the number provided
            :param - number is the number of empty strings to be returned
        """
        return [""] * number

    # do sales report stuff
    
    sales = Sale.objects.filter(start_date=start_date, end_date=end_date)
    number_of_empty_columns = gen_empty_strings(1)
    for sale in sales:
        if sale.number_of_items == 3:
            number_of_empty_columns = gen_empty_strings(3)
        elif sale.number_of_items == 2:
            number_of_empty_columns = gen_empty_strings(2)

Although the above code is a simplified use case of inner functions, inner functions can make code cleaner and easier to maintain, but over using it could make code harder to read. Some thoughts on inner functions in python:

https://softwareengineering.stackexchange.com/questions/232766/when-to-use-python-function-nesting
https://stackoverflow.com/questions/1589058/nested-function-in-python

Dictionaries as switch cases

In case you have not noticed, python has no switch cases for control flow, so most programmers resort to lengthy if statements. What if I told you that the pythonic way to create switch cases is to use a dictionary. Don’t believe me, follow the code below:

# Assuming you needed to show a different kind of menu to different kind of users. You will realise a switch-case may be cleaner than a series of if-statements:
# Note this is demo code.

def customer_menu():
    print("welcome customer")
    # do customer menu stuff

def admin_menu():
    print("welcome admin")
    # do admin menu stuff

def sales_menu():
    print("welcome sales rep")

menu = {
  'customer': customer_menu,
  'admin': admin_menu,
  'sales': sales_menu
}

# To call a specific menu 
selected_menu = menu.get('customer', lambda: "Invalid menu choice")
selected_menu()

Perhaps my love for using dictionaries in place of switch cases may be a sign of Stockholme Syndrome 🙂

 

Standard

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.