From 0e5b0a3ec0e2c803b56dca6218b50ba4a8312ff6 Mon Sep 17 00:00:00 2001 From: PeaceNira Date: Fri, 8 Nov 2024 19:30:32 +0000 Subject: [PATCH] Intial commit with first 3 tutorials --- 1_variables.py | 75 +++++++++++++++++++++++++++++++++++++++++++ 2_classes.py | 43 +++++++++++++++++++++++++ 3_advanced_classes.py | 72 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 190 insertions(+) create mode 100644 1_variables.py create mode 100644 2_classes.py create mode 100644 3_advanced_classes.py diff --git a/1_variables.py b/1_variables.py new file mode 100644 index 0000000..5d34fca --- /dev/null +++ b/1_variables.py @@ -0,0 +1,75 @@ +""" +In this example, we'll cover the fundamental variable types in Python and introduce the basics of functions. + +Key Concepts: + **Variables**: Variables store data that can be changed while the program is running. + + **Dynamic Typing**: Python is a dynamically-typed language, which means you don't need to specify + the data type of a variable explicitly (unlike statically-typed languages like C or Java, where you do). + - Example in Java: `int number = 1;` + - In Python: `number = 1` (Python automatically understands that `number` is an integer). +""" + +# The following are common variable types in Python. This list is not exhaustive, but it covers the basics. + +# Integer: An integer (int) represents a whole number, with no decimal point. +number = 1 + +# Float: A floating point number (float) represents a number with a decimal point. +number_float = 1.1 + +# String: A string (str) represents a sequence of characters, typically used for text. +text = "Hello, World!" + +# Boolean: A boolean (bool) represents a logical value, either True or False. +boolean = True + +# List: A list stores a collection of values in a specific order, and the values can be of any type. +# Lists are mutable, meaning they can be changed after they’re created (e.g., adding or removing items). +a_list = ["Apple", 64, 1.1, True] + +# Tuple: A tuple is similar to a list in that it can store multiple values, but it is immutable, +# meaning once it’s created, it cannot be changed. +a_tuple = ("Apple", 54, 11, 1.2, False) + +#dict: stores a value with a key +# Dictionaries (dict) are extremely useful, they allow you to map a name (key) to a value. +# they are mutable, meaning they can be changed after they’re created (e.g., adding or removing items). +dictionary = { + "Jan" : "January", + "Feb" : "February", + "Mar" : "March", + "Apr" : "April", + "May" : "May", + "Jun" : "June", + "Jul" : "July", + "Aug" : "August", + "Sep" : "September", + "Oct" : "October", + "Nov" : "November", + "Dec" : "December" +} + + +""" +A function allows you to define a reusable block of code that performs a specific task. + +Functions can: +- Take input (called parameters or arguments) +- Perform operations with that input +- Return a result, or simply perform an action (like printing something) + +Below is a function called `show_type` that takes in one parameter, `var`, and prints its data type. +""" + +def show_type(var): + """Prints the data type of the variable passed to it.""" + print(f"The type of {var} is {type(var)}") + +# Let's test our function with the variables defined above. +show_type(number) # Expected output: +show_type(number_float) # Expected output: +show_type(text) # Expected output: +show_type(boolean) # Expected output: +show_type(a_list) # Expected output: +show_type(a_tuple) # Expected output: diff --git a/2_classes.py b/2_classes.py new file mode 100644 index 0000000..a828198 --- /dev/null +++ b/2_classes.py @@ -0,0 +1,43 @@ +""" +Their is going to be a relatively big jump in difficulty here, but dont be scared! +All you need to know to understand classes are variables and functions, as covered in the previous file. + +Key Concepts: + **class** is a blueprint for creating objects (specific instances of that class), + a class represents a collection of attributes and methods to represent something (e.g a Person) + + **object** is an instance of a class with its own unique data. + + **attributes** are values tied to a object + + **methods** are the exact same as functions, but are tried to a class. + + **Magic/dunder methods** are methods predefined by python that can be used for various things. + + **__init__** is a type of magic method, it is known as a constructor and initializes the objects attributes when its created +""" + +class Person: + """A class Representing a Human/Person""" + + # This is the constructor, whenever a new person is created it runs and can be used to assign the new person their attributes! + def __init__(self, name, age, eye_color): + self.name = name # An attribute + self.age = age + self.eye_color = eye_color + + # This is a method, note "self" must be passed as a paramater/arguement for it to access the attributes of... itself. + def canApplyForLicence(self): + if self.age >= 17: + return f"{self.name} can apply for their driving permit!" + else: + return f"{self.name} is too young ({self.age}) and can not apply for a driving permit." + + +pedro = Person("Pedro", 19, "Brown") # Creates a new person with the following values + +print(pedro.canApplyForLicence()) # Runs the canApplyForLicence method, and prints the return value + +Iain = Person("Iain", 16, "Blue") # Creates a Another new person with the following values (iain armitage if you wanted to know.) + +print(Iain.canApplyForLicence()) # Runs the canApplyForLicence method, and prints the return value diff --git a/3_advanced_classes.py b/3_advanced_classes.py new file mode 100644 index 0000000..17cb4a0 --- /dev/null +++ b/3_advanced_classes.py @@ -0,0 +1,72 @@ +""" +Now that we know the basics of classes, variables, and functions, we will move on to more +abstract ideas. + +I'm also going to introduce type hinting; this reduces ambiguity and improves readability. + +Key Concepts: + **Encapsulation** is the concept of grouping related data and methods within a + class and restricting access to them to control how they are used. + + **Access Modifiers** are used to determine who/what can access a certain attribute or method. + + - **Public**: Accessible from any part of the code. Used for attributes and methods intended to be part + of the class's interface for external use. + + - **Protected**: Intended for internal use within the class and its subclasses. "_value" represents it. + Useful for attributes/methods that should be accessible in subclasses but not publicly. + + - **Private**: Only accessible within the class, represented by "__value". Useful for securing sensitive + data or internal methods that should not be altered externally. + + IMPORTANT: Python does not strictly enforce access control, so these conventions mainly serve as guidelines. +""" + +from abc import ABC, abstractmethod # This is the abstraction library in Python +from typing import Optional # Type hinting, not needed but reduces ambiguity. Note: not enforced at runtime. + +class Shape(ABC): # An abstract class, provides a blueprint for other classes to inherit. + + @abstractmethod + def area(self) -> float: + """Implemented to ensure each subclass contains this method.""" + # This method is required in all subclasses, ensuring they provide their own area calculation. + +class Rectangle(Shape): + def __init__(self, width: float, height: float): + self.__width = width # A private attribute to store width. + self.__height = height # A private attribute to store height. + + @property # This allows access to the private 'width' attribute in a controlled way. + def width(self) -> float: + return self.__width + + @width.setter # This allows you to set the value of 'width' after initialization. + def width(self, value: float): + if value <= 0: + raise ValueError("Width must be positive.") + self.__width = value + + @property # This allows access to the private 'height' attribute in a controlled way. + def height(self) -> float: + return self.__height + + @height.setter # This allows you to set the value of 'height' after initialization. + def height(self, value: float): + if value <= 0: + raise ValueError("Height must be positive.") + self.__height = value + + def area(self) -> float: + return self.__width * self.__height # Calculates the area of the rectangle. + + def set_dimensions(self, width: Optional[float] = None, height: Optional[float] = None): + if width is not None: + self.width = width # Sets 'width' using the setter. + if height is not None: + self.height = height # Sets 'height' using the setter. + +rect = Rectangle(5, 10) +print(rect.area()) # Prints the area of the rectangle (5 * 10 = 50). +rect.set_dimensions(width=8) # Updates 'width' using the setter, height remains the same. +print(rect.area()) # Prints the new area of the rectangle (8 * 10 = 80).