User defined custom object sorting in python

"""
@Author: Aseem Jain
@profile: https://www.linkedin.com/in/premaseem/

Title: Sort the class or custom object and not regular int / string using in build sort funcitons
Sort custom object can be done in 2 ways
1. Static way : class implementing < less then __lt__(self,other)
2. Dynamic way is by providing lambda func with key.
"""
class User:
def __init__(self,name,age):
self.name = name
self.age = age

def __repr__(self):
return self.name + str(self.age)

def __lt__(self, other):
return self.age < other.age

# Sorting String
ls = ["zeema", "aseemjain", "see",str(3),str(13),"$$"]
ls.sort()
print(ls)
#output: ['$$', '3', 'aseemjain', 'see', 'zeema']

# Reverse soring
ls.sort(reverse=True)
print(ls)
# output: ['zeema', 'see', 'aseemjain', '3', '$$']

# sorting Custom object
users = [User("aseem",16),User("aseemprem",56),User("premaseem",23),User("zseem",36),User("nseem",106) ]
users.sort(key = lambda x: x.name)
users.sort()
print(users)
# output : [aseem16, aseemprem56, nseem106, premaseem23, zseem36]

# create new sorted list
newlist = sorted(users, key=lambda x: x.age, reverse=True)
print(newlist)
# output: [nseem106, aseemprem56, zseem36, premaseem23, aseem16]

Github link: https://github.com/premaseem/pythonPlayground/blob/master/algorithm_and_datastructure/sorting/custom_object_sorting.py

Exit codes in Python

0 and 1 are the exit codes.

exit(0) means a clean exit without any errors / problems

exit(1) means there was some issue / error / problem and that is why the program is exiting.

This is not Python specific and is pretty common. A non-zero exit code is treated as an abnormal exit, and at times, the error code indicates what the problem was. A zero error code means a successful exit.

This is useful for other programs, shell, caller etc. to know what happened with your program and proceed accordingly.

For the record, you can use POSIX standard exit codes defined here.

Example:

import sys, os

try:
    config()
except:
    sys.exit(os.EX_CONFIG) 
try:
    do_stuff()
except:
    sys.exit(os.EX_SOFTWARE)
sys.exit(os.EX_OK) # code 0, all ok

Python: Quick script to create directory

Here is simple python code to smartly create a folder if it does not exisit

 

import os

def createFolder(directory):
    try:
        if not os.path.exists(directory):
            os.makedirs(directory)
    except OSError:
        print ('Error: Creating directory. ' +  directory)
        

# Example
createFolder('./data/')
# Creates a folder in the current directory called data

Python: printing on the same line (progress indicator)

In Java we have print which allow to print in same line
and println allow us to print on new line

But in python print always prints on new line, that makes it to difficult to print progress.

 

sys.stdout.write will print without return carriage

import sys
sys.stdout.write("progressing xxx")

Code running which needs to show progress
     sys.stdout.write(".")

Python: Check if all elements in a list are equal

# Pythonic ways of checking if all
# items in a list are equal:

>>> lst = ['a', 'a', 'a']

>>> len(set(lst)) == 1
True

>>> all(x == lst[0] for x in lst)
True

>>> lst.count(lst[0]) == len(lst)
True

# I ordered those from "most Pythonic" to "least Pythonic" 
# and  "least efficient" to "most efficient". 
# The len(set()) solution is idiomatic,  but constructing 
# a set is less efficient memory and speed-wise.

Python: list comprehensions

# Python's list comprehensions are awesome.

vals = [expression 
        for value in collection 
        if condition]

# This is equivalent to:

vals = []
for value in collection:
    if condition:
        vals.append(expression)

# Example:

>>> even_squares = [x * x for x in range(10) if not x % 2]
>>> even_squares
[0, 4, 16, 36, 64]

Python: Dict get with default value to void key not found error

# The get() method on dicts
# and its "default" argument

name_for_userid = {
    382: "Aseem",
    590: "Bob",
    951: "Dilbert",
}

def greeting(userid):
    return "Hi %s!" % name_for_userid.get(userid, "there")

>>> greeting(382)
"Hi Aseem!"

>>> greeting(333333)
"Hi there!"

Python: emulate switch/case statements by using dict with lambda functions

# Because Python has first-class functions they can
# be used to emulate switch/case statements

def dispatch_if(operator, x, y):
    if operator == 'add':
        return x + y
    elif operator == 'sub':
        return x - y
    elif operator == 'mul':
        return x * y
    elif operator == 'div':
        return x / y
    else:
        return None


def dispatch_dict(operator, x, y):
    return {
        'add': lambda: x + y,
        'sub': lambda: x - y,
        'mul': lambda: x * y,
        'div': lambda: x / y,
    }.get(operator, lambda: None)()


>>> dispatch_if('mul', 2, 8)
16

>>> dispatch_dict('mul', 2, 8)
16

>>> dispatch_if('unknown', 2, 8)
None

>>> dispatch_dict('unknown', 2, 8)
None

Python: Functions are first-class citizens

# Functions are first-class citizens in Python.

# They can be passed as arguments to other functions,
# returned as values from other functions, and
# assigned to variables and stored in data structures.

>>> def myfunc(a, b):
...     return a + b
...
>>> funcs = [myfunc]
>>> funcs[0]
<function myfunc at 0x107012230>
>>> funcs[0](2, 3)
5

Python: __dict__ class instance members are really dictionaries

Python class instance members are really dictionaries/mappings. For example,

    class Foo:
        def __init__(self, name=''):
            self.name = name

You can access the name member:

    In [2]: f = Foo('vito')

    In [3]: f.name
    Out[3]: 'vito'

You can also do:

    In [4]: f.__dict__['name']
    Out[4]: 'vito'

In fact, you can see all the data members:

    In [5]: f.__dict__
    Out[5]: {'name': 'vito'}

This gives us a quick way of creating an object at run time, say when parsing a text file. For a very contrived example, we have a text file that looks like this:

    name=John,age=35,hobby=philately
    name=Sally,age=28
    name=Vito,age=18,sex=male
    name=Maria,age=58

We can grab all the data into a bunch of objects like this:

    class Person:
        def __init__(self, name=''):
            self.name = name

    if __name__ == '__main__':
        f = open('people.dat', 'ro')
        people = []
        for l in f.readlines():
            people.append(Person())
            lsp = l.strip().split(',')
            p = []
            for i in lsp:
                p.append(i.split('='))
            people[-1].__dict__ = dict(p)

        for p in people:
            print p.__dict__

And the output is:

    {'hobby': 'philately', 'age': '35', 'name': 'John'}
    {'age': '28', 'name': 'Sally'}
    {'age': '18', 'name': 'Vito', 'sex': 'male'}
    {'age': '58', 'name': 'Maria'}