diff --git a/python3.html.markdown b/python3.html.markdown
index 0f5da8f1..7f3702e6 100644
--- a/python3.html.markdown
+++ b/python3.html.markdown
@@ -601,95 +601,9 @@ list(filter(lambda x: x > 5, [3, 4, 5, 6, 7])) # => [6, 7]
[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13]
[x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7]
-####################################################
-## 5. Classes
-####################################################
-
-
-# We use the "class" operator to get a class
-class Human:
-
- # A class attribute. It is shared by all instances of this class
- species = "H. sapiens"
-
- # Basic initializer, this is called when this class is instantiated.
- # Note that the double leading and trailing underscores denote objects
- # or attributes that are used by python but that live in user-controlled
- # namespaces. Methods(or objects or attributes) like: __init__, __str__,
- # __repr__ etc. are called magic methods (or sometimes called dunder methods)
- # You should not invent such names on your own.
- def __init__(self, name):
- # Assign the argument to the instance's name attribute
- self.name = name
-
- # Initialize property
- self.age = 0
-
- # An instance method. All methods take "self" as the first argument
- def say(self, msg):
- return "{name}: {message}".format(name=self.name, message=msg)
-
- # A class method is shared among all instances
- # They are called with the calling class as the first argument
- @classmethod
- def get_species(cls):
- return cls.species
-
- # A static method is called without a class or instance reference
- @staticmethod
- def grunt():
- return "*grunt*"
-
- # A property is just like a getter.
- # It turns the method age() into an read-only attribute
- # of the same name.
- @property
- def age(self):
- return self._age
-
- # This allows the property to be set
- @age.setter
- def age(self, age):
- self._age = age
-
- # This allows the property to be deleted
- @age.deleter
- def age(self):
- del self._age
-
-
-# Instantiate a class
-i = Human(name="Ian")
-print(i.say("hi")) # prints out "Ian: hi"
-
-j = Human("Joel")
-print(j.say("hello")) # prints out "Joel: hello"
-
-# Call our class method
-i.get_species() # => "H. sapiens"
-
-# Change the shared attribute
-Human.species = "H. neanderthalensis"
-i.get_species() # => "H. neanderthalensis"
-j.get_species() # => "H. neanderthalensis"
-
-# Call the static method
-Human.grunt() # => "*grunt*"
-
-# Update the property
-i.age = 42
-
-# Get the property
-i.age # => 42
-
-# Delete the property
-del i.age
-i.age # => raises an AttributeError
-
-
####################################################
-## 6. Modules
+## 5. Modules
####################################################
# You can import modules
@@ -724,6 +638,189 @@ dir(math)
# This happens because the local folder has priority
# over Python's built-in libraries.
+
+####################################################
+## 6. Classes
+####################################################
+
+# We use the "class" operator to get a class
+class Human:
+
+ # A class attribute. It is shared by all instances of this class
+ species = "H. sapiens"
+
+ # Basic initializer, this is called when this class is instantiated.
+ # Note that the double leading and trailing underscores denote objects
+ # or attributes that are used by python but that live in user-controlled
+ # namespaces. Methods(or objects or attributes) like: __init__, __str__,
+ # __repr__ etc. are called magic methods (or sometimes called dunder methods)
+ # You should not invent such names on your own.
+ def __init__(self, name):
+ # Assign the argument to the instance's name attribute
+ self.name = name
+
+ # Initialize property
+ self.age = 0
+
+ # An instance method. All methods take "self" as the first argument
+ def say(self, msg):
+ print ("{name}: {message}".format(name=self.name, message=msg))
+
+ # Another instance method
+ def sing(self):
+ return 'yo... yo... microphone check... one two... one two...'
+
+ # A class method is shared among all instances
+ # They are called with the calling class as the first argument
+ @classmethod
+ def get_species(cls):
+ return cls.species
+
+ # A static method is called without a class or instance reference
+ @staticmethod
+ def grunt():
+ return "*grunt*"
+
+ # A property is just like a getter.
+ # It turns the method age() into an read-only attribute
+ # of the same name.
+ @property
+ def age(self):
+ return self._age
+
+ # This allows the property to be set
+ @age.setter
+ def age(self, age):
+ self._age = age
+
+ # This allows the property to be deleted
+ @age.deleter
+ def age(self):
+ del self._age
+
+
+# When a Python interpreter reads a source file it executes all its code.
+# This __name__ check makes sure this code block is only executed when this
+# module is the main program.
+if __name__ == '__main__':
+ # Instantiate a class
+ i = Human(name="Ian")
+ i.say("hi") # "Ian: hi"
+ j = Human("Joel")
+ j.say("hello") # "Joel: hello"
+ # i and j are instances of type Human, or in other words: they are Human objects
+
+ # Call our class method
+ i.say(i.get_species()) # "Ian: H. sapiens"
+ # Change the shared attribute
+ Human.species = "H. neanderthalensis"
+ i.say(i.get_species()) # => "Ian: H. neanderthalensis"
+ j.say(j.get_species()) # => "Joel: H. neanderthalensis"
+
+ # Call the static method
+ print(Human.grunt()) # => "*grunt*"
+ print(i.grunt()) # => "*grunt*"
+
+ # Update the property for this instance
+ i.age = 42
+ # Get the property
+ i.say(i.age) # => 42
+ j.say(j.age) # => 0
+ # Delete the property
+ del i.age
+ # i.age # => this would raise an AttributeError
+
+
+####################################################
+## 6.1 Multiple Inheritance
+####################################################
+
+# Another class definition
+class Bat:
+
+ species = 'Baty'
+
+ def __init__(self, can_fly=True):
+ self.fly = can_fly
+
+ # This class also has a say method
+ def say(self, msg):
+ msg = '... ... ...'
+ return msg
+
+ # And its own method as well
+ def sonar(self):
+ return '))) ... ((('
+
+if __name__ == '__main__':
+ b = Bat()
+ print(b.say('hello'))
+ print(b.fly)
+
+
+# from "filename-without-extension" import "function-or-class"
+from human import Human
+from bat import Bat
+
+# Batman inherits from both Human and Bat
+class Batman(Human, Bat):
+
+ # Batman has its own value for the species class attribute
+ species = 'Superhero'
+
+ def __init__(self, *args, **kwargs):
+ # Typically to inherit attributes you have to call super:
+ #super(Batman, self).__init__(*args, **kwargs)
+ # However we are dealing with multiple inheritance here, and super()
+ # only works with the next base class in the MRO list.
+ # So instead we explicitly call __init__ for all ancestors.
+ # The use of *args and **kwargs allows for a clean way to pass arguments,
+ # with each parent "peeling a layer of the onion".
+ Human.__init__(self, 'anonymous', *args, **kwargs)
+ Bat.__init__(self, *args, can_fly=False, **kwargs)
+ # override the value for the name attribute
+ self.name = 'Sad Affleck'
+
+ def sing(self):
+ return 'nan nan nan nan nan batman!'
+
+
+if __name__ == '__main__':
+ sup = Batman()
+
+ # Instance type checks
+ if isinstance(sup, Human):
+ print('I am human')
+ if isinstance(sup, Bat):
+ print('I am bat')
+ if type(sup) is Batman:
+ print('I am Batman')
+
+ # Get the Method Resolution search Order used by both getattr() and super().
+ # This attribute is dynamic and can be updated
+ print(Batman.__mro__) # => (, , , )
+
+ # Calls parent method but uses its own class attribute
+ print(sup.get_species()) # => Superhero
+
+ # Calls overloaded method
+ print(sup.sing()) # => nan nan nan nan nan batman!
+
+ # Calls method from Human, because inheritance order matters
+ sup.say('I agree') # => Sad Affleck: I agree
+
+ # Call method that exists only in 2nd ancestor
+ print(sup.sonar()) # => ))) ... (((
+
+ # Inherited class attribute
+ sup.age = 100
+ print(sup.age)
+
+ # Inherited attribute from 2nd ancestor whose default value was overriden
+ print('Can I fly? ' + str(sup.fly))
+
+
+
####################################################
## 7. Advanced
####################################################