<jupyter_start><jupyter_text>Object Oriented Programming Basic Python1. Variables;2. Flow Control;3. Functions;4. Data structure. Basic Object Oriented Programming1. Classes;2. Attributes;3. Methods;4. Inheritance. Overview of PythonWhat is Python?Python is a programming language.A programming language allows you to write a program which is a sequence of instructions that specifies how to perform a computation.When writing a program you need two things:1. Something to save the code (a text editor for example)2. Something to run the codeWe will be using a combination of these 2 things called notebooks.<jupyter_code>print('ola')
2**3<jupyter_output>ola<jupyter_text>Variables Character variables:<jupyter_code>string = "Hello world"
num = complex(2,-3) + complex(2,2)
print(num)
print(string)
print(string)
print(string)
print(string)<jupyter_output>(4-1j)
Hello world
Hello world
Hello world
Hello world<jupyter_text>Numeric variables:<jupyter_code>num_1 = 2
num_2 = 3.0
num_1 + num_2<jupyter_output><empty_output><jupyter_text>String manipulation<jupyter_code>#We define a variable called String 
# (note that # allows me to comment my code)
string = "My name is Vince"
#Let's get the 5th letter of String 
# (Note that Python starts counting at 0):
string[2]
string[1:4]
index_of_v = string.index("V")
index_of_v
print(string[index_of_v:])
print(string[:index_of_v])<jupyter_output>Vince
My name is<jupyter_text>Numeric manipulation<jupyter_code>num = 3

# The following two lines are equivalent
num = num + 1
num += 1
num
num -= 2
num *= 3
num **= 2
num<jupyter_output><empty_output><jupyter_text>Flow control- In Python indentation is important!- In all languages indentation is good practice, in Python it is a requirement. If statements<jupyter_code>n = 8
if n <= 5:
    value = 1
elif n % 2 == 0:  
    value = 2
else: 
    value = 3
value<jupyter_output><empty_output><jupyter_text>While loops<jupyter_code>count = 0  
total = 0 
while count < 100: 
    count += 1  
    total += count 
total<jupyter_output><empty_output><jupyter_text>For loops<jupyter_code>for i in [1, 2, 3, 4]:
    print(i)
for subject in ["Queueing Theory", "Game Theory", 
                "Inventory Theory", "Reliability Theory", 
                "Project Management", "Decision Analysis"]:
    if "Theory" in subject:
        print(subject)<jupyter_output>Project Management<jupyter_text>Functions<jupyter_code>#To create a function we use the 'def' statement:
def hi():
    """
    This function simply prints a short statement. 
    
    This is a shorter way of writing documentation, 
    it is good practice to always include a 
    description of what a function does.
    """
    print("Hello everybody!")

hi()
def fibonacci(n):
    """
    This returns the nth Fibonacci number.
    """
    if n == 0:
        return 0
    if n == 1:
        return 1
    return fibonacci(n - 1) + fibonacci(n - 2)
fibonacci(5)<jupyter_output><empty_output><jupyter_text>Data structures: Lists<jupyter_code>my_list = list(range(6))
my_list[0]
my_list.append(100)
my_list<jupyter_output><empty_output><jupyter_text>Object Oriented ProgrammingThis is similar to cellular structure:![](resources/cellular_structure.png)We can create "things" with:- attributes: things those "things" have;- methods: things those "things" can do.![](resources/oop.png) Defining a class<jupyter_code>class Student():
    """We can create a simple empty class.
    
    This is a set of rules that says what a student is.
    """
vince = Student()  # Creating an instance
vince
zoe = Student()  # Creating a different instance
zoe<jupyter_output><empty_output><jupyter_text>Attributes<jupyter_code>class Student():
    courses = ["Biology", "Mathematics", "English"]
    age = 5
    gender = "Male"
#Let us now create Vince again:
vince = Student()<jupyter_output><empty_output><jupyter_text>Accessing these attributes:<jupyter_code>vince.courses
vince.age
vince.gender<jupyter_output><empty_output><jupyter_text>We can manipulate these attributes just like **any other** python variable:<jupyter_code>vince.courses.append("Photography")
print(vince.courses)
zoe = Student()
print(zoe.courses)
vince.age = 28
vince.age
vince.gender = "M"
vince.gender<jupyter_output><empty_output><jupyter_text>The self ParameterThe self parameter is a reference to the current instance of the class, and is used to access variables that belongs to the class.It does not have to be named self , you can call it whatever you like, but it has to be the first parameter of any function in the class:<jupyter_code>class Person:
  def __init__(self, name, age):
    self.name = name
    self.age = age

  def myfunc(self):
    print("Hello my name is " + self.name + " and I have "+ str(self.age) +" years.")

p1 = Person("John", 36)
p1.myfunc() 
p2 = Person("Oliver", 42)
p2.myfunc()<jupyter_output>Hello my name is John and I have 36 years.
Hello my name is Oliver and I have 42 years.<jupyter_text>Methods<jupyter_code>class Student():
    courses = ["Biology", "Mathematics", "English"]
    age = 5
    sex = "Male"
    
    def __init__(self, age=5):
        self.age = age

    def have_a_birthday(self):
        """This method increments the age of our instance."""
        self.age += 1
vince = Student(6)
vince.age
vince.have_a_birthday()
print(vince.age)
zoe = Student()
print(zoe.age)<jupyter_output>7
5<jupyter_text>The `__init__` method<jupyter_code>class Student():
    def __init__(self, courses, age=None, sex='Male'):
        """
        What the class should do when it 
        is used to create an instance
        """
        self.courses = courses
        self.age = age
        self.sex = sex

    def have_a_birthday(self):
        self.age += 1

vince = Student(["Biology","Math"],28,"Male")
vince.courses, vince.age, vince.sex<jupyter_output><empty_output><jupyter_text>InheritanceWe can use a class to create new classes:<jupyter_code>class Math_Student(Student):
    """
    A Math student: behaves exactly like a Student 
    but also has a favourite class attribute.
    """
    favourite_class = "Mathematics"
becky = Math_Student(["Mathematics", "Biology"], 29, "Female")
becky.courses, becky.age, becky.sex, becky.favourite_class
#This class has the methods of the parent class:
becky.have_a_birthday()
becky.age<jupyter_output><empty_output><jupyter_text>Use the super() FunctionPython also has a super() function that will make the child class inherit all the methods and properties from its parent:<jupyter_code>class Person:
  def __init__(self, fname, lname):
    self.firstname = fname
    self.lastname = lname

  def printname(self):
    print(self.firstname, self.lastname)


class Student(Person):
  def __init__(self, fname, lname, year):
    super().__init__(fname, lname)
    self.graduationyear = year
    
  def printname(self):
    print(self.firstname, self.lastname, self.graduationyear)

x = Student("Mike", "Olsen", 2019) 
x.printname()
x.printname()<jupyter_output><NAME> 2019
<NAME> 2019
{'fraction_non_alphanumeric': 0.10617566986674308, 'fraction_numerical': 0.014901848402349907, 'mean_word_length': 4.470219435736677, 'pattern_counts': {'":': 0, '<': 74, '<?xml version=': 0, '>': 72, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '19', 'dir': 'jupyter-structured-clean-dedup', 'id': '499876', 'license': 'MIT', 'n_tokens_mistral': 2415, 'n_tokens_neox': 2286, 'n_words': 701, 'path': '00 oop.ipynb', 'repo_name': 'mariolpantunes/python201', 'size': '6987'}