l = [] # List
d = {} # Dict
t = () # tuples
s = '' # strings
       # ...

"""
Explanation: Everything is an Object
So what objects do we know
Build-in types:
End of explanation
"""


fobj = open('test.dat', mode='w')

"""
Explanation: File objects:
End of explanation
"""


import numpy as np

ary = np.linspace(0, 2*np.pi, 200)

"""
Explanation: Numpy arrays
End of explanation
"""


from matplotlib import pyplot as plt
import numpy as np

%matplotlib inline

fig = plt.figure(figsize=(20,5))      # Figure object

ax0 = fig.add_subplot(121)  # Axes object
ax1 = fig.add_subplot(122)  # Axes object

x = np.linspace(0, 2*np.pi, 200)
line, = ax0.plot(x, np.sin(x)) # Line1d object

x = np.linspace(0, 2*np.pi, 200)
y = np.linspace(0, 2*np.pi, 200)
img = ax1.imshow(np.random.random((10,10))) # Image object

fig.tight_layout()

"""
Explanation: Plots contain many objects
End of explanation
"""


# Containg data
ary = np.random.random(100)

ary[0:10]

# Methods
ary.max() # Maximum element
ary.sum() # Sum of all elements
          # ...

# Operators
ary + 2  # Arithmetic
ary[2]   # Indexing
ary[3:4] # Slicing
         # ...

"""
Explanation: But what is Object-oriented programming ?
<i>"Object-oriented programming (OOP) is a programming paradigm based on the concept of <b>"objects"</b>, which may contain data, in the form of fields, often known as <b>attributes</b>; and code, in the form of procedures, often known as <b>methods</b>. A distinguishing feature of objects is that an object's procedures can access and often modify the data fields of the object with which they are associated (objects have a notion of "this" or <b>"self"</b>). In OO programming, computer programs are designed by making them out of objects that interact with one another".</i>
Further features of Oo-Programming: Encapsulation, Operator Overloading, Inheritance, Polymorphism, ...
End of explanation
"""


class MyObject:
    pass

"""
Explanation: How to create objects
Defining a minimum class
End of explanation
"""


a = MyObject()
b = MyObject()
c = MyObject()

a, b, c

"""
Explanation: Objects are instances of classes
End of explanation
"""


import datetime

class Person:

    def __init__(self, first_name, last_name, birthday, email_address):
        self.first_name = first_name
        self.last_name = last_name
        self.birthday = birthday
        self.email_address = email_address
       
    def age(self):
        today = datetime.date.today()
        born = datetime.date(*[int(field) for field in self.birthday.split('/')])
        return today.year - born.year - ((today.month, today.day) < (born.month, born.day))
      
    def email(self, message):
        print('Sending email to {} {} ({})'.format(self.first_name, self.last_name, self.email_address))   
        print(message)

harry = Person('Harry', 'Potter', '1980/7/31', 'harry@hogwarts.uk')

harry.email('Hello Harry')

harry.age()

"""
Explanation: Building something more useful
End of explanation
"""


contact_book = []

contact_book.append(Person('Harry', 'Potter', '1980/7/31', 'harry@hogwarts.uk'))
contact_book.append(Person('Albert', 'Einstein', '1879/03/14', 'albert@einstein.com'))
contact_book.append(Person('Ernst', 'August', '1771/6/5', 'ernst@koeningreich_hannover.de'))
contact_book.append(Person('Karl', 'Marx', '1818/5/5', 'marx@revolution.su'))

"""
Explanation: Contact Book
End of explanation
"""


for contact in contact_book:
    if contact.age() >= 40: 
        spam = 'You are {} years old.\nClick here to buy some blue pills.\n'.format(contact.age())
    
        contact.email(spam)

"""
Explanation: Send some spam
End of explanation
"""


