Python

Raw Notes: Not refined

Python- Compiled or Interpreted?

Python will fall under byte code interpreted. . py source code is first compiled to byte code as .pyc. This byte code can be interpreted 

From: http://i-techh.blogspot.in/p/c-compilation.html
Compiler vs Interpretor:
Interpreter: Reads a statement from input, converts to intermediate code, executes. Stops if error, else read next statement.
Compiler reads whole source, creates token, check semantics, generates intermediate code, executes whole program

String
"Hello" or 'Hello'

+ : concatenate
str1="Hello"  
str2='world'
concat=str1+str2
print concat  #HelloWorld. to add space, + ' ' +

str3='123'
str3=str3+1  //TypeError: cannot concatenate 'str' and 'int' objects
x=(int)str3 + 1
print x

name=raw_input(Enter string:')  #raw_input return value in string
Enter String: 
print name

name="hack"
letter=name[1]  #a
n=3
letter=name[n-1] #c
letter=name[6] IndexError: string index out of range.

builtin 
len(name)=4

print n,name[n] 

Loop through String
-------------------
for letter in name:  #for each letter in variable name
  print letter
  
idx=0
while idx < len(name):
  print name[idx]


name="jack"
print name[0:2] #slicing, 0 upto 2, not include 2
print name[1:] #slicing 1, upto 1, not include 2
print name[2:10] #no warning/error, prints ck
print name[2:] #from 2 till end of string

>>>'ack' in name:
True

String Comparison
-----------------
if name=='jack'
    print "Hi Jack"

if name<'jack'
    print "Word " + name + " comes before Jack"
elif name<'jack'
    print "Word " + name + " comes before Jack"
else
    print "Hello Jack!!"

String Library
--------------
Does not modify original variable

word='Hello World'
print word.lower() #hello world
print work #Hello World, unchanged
print 'Hi Bye'.lower()  #hi bye

name="Jack"
a=name.find(ac)  #1

name= ' Jack '
name.lstrip/rstrip/strip  #'Jack '/' Jack'/'Jack'

type(name)
String

dir(name)




Files

List: Allows to put many values in a single variable, like for loop.
Ordered sequence

buddy=['Jack', 'Jill', 'Hook']  #list, within []
  buddy[0]=Jack
  len(buddy)=3
  range(len(buddy)) = [0,1,2]
lsit=[1,[2,3],4,5]  #nested list

Strings immutable: can not change their content, must make new string. 
    Like, strip() does not change list, need to create new by assignment
str=str.strip()
Lists mutable: can change any element, like buddy[0]='Hill'

fruit="Banana"
fruit[0]='b'
print fruit #Banana. String not mutable.

Range: generates list
range(3) = [0,1,2]

for itr in range(len(buddy)):
   budd=buddy[i]
   print "Hi ", budd

concat list with +
   a=[1,2,3]
   b=[4,5,6]
   c=a+b #c=[1,2,3,4,5,6]
   
Slice list
   a[1:2] #from1, upto 2, not including 2


stuff=list()
stuff.apend('First')
stuff.apend(1)
print stuff #[First, 1]

1 in studd: True
'Second' in studd: False

sort list
buddy=['Jack', 'Jill', 'Hook']  #list, within []
buddy.sort() #modifies buddy. ['Hook', 'Jack', 'Jill']


Prebuilt routines
lst=[1,2,3,4,5,6,100]
print max/min/sum(lst) #100,1,121


while True:
    inp=raw_input("Enter number: ")
if inp=='done':break


Merge String and List
str1="Hi There hello"
stuff=str.split() #stuff is list containing split of str1
print stuff
print len(stuff) #3

split
can split on char, say ':' as delimiter char.
If no delimiter gives, split takes many spaces as single space as splitter

double split
mail="abc@email.com Sat Feb "
addr=mail.split() #0: abc@email.com
pieces=addr.split('@') #abc, email.com

list is linear collection of values that stay in that order.
dictionary does not have order, they are key-val pair.

dictionaries : bag of values each with its own level
bag=dict()
bag['amount']=20
bag['toffee']=3
bag['coins']=10
bag['toffee']=bag['toffee']+4
print bag
#{'amount': 20, 'coins': 10, 'toffee': 7}


blank={}


print dictionary['key'] 
KeyErr: key is not in dictionary

print 'key' in dictionary
False

if name not in dictionary:
  dictionary[name]=1
else
  dictionary[name]=dictionary[name]+1

print dictionary get(name, 0) #0 default value if name not present in dictionary
Tells if name is in dictionary


if name in dict:
  print dict[name]
else:
  print 0
  
Can be re-written as

print dict.get(name,0)

#Counting with get
counts=dict()
names=['jack', 'jill', 'jack']
for name in names:
  counts[name]=counts.get(name,0)+1
print counts

#Convert Dict to List
dict=['key1':1, 'key2':3; 'key3':5]
print list(dict) #['key1', 'key2', 'key3']
print dict.keys()
print dict.values()
print dict.items() #[('key1',1), ('key2', 2), ('key3',5)]  #Tuples
for a,b in dict.items():
  print a,b #key1, 1\nkey2,2\nkey3,4


  
Tuples
Non changeable list
x=('Jack', 'Jill', 'John')  #Has (), not []
print x[2]=John
Not allowed: x.sort() x.append(5) x.reverse()
Efficient, quicker. 

tuples over list: when need to create temp var and discard.

#(x,y)=(4, 'key') #OK. var left, const right
#a,b=(4, 'key') #OK.
#for a,b in dic.items()

>>> (0,1,2000)<(0,1,100)
False

t=dict.items(): list of tuples
t.sort() #OK
t=sorted(dic.items())


Sort by values
tmp=list()
for k,v in dic.items():
  tmp.append( (v,k,) )
tmp.sort[reverse=True]  #Reverse sort

print sorted( [ (v,k) for k,v in dic.itemd() ]) #dic sorted by val


List is a class for which method are obtained by dir

DIR
l=list()
dir: gives capabilities

>>> dir(l)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

t=tuple()
>>> dir(t)
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index']

>>> d=dict()
>>> dir(d)
['__class__', '__cmp__', '__contains__', '__delattr__', '__delitem__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'has_key', 'items', 'iteritems', 'iterkeys', 'itervalues', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']



class C:
  var=0
  
  def __init__(self):
    print "constructor" #optional, used to setup variables.

  def mod_x(self):
    self.x=self.x+1;
print "Self x is ", self.x

  def __del__(self):
    print "destructor", self.x  #optional, rarely used

type(class_instance) #Type <type 'instance'>


Advanced Python
OOP: 

Class in Python

self: Reference to new object.

Example 1: name, health, inventory are fields inside object self.

class Char:
    def __init__(self, n, start_health):  #create new object
        self.name = n
        self.health = start_health
        self.inventory = []   #Though no return, it actually returns new object 
        
    def __str__(self):  #creates string and returns it for printing
        s  = "Name: " + self.name
        s += " Health: " + str(self.health)
        s += " Inventory: " + str(self.inventory)
        return s
    
    def grab(self, item):
        self.inventory.append(item)
        
    def get_health(self):
        return self.health
    
def example():
    me = Char("Bob", 20)  #calls __init__
    print str(me)   #calls __str__
    me.grab("pencil")
    me.grab("paper")
    print str(me)
    print "Health:", me.get_health()
    
example()

Example 2: Create a Ball object, move it in a domain.

# ball physics code for generic 2D domain
# the functions inside() and normal() encode the shape of the ennvironment

import simplegui
import random
import math

# Canvas size
width = 600
height = 400

# Ball traits
radius = 20
color = "White"

# math helper function
def dot(v, w):
    return v[0] * w[0] + v[1] * w[1]

class RectangularDomain:
    def __init__(self, width, height):
        self.width = width
        self.height = height
        self.border = 2

    # return if bounding circle is inside the domain    
    def inside(self, center, radius):
        in_width = ((radius + self.border) < center[0] < 
                    (self.width - self.border - radius))
        in_height = ((radius + self.border) < center[1] < 
                     (self.height - self.border - radius))
        return in_width and in_height

    # return a unit normal to the domain boundary point nearest center
    def normal(self, center):
        left_dist = center[0]
        right_dist = self.width - center[0]
        top_dist = center[1]
        bottom_dist = self.height - center[1]
        if left_dist < min(right_dist, top_dist, bottom_dist):
            return (1, 0)
        elif right_dist < min(left_dist, top_dist, bottom_dist):
            return (-1, 0)
        elif top_dist < min(bottom_dist, left_dist, right_dist):
            return (0, 1)
        else:
            return (0, -1)

    # return random location
    def random_pos(self, radius):
        x = random.randrange(radius, self.width - radius - self.border)
        y = random.randrange(radius, self.height - radius - self.border)
        return [x, y]

    # Draw boundary of domain
    def draw(self, canvas):
        canvas.draw_polygon([[0, 0], [self.width, 0], 
                             [self.width, self.height], [0, self.height]],
                             self.border*2, "Red")
        
class CircularDomain:
    def __init__(self, center, radius):
        self.center = center
        self.radius = radius
        self.border = 2
        
    # return if bounding circle is inside the domain    
    def inside(self, center, radius):
        dx = center[0] - self.center[0]
        dy = center[1] - self.center[1]
        dr = math.sqrt(dx ** 2 + dy ** 2)
        return dr < (self.radius - radius - self.border)

    # return a unit normal to the domain boundary point nearest center
    def normal(self, center):
        dx = center[0] - self.center[0]
        dy = center[1] - self.center[1]
        dr = math.sqrt(dx ** 2 + dy ** 2)
        return [dx / dr, dy / dr]
    
    # return random location
    def random_pos(self, radius):
        r = random.random() * (self.radius - radius - self.border)
        theta = random.random() * 2 * math.pi
        x = r * math.cos(theta) + self.center[0]
        y = r * math.sin(theta) + self.center[1]
        return [x, y]
        
    # Draw boundary of domain
    def draw(self, canvas):
        canvas.draw_circle(self.center, self.radius, self.border*2, "Red")
    
class Ball:
    def __init__(self, radius, color, domain):
        self.radius = radius
        self.color = color
        self.domain = domain
        
        self.pos = self.domain.random_pos(self.radius)
        self.vel = [random.random() + .1, random.random() + .1]
        
    # bounce
    def reflect(self):
        norm = self.domain.normal(self.pos)
        norm_length = dot(self.vel, norm)
        self.vel[0] = self.vel[0] - 2 * norm_length * norm[0]
        self.vel[1] = self.vel[1] - 2 * norm_length * norm[1]
    

    # update ball position
    def update(self):
        self.pos[0] += self.vel[0]
        self.pos[1] += self.vel[1]
        if not self.domain.inside(self.pos, self.radius):
            self.reflect()

    # draw
    def draw(self, canvas):
        canvas.draw_circle(self.pos, self.radius, 1, 
                           self.color, self.color)
        

# generic update code for ball physics
def draw(canvas):
    ball.update()
    field.draw(canvas)
    ball.draw(canvas)

field = RectangularDomain(width, height)
# field = CircularDomain([width/2, height/2], 180)
ball = Ball(radius, color, field)
        
frame = simplegui.create_frame("Ball physics", width, height)

frame.set_draw_handler(draw)

frame.start()

Reference:
Coursera Python-Data structure Course [The prof keeps things interesting]
https://www.coursera.org/learn/interactive-python-2/lecture/i3Wbh/object-oriented-programming-1

No comments:

Post a Comment