## Lesson: Syntax Elements of Python Classes <div style="position: relative; padding-bottom: 64.90384615384616%; height: 0;"><iframe src="https://www.loom.com/embed/836f42f2a3f94e8384a29107873ba535?sid=939b4d2f-b4f8-437c-8fb6-94ee80219e5b" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"></iframe></div> ### Specific Syntax Elements of Python Classes In Python, classes are used to create user-defined data structures. A class defines the attributes and methods of the objects created from it. Here is an overview of the syntax elements you'll encounter when working with Python classes. ### 1. Defining a Class The `class` keyword is used to define a class. The class name should follow the CapitalizedWords convention. ```python class MyClass: pass # Placeholder for an empty class ``` ### 2. The `__init__` Method The `__init__` method is the constructor method for a class. It is called when an instance (object) of the class is created. This method is used to initialize the object's attributes. ```python class MyClass: def __init__(self, attribute1, attribute2): self.attribute1 = attribute1 self.attribute2 = attribute2 ``` ### 3. Instance Attributes Instance attributes are variables that are unique to each instance. They are typically initialized in the `__init__` method. ```python class MyClass: def __init__(self, name, age): self.name = name self.age = age ``` ### 4. Class Attributes Class attributes are variables that are shared across all instances of a class. They are defined within the class but outside any instance methods. ```python class MyClass: species = "Human" # Class attribute def __init__(self, name): self.name = name # Instance attribute ``` ### 5. Methods Methods are functions defined within a class. They are used to define the behaviors of the objects. ```python class MyClass: def __init__(self, name): self.name = name def greet(self): return f"Hello, {self.name}!" ``` ### 6. The `self` Parameter The `self` parameter is a reference to the current instance of the class. It is used to access variables and methods associated with the class instance. ```python class MyClass: def __init__(self, name): self.name = name def display_name(self): print(f"Name: {self.name}") ``` ### 7. Inheritance Inheritance allows one class to inherit attributes and methods from another class. The class being inherited from is called the parent or base class, and the class that inherits is called the child or derived class. ```python class Animal: def __init__(self, name): self.name = name def speak(self): pass class Dog(Animal): def speak(self): return f"{self.name} says Woof!" ``` ### 8. Overriding Methods A method in a child class can override a method in the parent class. This allows for specific behavior in the child class. ```python class Animal: def speak(self): return "Some sound" class Dog(Animal): def speak(self): return "Woof!" ``` ### 9. Encapsulation Encapsulation involves restricting access to certain attributes and methods. This is typically done by prefixing an attribute or method name with an underscore (`_`) for protected access or double underscore (`__`) for private access. ```python class MyClass: def __init__(self, name, age): self._name = name # Protected attribute self.__age = age # Private attribute def get_age(self): return self.__age # Accessing a private attribute via a public method ``` ### 10. Class Methods and Static Methods - **Class methods** are methods that are bound to the class and not the instance. They can be used to access or modify the class state. They are defined using the `@classmethod` decorator and take `cls` as the first parameter. ```python class MyClass: count = 0 def __init__(self): MyClass.count += 1 @classmethod def get_count(cls): return cls.count ``` - **Static methods** are methods that do not depend on the class or instance. They are defined using the `@staticmethod` decorator and do not take `self` or `cls` as the first parameter. ```python class MyClass: @staticmethod def greet(): return "Hello!" ``` ### 11. Special Methods (Magic Methods) Special methods, also known as magic methods or dunder methods, are used to provide special functionality. They are surrounded by double underscores (`__`). Examples include `__str__`, `__repr__`, `__len__`, and `__eq__`. ```python class MyClass: def __init__(self, name): self.name = name def __str__(self): return f"MyClass instance with name: {self.name}" ``` ### Cheat Sheet | Syntax Element | Description | |---------------------|------------------------------------------------------| | `class` | Defines a new class | | `__init__` | Constructor method | | `self` | Refers to the current instance | | `@classmethod` | Defines a class method | | `@staticmethod` | Defines a static method | | `__str__` | String representation method | | `__repr__` | Official string representation method | | `_attribute` | Protected attribute | | `__attribute` | Private attribute | | `class Attribute` | Class attribute | ### Exercise Create a Python class that models a simple banking system. The class should have the following features: - Attributes for the account holder's name, balance, and account number. - Methods to deposit money, withdraw money, and check the balance. - Implement encapsulation to ensure the balance cannot be directly accessed from outside the class. - Include a class method to keep track of the total number of accounts created. ```python class BankAccount: total_accounts = 0 def __init__(self, account_holder, initial_balance, account_number): self.__account_holder = account_holder self.__balance = initial_balance self.__account_number = account_number BankAccount.total_accounts += 1 def deposit(self, amount): if amount > 0: self.__balance += amount return f"Deposited {amount}. New balance is {self.__balance}." return "Invalid deposit amount." def withdraw(self, amount): if 0 < amount <= self.__balance: self.__balance -= amount return f"Withdrew {amount}. New balance is {self.__balance}." return "Invalid withdrawal amount." def check_balance(self): return f"Account balance is {self.__balance}." @classmethod def get_total_accounts(cls): return f"Total bank accounts: {cls.total_accounts}" ``` Use this class to create a few accounts and perform some transactions, ensuring all features work correctly. This covers the syntax elements of Python classes comprehensively. For patterns, we can delve deeper into specific design patterns used in OOP.