Cool Features of Python


Mafinar Khan, Product Manager
Panacea Systems Limited
http://www.bdpanacea.com
@mafinar

In this presentation...

  • What makes Python pleasant
  • What makes Python powerful
  • What makes Python productive
  • import this; the Philosophy within
  • Way too many P's...

Pleasant Python

  • Easy to get up and running
  • Fully Object Oriented
  • Dynamic & Strongly typed
  • "Executable Pseudo-code"
  •  Conventions in the blood-stream
  • Philosophy driven
  • PEP8

Python Syntax Tidbits

  • Python's white spaces are important
  • Python compound statements end with ":" and start a scope with leading white-space
  • Python has "if", "while", "for..in", "with..as"
  • Python "else if" is written "elif"
  • Python supports Multiple Inheritance
  • Python has some magic functions that start and end with __
  • Python can do operator overloading
  • Python's List Comprehension is hell fun!

Operator Overloading

class Product(object):
    def __init__(self, name, price):
        self.name, self.price = name, price

    def __add__(self, other):
        return self.price + other.price

    def __call__(self, *args, **kwargs):
        return "PRODUCT: {} @ Tk {}".format(self.name, self.price)

a = Product("Apple", 160.00)
o = Product("Orange", 140.00)

assert a + o == 300

assert a() == "PRODUCT: Apple @ Tk 160.00"

List Comprehensions

# List
[i**2 for i in range(100)]

# A bit complex
[item for sublist in l for item in sublist]

# In two dimensions
[[c for c in line] for line in f]

# With guards
[i for i in range(100) if i%2]

# Works with set too
{i for i in [1,2,3,3,3,4,1,12,2,3,4]}



Powerful Python

  • Fully Object Oriented
  • Duck-typing
  • Functional Programming
  • Decorators and Generators
  • Advanced Object Oriented Constructs
  • Metaclasses

Functional Programming in Python

  • Functions are first class citizens
  • Single expression lambda's are available
  • Higher order Functions (map, reduce, filter)
  • Decorators
  • List/Set/Dictionary Comprehensions

Examples...

# Mathematics: f(x) = 2*x + 1
f = lambda x: 2*x + 1
is_odd = lambda x: not x%2

to_the_two = lambda limit: map(lambda x: x**2, range(limit)) # MAP

filter(is_odd, range(100)) # FILTER

reduce(lambda x,y: x+y, range(10)) # REDUCE

# Combine them all
import operator
reduce(operator.__add__, filter(is_odd, to_the_two(100)))




Decorators

  • Function wrapping other functions
  • Function takes a functions in, spits a function out.
  • Useful in hiding complex details from function implementors
  • Example: staticmethod, classmethod, login_required, expose, render_to
  • Mathematical analogy (somewhat): gof and fog.

Example (Decorator)

def bold_maker(f):
    def _wrap(f, *args, **kwargs):
        return "<b>{}</b>".format(f(*args, **kwargs))

    return _wrap


@bold_maker
def greet(name):
    return "Hello {}".format(name.capitalize())


# Alternatively
greet = bold_maker(lambda name: "Hello {}".format(name.capitalize())



Play around with itertools for more powerful Python Functional Programming constructs

Productive Python

  • Pleasant + Powerful = Productive
  • Fun with shell, dir, and help
  • Readability begets maintainability
  • Insanely big ecosystem
  • Amazing tools and frameworks
  • <3 Open Source

Multiple Inheritance

  • Depth First Search from Left-to-Right
  • (New Style) In case of duplicate parents, all but last get removed
  • Use __mro__ to find out the method resolution order
  • If A(object), B(A), C(A) and D(B, C) the resolution order would be [ D, B, C, A, object ] ([D, B, A, C, A] with all but last A gone)
  • Don't you just love __magic_methods__ ???


Fun with Objects

# Making methods case insensitive
class Person(object):
     def name(self):
         return "<NAME>"

     def age(self):
         return "<AGE>"

     def __getattr__(self, value):
         for i in type(self).__dict__.keys():
             if value.lower() == i.lower():
                 return getattr(self, i)
         return "UNDEFINED"

p = Person()
"Name: {}; Age: {}".format(p.NaME(), p.AGE())

Fun Continues...

class Container(object):
     def __init__(self, numbers):
         self.numbers = numbers

     def add(self, number):
         self.numbers.append(number)

     def __getattr__(self, attr):
         if attr.startswith("get_"):
             suffix = "_".join(attr.split("_")[1:])
             if suffix == "odd_numbers":
                 return lambda: filter(lambda x: x%2 == 1, self.numbers)
             if suffix == "less_than":
                 return lambda n: filter(lambda x: x < n, self.numbers)

c = Container(range(100))
c.get_odd_numbers(); c.get_less_than(50)

This is why Python has so many Beautiful Frameworks!

Python's Philosophy

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than right now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

Also, PEP8...

My Favorite Python Tools/Frameworks

  • Django
  • Twisted
  • BeautifulSoup
  • Matplotlib
  • NLTK
  • Reportlab
  • Numpy
  • Pandas
  • Jinja2

Thank You!!!

Made with Slides.com