Learning Python, Django



PYTHON • CORE
Context manager types - with
The context manager type is a Python feature to help work with unmanaged resources (e.g. file streams) which it is better to clean up or shutdown in an orderly manner after use, e.g. always closing a file after use).

The use of the with statement (on objects that support it, such as built-in or custom context managers) is used to ensure resources are cleaned up after use.

>>> with open('a.txt', 'w') as f:
...     f.write('a line')
...
6
>>> f.closed
True
>>> with open('a.txt', 'r') as f:
...     l = f.read()
...
>>> f.closed
True
>>> l
'a line'
with can be seen as syntactic sugar for the try/except/finally block.

To implement a custom context manager, two methods must be implemented:

class my_context_manager:
  def __enter__(self):
      # set up things
      return thing
  def __exit__(self,type,value,traceback):
      # deal with unmanaged resources
#....
with my_context_manager as custom_name
   # work with resources
When the with statement is executed, __enter__ is called, assigning the returned value to the variable after as.

Whatever happens in the code, the __exit__ method will be called in the end to make sure nothing is left unmanaged.


PYTHON • CORE
Check available python modules
Find a list of all python modules installed on a machine by running the following command in a terminal.

$> pydoc modules
or

>>> help('modules')
inside of a python interactive shell.


PYTHON • CORE
Dynamic Typing
Unlike in statically-typed programming language, Python variables are dynamically typed. That means that a variable (e.g. x) can take the value of a number, a string or even a function, but not at the same time.

Some people consider Python's dynamic typing a weakness as it can lead to hard to find bugs.

As said before, a variable can take different types of values:

x = 'enki'
x = 3.14
def x():
  pass
In Python, variables do not represent a portion of computer's memory where their value is written, but tags pointing to object.

Keep in mind that it is a bad practice to use the same variable name for different data types. Instead, use meaningful names for

# bad
x = 2.71
x = 'hey'
# good
e = 2.71
greeting = 'hey'


PYTHON • CORE
Chain comparison operators
Python provides a syntactic shortcut for chaining comparison operators.

>>> x = 10
>>> 1 < x < 15
True
Is the equivalent of:

>>> x = 10
>>> 1 < x  && x < 15
True


PYTHON • OOP
Custom exceptions as classes
Because exceptions in Python are built-in classes, you can create your own exceptions by inheriting from class Exception or one of its subclasses.

class ErrOne(Exception):
  pass
class ErrTwo(ErrOne):
  pass
class ErrThree(ErrTwo):
  pass
# these are all exceptions
We can raise any of these exceptions using the raise statement:

for err in [ErrOne, ErrTwo, ErrThree]:
  try:
  raise err()
  except ErrThree:
  print("3")
  except ErrTwo:
  print("2")
  except ErrOne
  print("1") 
# output 1 / 2 /3
Unhandled exceptions will print an error message with the exception's class name. Suppose we remove the last except ErrOne clause, the following message will be printed:

....
  raise err()
__main__.ErrOne


PYTHON • DATA STRUCTURES
Playing with time
The time module is a widely used module for time manipulation, representation and conversion.

Import the module:

import time
The time.time() function returns the current time in seconds since "the Unix Epoch", i.e.
12:00am January 1, 1970.

cur_time = time.time()
print("Seconds since Epoch: ",\
cur_time)

Seconds since Epoch:
1455637441.6129153
Pass time.localtime the number of seconds since the Epoch; it will return a time-tuple with the current local time:

print("Current local time :",\
time.localtime(cur_time))
To make localtime's output more readable, use time.asctime:

print("Formatted time:", \
time.asctime(time.localtime()))
Formatted time:
Sat Jun 25 01:05:20 2016
time.sleep(n) can be used to make your program sleep for n seconds:

print("sleeping")
time.sleep(5) #pauses for 5 seconds
print("woke up")


PYTHON • DATA STRUCTURES
datetime module
Python's datetime module provides multiple classes regarding date manipulation. Accessible date and time objects are either naive or aware and can be used as both simple and complex solutions.

Unlike naive objects, aware objects have enough knowledge to locate themselves relative to other aware objects. (e.g. time zone/daylight saving time). They represent specific points in time that aren't open to interpretation.

The datetime module itself exports the constants:

datetime.MINYEAR # == 1
# smallest year of date/datetime objects
datetime.MAXYEAR # == 9999
## largest year of date/datetime objects
While this module supplies multiple straightforward classes such as date, time or timedelta, it also supplies the datetime class that can be confused with the name of the module.

Be aware of the distinction:

from datetime import datetime
print (datetime.today())
## same result, different approach
import datetime
print (datetime.datetime.today())


PYTHON • DATA STRUCTURES
datetime object
The datetime type is a single object that encapsulates both a date and time object. This type is an aware object that will keep record of a specific point in time, not open to interpretation.

Its basic constructor combines the parameters of date and time objects constructors:

from datetime import datetime
d = datetime(2016, 2, 15, 13, 25)
print(d)
# 2016-02-15 13:25:00
Get the current exact time:

datetime.now() == datetime.today()
The difference between the now() and today() methods is that the former can be passed a tzinfo (timezone) argument which is by default set to None.

The datetime class is a complex one, with many methods that will meet most needs related to date and time manipulation.


PYTHON • DATA STRUCTURES
time object
The time object represents the time portion of the datetime object with microsecond precision. It represents a specific time of the day, independent of any particular one.

The time object can be adjusted via the tzinfo (also provided by datetime module) object, which specifies the time-zone information.

Basic constructor syntax :

#time(hour,minute,second,microsecond,tzinfo)
from datetime import time
t = time(5, 0, 55, 222222)
print(t)
# 05:00:55.222222
Note that every argument of the constructor is optional, and tzinfo is by default set to None.

Allowed arg values: hrs 0-23, mins 0-59, secs 0-59, msecs 0-999999.

Earliest representable time:

time.min == time(0, 0, 0, 0)
Latest representable time:

time.max == time(23,59,59,999999)
The time class has other methods, both basic and advanced, for other needs., such as time.replace or time.dst.


PYTHON • DATA STRUCTURES
timedelta object
The timedelta object provided by the datetime module represents a duration equal to the difference between two dates or times.

Instantiate a timedelta object:

import datetime as dt
# timedelta(days=0, seconds=0,
# microseconds=0,# milliseconds=0,
# minutes=0, hours=0, weeks=0)
# all args are OPTIONAL and default to 0
d = dt.timedelta(days=1, hours=3)
# the difference is one day and three hours
Substract the difference from a datetime:

import datetime as dt

today = dt.datetime.today()
d = dt.timedelta(days=1)
yesterday = today - d;
print(yesterday)
# 2016-02-15 15:05:14.095240
More operations are supported such as multplication and division.

With the introduction of Python 3.2, floor division and true division are supported between timedelta objects or by floats. This applies as well to timedelta.total_seconds() method that will return the number of seconds contained in the difference.

#older version equivalent
 td / timedelta(seconds=1)


Installing the SciPy Stack
https://www.scipy.org/install.html

Via pip
python -m pip install --upgrade pip
pip install --user numpy scipy matplotlib ipython jupyter pandas sympy nose

Via apt-get
sudo apt-get install python-numpy python-scipy python-matplotlib ipython ipython-notebook python-pandas python-sympy python-nose


PYTHON • DATA STRUCTURES
When range comes in handy
The range type is a fundamental immutable sequence type, used regularly hand in hand with for loops. It represents a sequence of numbers.

The most basic constructor for a range takes the stop index (not included) as argument:

r = range(5)
# r contains 0, 1, 2, 3, 4
Start index can be specified as well:

r = range (5,10)
# r contains 5, 6, 7, 8, 9
Specifying the step, the contents of r[i] is equal to start + step*i:

r = range (0,11,2)
# r contains 0, 2, 4, 6, 8, 10
in statement can be used for checks:

>>> r = range(0, 11, 2)
>>> 11 in r
False
>>> 8 in r
True
Use range together with for loops:

for i in range(0, 10, 3):
    print(i)
# print 0 3 6 9


PYTHON • DATA STRUCTURES
Get the most of ints
The basic int type has a few more additional methods:

Find the necessary number of bits to represent the int in binary (no sign and no leading zeros):

>>> n = 1024
>>> n.bit_length()
11
1024 in binary is 10000000000, i.e. requires 11 bits to represent in binary.

Get an array of bytes representing your int. Here, endianness aka byteorder (whether big or little) and signed or unsigned representation (True for two's complement) are taken into consideration:

# to_byes(length, byteorder, *, \
#  signed= False)
>>> n.to_bytes(2, byteorder='big')
b'\x04\x00'
>>> n.to_bytes(10, byteorder='little', \
signed=True)
b'\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00'
The reverse process can be achieved with the classmethod int.from_bytes:

int.from_bytes(b'\x04\x00', byteorder='big')
1024


Modules everywhere!
Whether being used for easier maintenance, scripting, logical organization of code or even for avoiding repetition, modules are a fundamental structuring mechanism for any Python application which is more than a few lines of code.

Modules are basically files with data, function and class definitions that can be imported in other modules or in the main module. They can also contain statements at global scope, that are executed when the module is imported or run.

Sample module:

#my_module.py file
def greet(name):
  print("Enki says hello,", name)
To use it the import statement can be used (the optional as clause renames the imported module):

import my_module as mod
mod.greet("Craig")
# prints 'Enki says hello, Craig'
To import a single definition (function, class or variable), the from keyword is used:

from my_module import greet
greet("Craig")
# prints 'Enki says hello, Craig'
It's possible to import all definitions:

from my_module import *
greet("Craig")
# prints 'Enki says hello, Craig'
but this is not considered a good practice, and isn't used except in a few special cases.


PYTHON • DATA STRUCTURES
Operations with bytes and bytearray
Both bytes and bytearray support common special operations not only with operand of the same type, but with any bytes-like objects.

Arguments should not be strings, but conversions:

a = bytes(b"abc") # bytes object
b = a.replace("a", "f")  # will raise error
b = a.replace(b"a", b"f") # will work
print (b)
# output: b'fbc'
Most of the following methods have been introduced in Python's version 3.1 or modified later on.

You can count the occurrences of a subsequence:

a = bytearray(b"ababab")
print(a.count(b"a"))
# output: 3
You can check if all bytes in the sequence are ASCII alphanumeric characters:

>>> (b'abc').isalnum()
True
>>> (b'abc?').isalnum()
False
You can create copy of the bytes, zero-filled to a specified width. This is useful in generating formatted report columns:

>>> (b"37").zfill(6)
b'000037'
You can strip a bytes object to remove leading or trailing bytes from a specified sequence given as argument:

>>> (b'www.enki.com').strip(b'wcom.')
b'enki'


Test is number is an integer:
def modulus(n):
    if n % 1 == 0:
        return n % 2
    else:
        return -1


Bit_length()
Implement a function that, given an integer n, will return the number of bits in its binary representation.
For n = 50, the output should be
countBits(n) = 6.
5010 = 1100102, a number that consists of 6 digits. Thus, the output should be 6.

def countBits(n):
    return n.bit_length()


PYTHON • DATA STRUCTURES
Tuples represent one of the three currently implemented sequence data types (along with lists and ranges).

Tuples are used to group any number of items into a single compound value regardless of their type (even nested tuples):
>>> myTuple = ("first", 13, "random", 42)

You can extract elements from the tuple using the index operator:
>>> myTuple[3] 42

The index used has to be a valid one:
>>> myTuple[4] IndexError: tuple index out of range

Keep in mind that tuples are immutable so trying to reassign an item is an error:
>>> myTuple[0] = "ABC" TypeError: ...

The tuple assignment feature allows packing and unpacking of tuples such that a tuple left of the assignment will be assigned all values from the tuple right of the assignment:
>>> flash = ("Berry", "Allen" , 27) >>> (fname, lname, age) = flash >>> fname 'Berry' >>> age 27

Tuples are often used for a sequence of values of heterogeneous types (e.g. fields of a database record or columns from a CSV file), while lists are often used for homogeneous items, such as a list of only numbers, or a list of only strings. But this is not a rule, it can be the other way around too.


def commonCharacterCount(s1, s2):
    map1 = {}
    map2 = {}
    answer = 0

    for i in range(len(s1)):
        char = s1[i]
        if char in map1:
            map1[char] += 1
        else:
            map1[char] = 1

    for i in range(len(s2)):
        char = s2[i]
        if char in map2:
            map2[char] += 1
        else:
            map2[char] = 1

    for i in range(ord('a'), ord('z')+1):
        char = chr(i)
        if char in map1 and char in map2:
            answer+=min(map1[char],map2[char])
    return answer


Learning Django
$ pip freeze                                                                                                                                       
argparse==1.2.1                                                                                                                                    
awscli==1.5.1                                                                                                                                      
bcdoc==0.12.2                                                                                                                                      
botocore==0.65.0                                                                                                                                   
chardet==2.0.1                                                                                                                                     
colorama==0.2.5                                                                                                                                    
dnspython==1.11.1                                                                                                                                  
docutils==0.12                                                                                                                                     
html5lib==0.999                                                                                                                                    
jmespath==0.4.1                                                                                                                                    
mercurial==2.8.2                                                                                                                                   
oauthlib==1.0.3                                                                                                                                    
pyasn1==0.1.7                                                                                                                                      
pycrypto==2.6.1                                                                                                                                    
pysolr==3.4.0                                                                                                                                      
python-apt==0.9.3.5ubuntu2                                                                                                                         
python-dateutil==2.2                                                                                                                               
python-debian==0.1.21-nmu2ubuntu2                                                                                                                  
python-twitter==2.2                                                                                                                                
requests==2.2.1                                                                                                                                    
requests-oauthlib==0.6.0                                                                                                                           
rsa==3.1.2                                                                                                                                         
six==1.5.2                                                                                                                                         
urllib3==1.7.1                                                                                                                                     
watson-developer-cloud==0.5.0                                                                                                                      
wsgiref==0.1.2                                                                                                                                     
              

Python/Django Command line
See Python Version
sudo apt-get install python-mysqldb

Install Python Package Manager (Pip)
sudo apt-get install python-pip

Getting in MySQL from Command Line
invisible@no-name { /var/www/html/django-course } » sudo mysql -u root -p

Install MySql Python DB
sudo apt-get install python-mysqldb

Login MySQL from command line
sudo mysql -u root -p

Grep history commands 
ps -aux | grep mysql

Find mySQL 
mysql> status

--------------
mysql Ver 14.14 Distrib 5.5.54, for debian-linux-gnu (x86_64) using readline 6.3

Connection id: 293
Current database:
Current user: root@localhost
SSL: Not in use
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server version: 5.5.54-0ubuntu0.14.04.1 (Ubuntu)
Protocol version: 10
Connection: Localhost via UNIX socket
Server characterset: latin1
Db characterset: latin1
Client characterset: utf8
Conn. characterset: utf8
UNIX socket: /var/run/mysqld/mysqld.sock
Uptime: 1 day 18 hours 5 min 37 sec

Threads: 1 Questions: 2242 Slow queries: 0 Opens: 205 Flush tables: 1 Open tables: 55 Queries per second avg: 0.014

Handle MySQL Migration from Django
invisible@no-name { /var/www/html/django-course } (master) » python manage.py migrate

Create DB, List DBs, Change active DB, List active DB tables
mysql> CREATE DATABASE todolist
mysql> SHOW DATABASES;
mysql> USE todolist;
mysql> SHOW tables;


What is Django?
Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design. Built by experienced developers, it takes care of much of the hassle of Web development, so you can focus on writing your app without needing to reinvent the wheel. It’s free and open source.
Ridiculously fast (to develop).
Django was designed to help developers take applications from concept to completion as quickly as possible.

Reassuringly secure.
Django takes security seriously and helps developers avoid many common security mistakes.

Exceedingly scalable.
Some of the busiest sites on the Web leverage Django’s ability to quickly and flexibly scale.

What is a .pyc file?
Python automatically compiles your script to compiled code, so called byte code, before running it. When a module is imported for the first time, or when the source is more recent than the current compiled file, a .pyc file containing the compiled code will usually be created in the same directory as the .py file.

if python is interpreted, why are there compiled files (.pyc vs .py)?

They contain byte code, which is what the Python interpreter compiles the source to. This code is then executed by Python's virtual machine.

Python's documentation explains the definition like this:

Python is an interpreted language, as opposed to a compiled one, though the distinction can be blurry because of the presence of the bytecode compiler. This means that source files can be run directly without explicitly creating an executable which is then run.


if python is interpreted, why are there compiled files?

.pyc contain the compiled bytecode of Python source files. The Python interpreter loads .pycfiles before .py files, so if they're present, it can save some time by not having to re-compile the Python source code. You can get rid of them if you want, but they don't cause problems, they're not big, and they may save some time when running programs.



Working with FIles

my_list = [i**2 for i in range(1,11)]

my_file = open("output.txt", "r+")

# Add your code below!
for item in my_list:
  my_file.write(str(item) + '\n')

my_file.close()
--------------------
my_file = ''
with open('text.txt', 'r+') as my_file:
  my_file.write('Hello there.')

if my_file.closed != True:
  my_file.close()

print my_file.closed



Classes

But what makes "Eric" a string and my_dict a dictionary? The fact that they're instances of the str and dict classes, respectively. A class is just a way of organizing and producing objects with similar attributes and methods.

Creating a Class
class Animal(object):
  """Makes cute animals."""
  is_alive = True
  def __init__(self, name, age):
  self.name = name
  self.age = age
  # Add your method here!
  def description(self):
  print self.name
  print self.age

hippo = Animal("Thomas", 33)
hippo.description()

Class Methods and Instantiation
class ShoppingCart(object):
  """Creates shopping cart objects
  for users of our fine website."""
  items_in_cart = {}
  def __init__(self, customer_name):
  self.customer_name = customer_name

  def add_item(self, product, price):
  """Add product to the cart."""
  if not product in self.items_in_cart:
  self.items_in_cart[product] = price
  print product + " added."
  else:
  print product + " is already in the cart."

  def remove_item(self, product):
  """Remove product from the cart."""
  if product in self.items_in_cart:
  del self.items_in_cart[product]
  print product + " removed."
  else:
  print product + " is not in the cart."

my_cart = ShoppingCart('Jordan')
my_cart.add_item('bandaids',.99)
my_cart.add_item('milk',1.99)
my_cart.add_item('milk',1.99)

# bandaids added.
# milk added.
# milk is already in the cart.

Class Inheritance
class Customer(object):
  """Produces objects that represent customers."""
  def __init__(self, customer_id):
  self.customer_id = customer_id

  def display_cart(self):
  print "I'm a string that stands in for the contents of your shopping cart!"

class ReturningCustomer(Customer):
  """For customers of the repeat variety."""
  def display_order_history(self):
  print "I'm a string that stands in for your order history!"

monty_python = ReturningCustomer("ID: 12345")
monty_python.display_cart()
monty_python.display_order_history()

Overriding Parent attributes
class Employee(object):
  """Models real-life employees!"""
  def __init__(self, employee_name):
  self.employee_name = employee_name

  def calculate_wage(self, hours):
  self.hours = hours
  return hours * 20.00

# Add your code below!
class PartTimeEmployee(Employee):
  def calculate_wage(self, hours):
  self.hours = hours
  return hours * 12.00

Call to overriden method or attribute
class Employee(object):
  """Models real-life employees!"""
  def __init__(self, employee_name):
  self.employee_name = employee_name

  def calculate_wage(self, hours):
  self.hours = hours
  return hours * 20.00

# Add your code below!
class PartTimeEmployee(Employee):
  def calculate_wage(self, hours):
  self.hours = hours
  return hours * 12.00

  def full_time_wage(self, hours):
  self.hours = hours
  return super(PartTimeEmployee, self).calculate_wage(hours)

milton = PartTimeEmployee('Milton')
print milton.full_time_wage(10)

Another Class Example
class Triangle(object):
  number_of_sides = 3
  def __init__(self, angle1, angle2, angle3):
  self.angle1 = angle1
  self.angle2 = angle2
  self.angle3 = angle3
  def check_angles(self):
  if self.angle1 + self.angle2 + self.angle3 == 180:
  return True
  else:
  return False

my_triangle = Triangle(90,30,60)
print my_triangle.number_of_sides
print my_triangle.check_angles()

class Equilateral(Triangle):
  angle = 60
  def __init__(self):
  self.angle1 = self.angle
  self.angle2 = self.angle
  self.angle3 = self.angle

Representation
class Point3D(object):
  def __init__(self, x, y, z):
  self.x = x
  self.y = y
  self.z = z
  def __repr__(self):
  return '(%d, %d, %d)' % (self.x, self.y, self.z)

my_point = Point3D(1, 2, 3)
print my_point


Bitwise Operations

Overview
print 5 >> 4 # Right Shift
print 5 << 1 # Left Shift
print 8 & 5 # Bitwise AND
print 9 | 4 # Bitwise OR
print 12 ^ 42 # Bitwise XOR
print ~88 # Bitwise NOT


Binary Counting
one = 0b1
two = 0b10
three = 0b11
four = 0b100
five = 0b101
six = 0b110
seven = 0b111
eight = 0b1000
nine = 0b1001
ten = 0b1010
eleven = 0b1011
twelve = 0b1100


Powers of 2
2**0 = 1
2**1 = 2
2**2 = 4
2**3 = 8
2**4 = 16
2**5 = 32
2**6 = 64
2**7 = 128
2**8 = 256
2**9 = 512
2**10 = 1024

======================
Convert an input to target base-x

print bin(1)
print bin(2)
print bin(3)
print bin(4)
print bin(5)
# 0b1
# 0b10
# 0b11
# 0b100
# 0b101

print oct(1)
print oct(2)
print oct(3)
print oct(4)
print oct(5)
# 01
# 02
# 03
# 04
# 05

print hex(1)
print hex(2)
print hex(3)
print hex(4)
print hex(5)
# 0x1
# 0x2
# 0x3
# 0x4
# 0x5

=======================

print int("1",2)
print int("10",2)
print int("111",2)
print int("0b100",2)
print int(bin(5),2)
# Print out the decimal equivalent of the binary 11001001.
print int("0b11001001",2)

#1
#2
#7
#4
#5
#201

=======================
Bit Shift Operator
shift_right = 0b1100 >> 2
shift_left = 0b1 << 2

# Your code here!
print bin(shift_right)
print bin(shift_left)

# 0b11
# 0b100

===========================

# a: 00101010 42
# b: 00001111 15
#===================
# a & b: 00001010 10

Bitwise AND
print bin(0b1110 & 0b101)
# 0b100

=====================

Bitwise OR
print bin(0b1110 | 0b101)
# 0b1111

=====================

Bitwise XOR
print bin(0b1110 ^ 0b101)
# 0b1011

=====================
Bitwise NOT
print ~1
# -2
print ~2
# -3
print ~3
# -4
print ~42
# -43
print ~123
# -124


Bit Mask Checking if single bit on or off
def check_bit4(input):
  num = input
  mask = 0b1000
  desired = num & mask
  if desired > 0:
  return "bit was on"
  else:
  return "bit was off"

print check_bit4(8)


Turn on a bit with a bitmask
a = 0b10111011
mask = 0b100
desired = a | mask
print bin(desired)

# 0b10111111


Flip all bits in an octet
a = 0b11101110
mask = 0b11111111 
desired = a ^ mask
print bin(desired)

# 0b10001


Slide a bitmask into place using  the << BIT SHIFT operator "n" bits, then flipping the "nth" bit of "number" with the XOR operator
def flip_bit(number, n):
  mask = (0b1 << n-1)    
  result = number ^ mask
  return bin(result)

print flip_bit(7, 2)

# 0b101

List Comprehension, lambda Review

threes_and_fives = [x for x in range(1,16) if x % 3 == 0 or x % 5 == 0]
print threes_and_fives
# [3, 5, 6, 9, 10, 12, 15]


garbled = "!XeXgXaXsXsXeXmX XtXeXrXcXeXsX XeXhXtX XmXaX XI"
message = garbled[::-2]
print message
# I am the secret message!


garbled = "IXXX aXXmX aXXXnXoXXXXXtXhXeXXXXrX sXXXXeXcXXXrXeXt mXXeXsXXXsXaXXXXXXgXeX!XX"

message = filter(lambda x: x != 'X', garbled)
print message


List Methods in Python
movies = {
"Monty Python and the Holy Grail": "Great",
"Monty Python's Life of Brian": "Good",
"Monty Python's Meaning of Life": "Okay"
}

print movies.items()
[("Monty Python's Life of Brian", 'Good'), ("Monty Python's Meaning of Life", 'Okay'), ('Monty Python and the Holy Grail', 'Great')]

print movies.keys()
["Monty Python's Life of Brian", "Monty Python's Meaning of Life", 'Monty Python and the Holy Grail']

print movies.values()
['Good', 'Okay', 'Great']


Anonymous Functions

One of the more powerful aspects of Python is that it allows for a style of programming called functional programming, which means that you're allowed to pass functions around just as if they were variables or values. Sometimes we take this for granted, but not all languages allow this!

Check out the code at the right. See the lambda bit? Typing

lambda x: x % 3 == 0

Is the same as

def by_three(x):
    return x % 3 == 0

Only we don't need to actually give the function a name; it does its work and returns a value without one. That's why the function the lambda creates is an anonymous function.
Example of an anonymous (lambda) function
languages = ["HTML", "JavaScript", "Python", "Ruby"]
print filter(lambda x: x == "Python", languages)
# ['Python']

squares = [x**2 for x in range(1, 11)]
print filter(lambda x: x > 30 and x < 70, squares)
# [36, 49, 64]


List Comprehensions
doubles_by_3 = [x*2 for x in range(1,100) if (x*2) % 3 == 0]
print doubles_by_3
# [6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 96, 102, 108, 114, 120, 126, 132, 138, 144, 150, 156, 162, 168, 174, 180, 186, 192, 198]

even_squares = [x ** 2 for x in range(1,11) if (x ** 2) % 2 == 0]
print even_squares
# [4, 16, 36, 64, 100]

cubes_by_four = [x ** 3 for x in range(1, 11) if (x ** 3) % 4 == 0]
print cubes_by_four
#[8, 64, 216, 512, 1000]

evens_to_50 = [i for i in range(51) if i % 2 == 0]
print evens_to_50
# [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50]

cubes_by_four = [x ** 3 for x in range(1, 11) if (x ** 3) % 4 == 0]
print cubes_by_four
# [8, 64, 216, 512, 1000]

l = [i ** 2 for i in range(1, 11)]
# Should be [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

print l[2:9:2]
#[9, 25, 49, 81]

my_list = range(1, 11) # List of numbers 1 - 10

# Add your code below!
print my_list[::2]
# [1, 3, 5, 7, 9]

my_list = range(1, 11)
# Reverse a list!
backwards = my_list[::-1]
print backwards

to_21 = range(1,22)
print to_21
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]

odds = to_21[::2]
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21]
print odds

middle_third = to_21[7:14:]
[8, 9, 10, 11, 12, 13, 14]
print middle_third


Basic Statistics Algorithms in Python (sum, avg, variance, std deviation):
grades = [100, 100, 90, 40, 80, 100, 85, 70, 90, 65, 90, 85, 50.5]

def print_grades(grades):
  for grade in grades:
  print grade

print 'Grades:', print_grades(grades)


def grades_sum(grades):
  total = 0
  for grade in grades: 
  total += grade
  return total

print 'Sum:', grades_sum(grades)


def grades_average(grades):
  sum_of_grades = grades_sum(grades)
  average = sum_of_grades / float(len(grades))
  return average

print 'Average:', grades_average(grades)


def grades_variance(scores):
  average = grades_average(scores)
  variance = 0
  for score in scores:
  variance += (average - score) ** 2
  return variance / len(scores)

print 'Variance:', grades_variance(grades)
variance = grades_variance(grades)

def grades_std_deviation(variance):
  return variance ** 0.5

print 'Standard Deviation:', grades_std_deviation(variance)



Each print statement gets its own line by default





Built-in Functions


abs()divmod()input()open()staticmethod()
all()enumerate()int()ord()str()
any()eval()isinstance()pow()sum()
basestring()execfile()issubclass()print()super()
bin()file()iter()property()tuple()
bool()filter()len()range()type()
bytearray()float()list()raw_input()unichr()
callable()format()locals()reduce()unicode()
chr()frozenset()long()reload()vars()
classmethod()getattr()map()repr()xrange()
cmp()globals()max()reversed()zip()
compile()hasattr()memoryview()round()__import__()
complex()hash()min()set()
delattr()help()next()setattr()
dict()hex()object()slice()
dir()id()oct()sorted()

append: Appends object at end.

x = [1, 2, 3]
x.append([4, 5])print (x)

gives you: [1, 2, 3, [4, 5]]


extend: Extends list by appending elements from the iterable.

x = [1, 2, 3]
x.extend([4, 5])print (x)
gives you: [1, 2, 3, 4, 5]


Battleship Game
from random import randint

board = []

for x in range(5):
  board.append(["O"] * 5)

def print_board(board):
  for row in board:
  print " ".join(row)

print "Let's play Battleship!"
print_board(board)

def random_row(board):
  return randint(0, len(board) - 1)

def random_col(board):
  return randint(0, len(board[0]) - 1)

ship_row = random_row(board)
ship_col = random_col(board)
print ship_row, ',', ship_col

# Everything from here on should go in your for loop!
# Be sure to indent four spaces!
for turn in range(4):
  print "Turn", turn + 1
  guess_row = int(raw_input("Guess Row:"))
  guess_col = int(raw_input("Guess Col:"))

  if guess_col == ship_row and guess_row == ship_col:
  print "Congratulations! You sunk my battleship!"
  break
  else:
  if (guess_row < 1 or guess_row > 5) or (guess_col < 1 or guess_col > 5):
  print "Oops, that's not even in the ocean."
  elif(board[guess_row-1][guess_col-1] == "X"):
  print "You guessed that one already."
  else:
  print "You missed my battleship!"
  board[guess_row-1][guess_col-1] = "X"
  # Print (turn + 1) here!
  print_board(board)
  if turn == 3:
  print "Game Over."

Take text input, split to array by words, sort, reverse the array, print each key and value to a string
Splitting input into and array, creating histogram from a hash map
puts 'Yes?'
text = gets.chomp
words = text.split()
frequencies = Hash.new(0)
words.each { |word| frequencies[word] += 1 }
frequencies = frequencies.sort_by do |word, count| 
  count
end
frequencies.reverse!

frequencies.each do |key, count|
  puts key + ' ' + count.to_s
end


Iterate through lists/arrays
s = [["ham", "swiss"], ["turkey", "cheddar"], ["roast beef", "gruyere"]]
s.each { |sub_array| sub_array.each { |x| puts x } }

Output:
ham
swiss
turkey
cheddar
roast beef
gruyere

Iterate through hash maps
secret_identities = {
  "The Batman" => "Bruce Wayne",
  "Superman" => "Clark Kent",
  "Wonder Woman" => "Diana Prince",
  "Freakazoid" => "Dexter Douglas"
}

secret_identities.each { |identity, name| puts "#{identity}: #{name}" }

lunch_order = {
  "Ryan" => "wonton soup",
  "Eric" => "hamburger",
  "Jimmy" => "sandwich",
  "Sasha" => "salad",
  "Cole" => "taco"
}

lunch_order.each { |x,y| puts y }




Get the median of a list

def median(numbers):
  count = 0
  median = float(0)
  sortedList = sorted(numbers)
  count = len(sortedList)
  print 'sortedList:', sortedList, 'count:', count
  if count == 1:
  median = 1
  elif count % 2 == 0:
  medianIndex1 = count / 2 - 1
  medianIndex2 = medianIndex1 + 1
  median = (float(sortedList[medianIndex1])+float(sortedList[medianIndex2]))/2
  print 'sortedList[medianIndex1]:' sortedList[medianIndex1]
  print 'sortedList[medianIndex2]:' sortedList[medianIndex2]
  print 'medianIndex1:', medianIndex1, 'medianIndex2:', medianIndex2, 'median:', median
  else:
  medianIndex = count / 2
  median = sortedList[medianIndex]
  print 'medianIndex:', medianIndex, 'median:', median
  return median

print 'ok:', median([4,5,5,4])

// REFACTORED BELOW TO 

def median(numbers):
  median = 0
  sortedList = sorted(numbers)
  count = len(sortedList)

  if count % 2 == 0:
  medianIndex1 = count / 2 - 1
  medianIndex2 = medianIndex1 + 1
  median = (float(sortedList[medianIndex1])+float(sortedList[medianIndex2]))/2
  else:
  medianIndex = count / 2
  median = sortedList[medianIndex]
  return median

print median([1])


Remove duplicates from a list
def remove_duplicates(elements):
  register = []
  for element in elements:
  if element not in register:
  register.append(element)
  print register
  return register

remove_duplicates([1,1,2,2,3,3])


Get the product of all items in a list
def product(integers):
  product = 1
  for integer in integers:
  product = product * integer
  return product

print product([2,3,4])

Remove odd numbers from a list
def purify(numbers):
  clean = []
  for number in numbers:
  if number % 2 == 0:
  clean.append(number)
  return clean

print purify([1,2,3,4,5,6,7,8,9])



Count words in a string
  def count(sequence, item):
  n = 0
  array = sequence.split()
  for word in array:
  if word.lower() == item.lower():
  n = n + 1
  return n

print count("hey hey hey", "hey")

Count occurences in a list
def count(sequence, item):
  found = 0
  for word in sequence:
  if word == item:
  found = found + 1
  return found

print count([1,2,1,1], 1)


Match and censor a Word: 
def censor(text, curse):
  words = text.split()

  for word in words:
  if word.lower() == curse.lower():
  i = words.index(word)
  words[i] = '*' * len(word)

  return ' '.join(words)

print censor("this shit is wack, shit", "hack")


Score a word in Scrabble
score = {"a": 1, "c": 3, "b": 3, "e": 1, "d": 2, "g": 2, 
  "f": 4, "i": 1, "h": 4, "k": 5, "j": 8, "m": 3, 
  "l": 1, "o": 1, "n": 1, "q": 10, "p": 3, "s": 1, 
  "r": 1, "u": 1, "t": 1, "w": 4, "v": 4, "y": 4, 
  "x": 8, "z": 10}

def scrabble_score(word):
  sscore = 0
  for i in range(len(word)):
  sscore = sscore + score[word[i].lower()]
  return sscore

print scrabble_score('Helix')


Remove all Vowels from a string 
def anti_vowel(text):
  anti = ''
  for i in range(len(text)):
  if text[i].lower() != 'a' and text[i].lower() != 'e' and text[i].lower() != 'i' and text[i].lower() != 'o' and text[i].lower() != 'u':
  anti = anti + text[i]
  return anti

print anti_vowel("Hey You!")


Reverse a String
def reverse(text):
  rev = ''
  for i in range(len(text)):
  rev = rev + text[len(text)-1-i]    
  print rev
  return rev

reverse('word')


If is Prime

def is_prime(x):
  prime = True
  if x < 2:
  prime = False
  for n in range(2, x):
  if x % n == 0:
  prime = False
  break
  else:
  prime = True
  return prime


Factorial
def factorial(x):
  f = 1
  for i in range(x):
  f *=i+1
  print f
  return f

print factorial(20)

1
2
6
24
120
720
5040
40320
362880
3628800
39916800
479001600
6227020800
87178291200
1307674368000
20922789888000
355687428096000
6402373705728000
121645100408832000
2432902008176640000
2432902008176640000


Sum Digits
def digit_sum(n):
  s = 0
  while n:
  s += n % 10
  n //= 10
  print s
  return s

digit_sum(555)


Function for checking if data is an integer
def is_int(x):
  if x == 0 or round(x, 0)/x == 1:
  return True
  else:
  return False

print is_int(-2)

Enumerate
choices = ['pizza', 'pasta', 'salad', 'nachos']

print 'Your choices are:'
for index, item in enumerate(choices):
  print index+1, item


Guessing Game
from random import randint

# Generates a number from 1 through 10 inclusive
random_number = randint(1, 10)

guesses_left = 3
# Start your game!
while guesses_left > 0:
  guess = str(raw_input("Your guess:"))
  if guess == random_number:
  print 'You win!'
  break
  guesses_left -= 1

else:
 print 'You lose.'

Lists and Dictionaries
lloyd = {
    "name": "Lloyd",
    "homework": [90.0, 97.0, 75.0, 92.0],
    "quizzes": [88.0, 40.0, 94.0],
    "tests": [75.0, 90.0]
}
alice = {
    "name": "Alice",
    "homework": [100.0, 92.0, 98.0, 100.0],
    "quizzes": [82.0, 83.0, 91.0],
    "tests": [89.0, 97.0]
}
tyler = {
    "name": "Tyler",
    "homework": [0.0, 87.0, 75.0, 22.0],
    "quizzes": [0.0, 75.0, 78.0],
    "tests": [100.0, 100.0]
}

students = [lloyd,alice,tyler]
# Add your function below!

def average(numbers):
    total = sum(numbers)
    total = float(total)
    total = total / len(numbers)
    return total

def get_average(student):
    homework = average(student["homework"])
    quizzes = average(student["quizzes"])
    tests = average(student["tests"])
    return homework * .1 + quizzes * .3 + tests * .6

def get_letter_grade(score):
    if score >= 90:
        return "A"
    elif score >= 80:
        return "B"
    elif score >= 70:
        return "C"
    elif score >= 60:
        return "D"   
    else:
        return "F"

def get_class_average(students):
    results = []
    for student in students:
        results.append(get_average(student))
    return average(results)

print get_class_average(students)
print get_letter_grade(get_class_average(students))


def hotel_cost(nights):
    return 140 * nights

def plane_ride_cost(city):
    if city == "Charlotte":
        return 183
    elif city == "Tampa":
        return 220
    elif city == "Pittsburgh":
        return 222
    elif city == "Los Angeles":
        return 475

def rental_car_cost(days):
    total = 40 * days
    if days >= 7:
        total -= 50
    elif days >= 3:
        total -= 20
    return total

def trip_cost(city, days):
    return rental_car_cost(days) + hotel_cost(days) + plane_ride_cost(city)


PythonForDataScience.pdf

beginners_python_cheat_sheet_pcc.pdf
beginners_python_cheat_sheet_pcc_dictionaries.pdfbeginners_python_cheat_sheet_pcc_functions.pdfbeginners_python_cheat_sheet_pcc_classes.pdf

beginners_python_cheat_sheet_pcc_if_while.pdfbeginners_python_cheat_sheet_pcc_lists.pdf