# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# # Lesson 10: Make Classes: advanced topics
#
# **Udacity Full Stack Web Developer Nanodegree program**
#
# Part 01. Programming fundamentals and the web
#
# [Programming foundations with Python](https://www.udacity.com/course/programming-foundations-with-python--ud036)
#
# <NAME>
#
# br3ndonland

# ## 01. Advanced Ideas in OOP
#
# ## 02. Class Variables
#
# * Class variables can be shared by all instances of the Class.
# * The Google Style Guide recommends all caps for class variable names, like `VALID_RATINGS`.
# * PEP 8 [recommends](https://www.python.org/dev/peps/pep-0008/#class-names) CapWords for class names.
#
# *Instructor notes*:
#
# Around 0:40 or so, Kunal said with regard to the valid_ratings variable:
#
# "...This is an array or a list..."
#
# To avoid confusion down the road: Arrays and lists are actually not the same thing in Python. 99.9% of the time, you'll want to use lists. They're flexible, and good for pretty much every purpose.
#
# However, there is also an array.array class in Python, which is essentially a thin wrapper on top of C arrays.
#
# They're not something you'll probably need to use, but read more here if interested: http://www.wired.com/2011/08/python-notes-lists-vs-arrays/
#
#
# ## 03. Quiz: Using Predefined Class Variables
#
# We explored three of the built-in class variables: `__doc__`, `__name__`, `__module__`.
#
# ```python
# print(media.Movie.__doc__) # documentation function
# print(media.Movie.__name__) # prints the class function name
# print(media.Movie.__module__) # prints module name
# ```
# ```
# This class provides a way to store movie information.
# Movie
# media
# ```
#

import webbrowser
webbrowser.__doc__

# ## 04. Inheritance
#
# This is another major topic in object-oriented programming. Think about it like a family. A child inherits characteristics and genomic material from their parents. Similarly, child classes can inherit information from parent classes
#
# ## 05. Class Parent
#
# We create a parent class, and reference it in a child instance. While watching, I was thinking that the parent class should be in a separate file. Kunal addressed this, and he just combined them for ease of demonstration.
#
# ```python
# # Udacity full-stack web developer nanodegree
# # 01. Programming fundamentals and the web
# # Lesson 10. Make Classes: Advanced Topics
#
#
# class Parent():
#     def __init__(self, last_name, eye_color):
#         print("Parent Constructor called.")
#         self.last_name
#         self.eye_color
#
#
# # Normally the child instance would be in a separate file.
# # Included here for ease of demonstration.
# billy_cyrus = Parent("Cyrus", "blue")
# print(billy_cyrus.last_name)
#
# ```
#
# When I first ran this, I was getting `AttributeError: 'Parent' object has no attribute 'last_name'`. I hadn't finished defining parameters in the Parent Class.
#
# ```python
# # Udacity full-stack web developer nanodegree
# # 01. Programming fundamentals and the web
# # Lesson 10. Make Classes: Advanced Topics
#
#
# class Parent():
#     def __init__(self, last_name, eye_color):
#         print("Parent Constructor called.")
#         self.last_name = last_name
#         self.eye_color = eye_color
#
#
# # Normally the child instance would be in a separate file.
# # Included here for ease of demonstration.
# billy_cyrus = Parent("Cyrus", "blue")
# print(billy_cyrus.last_name)
#
# ```

# ## 06. Quiz: What's the Output?
#
# The code seems highly redundant.
#
# *What will the output be?*
#
# ```
# Parent Constructor called
# Child Constructor called
# Cyrus
# 5
# ```
#
# *output*:
#
# ```
# Parent Constructor called.
# Cyrus
# Child Constructor called.
# Parent Constructor called.
# Cyrus
# 5
# ```
# When computing the `miley_cyrus` function, the Child Constructor is first called. The Child calls the Parent. The output is then generated.

# ## 07. Transitioning to Class `Movie`
# ## 08. Updating the Design for Class `Movie`
#
# We revisit the code from our Class `Movie`. What if we wanted to add a similar Class for TV shows? Movies and TV shows share some characteristics, like the presence of a title and duration. We could create a parent function, `class Video():`, and group `class Movie(Video):` and `class TvShow(Video):` as child classes. Inheritance allows us to write code in an intuitive, human-readable way.
#
# <img src="https://www.dropbox.com/s/ibi6t0b2aexkvr1/01_10_inheritance.png?dl=1">

# ## 10. Reusing methods
#
# Kunal went back to the *inheritance.py* file, and defined a new instance method inside `class Parent()` called `show_info`. 
#
# ```python
#     def show_info(self):
#         print("Last Name - " + self.last_name)
#         print("Eye Color - " + self.eye_color)
#
# ```
#
# He then referenced it with `billy_cyrus.show_info()`.
#

# ## 11. Method Overriding
#
# The `show_info()` method is present inside the `class Parent():`. It can be created again inside the `class Child():`, and it will override the parent function.

StarcoderdataJupyterScriptsDedupFiltered