{"componentChunkName":"component---node-modules-smooth-doc-src-templates-doc-js","path":"/docs/oops/","result":{"data":{"mdx":{"fields":{"pageType":"doc","title":"Object-Oriented Programming (OOP)","editLink":""},"body":"var _excluded = [\"components\"];\nfunction _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n/* @jsxRuntime classic */\n/* @jsx mdx */\n\nvar _frontmatter = {\n  \"title\": \"Object-Oriented Programming (OOP)\",\n  \"section\": \"Docs\",\n  \"order\": 4\n};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n    props = _objectWithoutProperties(_ref, _excluded);\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"h1\", {\n    \"id\": \"object-oriented-programming-oop\"\n  }, mdx(\"a\", {\n    parentName: \"h1\",\n    \"href\": \"#object-oriented-programming-oop\",\n    \"aria-hidden\": true,\n    \"className\": \"anchor\"\n  }, mdx(\"svg\", {\n    \"aria-hidden\": \"true\",\n    height: \"16\",\n    version: \"1.1\",\n    viewBox: \"0 0 16 16\",\n    width: \"16\"\n  }, mdx(\"path\", {\n    fillRule: \"evenodd\",\n    d: \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"Object-Oriented Programming (OOP)\"), mdx(\"p\", null, \"Object-Oriented Programming (OOP) is a programming paradigm that revolves around the concept of objects, which are instances of classes. It provides a way to structure and organize code by encapsulating data (attributes) and behavior (methods) into reusable and modular units. OOP is widely used in software development because it promotes code reusability, modularity, and maintainability.\"), mdx(\"h2\", {\n    \"id\": \"1-classes-and-objects\"\n  }, mdx(\"a\", {\n    parentName: \"h2\",\n    \"href\": \"#1-classes-and-objects\",\n    \"aria-hidden\": true,\n    \"className\": \"anchor\"\n  }, mdx(\"svg\", {\n    \"aria-hidden\": \"true\",\n    height: \"16\",\n    version: \"1.1\",\n    viewBox: \"0 0 16 16\",\n    width: \"16\"\n  }, mdx(\"path\", {\n    fillRule: \"evenodd\",\n    d: \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"1. Classes and Objects\"), mdx(\"p\", null, \"In Python, classes are the blueprints or templates for creating objects. An object is an instance of a class, containing its own data (attributes) and methods.\"), mdx(\"h3\", {\n    \"id\": \"i-defining-a-class\"\n  }, mdx(\"a\", {\n    parentName: \"h3\",\n    \"href\": \"#i-defining-a-class\",\n    \"aria-hidden\": true,\n    \"className\": \"anchor\"\n  }, mdx(\"svg\", {\n    \"aria-hidden\": \"true\",\n    height: \"16\",\n    version: \"1.1\",\n    viewBox: \"0 0 16 16\",\n    width: \"16\"\n  }, mdx(\"path\", {\n    fillRule: \"evenodd\",\n    d: \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"i. Defining a Class\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-python\"\n  }, \"class Dog:\\n    def __init__(self, name, breed, age):\\n        self.name = name  # Attributes\\n        self.breed = breed\\n        self.age = age\\n\\n    def bark(self):  # Method\\n        print(f\\\"{self.name} says woof!\\\")\\n\\n    def get_info(self):\\n        return f\\\"{self.name} is a {self.age}-year-old {self.breed}.\\\"\\n\")), mdx(\"p\", null, \"In this example, \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Dog\"), \" is a class with three attributes (\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"name\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"breed\"), \", and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"age\"), \") and two methods (\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"bark()\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"get_info()\"), \"). The \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"__init__()\"), \" method is a special method called a constructor, which is automatically invoked when an object is created. It is responsible for initializing the object's attributes with the provided values.\"), mdx(\"h3\", {\n    \"id\": \"ii-creating-objects\"\n  }, mdx(\"a\", {\n    parentName: \"h3\",\n    \"href\": \"#ii-creating-objects\",\n    \"aria-hidden\": true,\n    \"className\": \"anchor\"\n  }, mdx(\"svg\", {\n    \"aria-hidden\": \"true\",\n    height: \"16\",\n    version: \"1.1\",\n    viewBox: \"0 0 16 16\",\n    width: \"16\"\n  }, mdx(\"path\", {\n    fillRule: \"evenodd\",\n    d: \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"ii. Creating Objects\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-python\"\n  }, \"my_dog = Dog(\\\"Buddy\\\", \\\"Labrador\\\", 3)\\nyour_dog = Dog(\\\"Max\\\", \\\"Golden Retriever\\\", 5)\\n\")), mdx(\"p\", null, \"Here, \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"my_dog\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"your_dog\"), \" are instances (objects) of the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Dog\"), \" class, each with its own set of attributes (\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"name\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"breed\"), \", and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"age\"), \").\"), mdx(\"h3\", {\n    \"id\": \"iii-accessing-attributes-and-methods\"\n  }, mdx(\"a\", {\n    parentName: \"h3\",\n    \"href\": \"#iii-accessing-attributes-and-methods\",\n    \"aria-hidden\": true,\n    \"className\": \"anchor\"\n  }, mdx(\"svg\", {\n    \"aria-hidden\": \"true\",\n    height: \"16\",\n    version: \"1.1\",\n    viewBox: \"0 0 16 16\",\n    width: \"16\"\n  }, mdx(\"path\", {\n    fillRule: \"evenodd\",\n    d: \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"iii. Accessing Attributes and Methods\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-python\"\n  }, \"print(my_dog.name)  # Output: Buddy\\nprint(your_dog.breed)  # Output: Golden Retriever\\nprint(my_dog.get_info())  # Output: Buddy is a 3-year-old Labrador.\\n\\nmy_dog.bark()  # Output: Buddy says woof!\\nyour_dog.bark()  # Output: Max says woof!\\n\")), mdx(\"p\", null, \"Objects can access and manipulate their own attributes and methods using the dot notation (\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"object.attribute\"), \" or \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"object.method()\"), \").\"), mdx(\"h3\", {\n    \"id\": \"iv-class-and-instance-attributes\"\n  }, mdx(\"a\", {\n    parentName: \"h3\",\n    \"href\": \"#iv-class-and-instance-attributes\",\n    \"aria-hidden\": true,\n    \"className\": \"anchor\"\n  }, mdx(\"svg\", {\n    \"aria-hidden\": \"true\",\n    height: \"16\",\n    version: \"1.1\",\n    viewBox: \"0 0 16 16\",\n    width: \"16\"\n  }, mdx(\"path\", {\n    fillRule: \"evenodd\",\n    d: \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"iv. Class and Instance Attributes\"), mdx(\"p\", null, \"In Python, you can define attributes at the class level or the instance level. Class attributes are shared among all instances of the class, while instance attributes are specific to each individual instance.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-python\"\n  }, \"class Dog:\\n    species = \\\"Canis familiaris\\\"  # Class attribute\\n\\n    def __init__(self, name, breed, age):\\n        self.name = name  # Instance attributes\\n        self.breed = breed\\n        self.age = age\\n\\nmy_dog = Dog(\\\"Buddy\\\", \\\"Labrador\\\", 3)\\nprint(my_dog.species)  # Output: Canis familiaris\\nprint(Dog.species)  # Output: Canis familiaris\\n\\nmy_dog.species = \\\"Canine\\\"  # This creates a new instance attribute\\nprint(my_dog.species)  # Output: Canine\\nprint(Dog.species)  # Output: Canis familiaris\\n\")), mdx(\"p\", null, \"In this example, \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"species\"), \" is a class attribute shared by all instances of the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Dog\"), \" class. However, when we assign a new value to \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"my_dog.species\"), \", it creates a new instance attribute with the same name, leaving the class attribute unchanged.\"), mdx(\"h3\", {\n    \"id\": \"v-class-methods-and-static-methods\"\n  }, mdx(\"a\", {\n    parentName: \"h3\",\n    \"href\": \"#v-class-methods-and-static-methods\",\n    \"aria-hidden\": true,\n    \"className\": \"anchor\"\n  }, mdx(\"svg\", {\n    \"aria-hidden\": \"true\",\n    height: \"16\",\n    version: \"1.1\",\n    viewBox: \"0 0 16 16\",\n    width: \"16\"\n  }, mdx(\"path\", {\n    fillRule: \"evenodd\",\n    d: \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"v. Class Methods and Static Methods\"), mdx(\"p\", null, \"In addition to instance methods, Python also supports class methods and static methods.\"), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Class Methods\"), \":\\nClass methods are methods that operate on the class itself, rather than on individual instances. They take the class as the first argument (\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"cls\"), \") and can access and modify class attributes.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-python\"\n  }, \"class Dog:\\n    species = \\\"Canis familiaris\\\"\\n\\n    def __init__(self, name, breed, age):\\n        self.name = name\\n        self.breed = breed\\n        self.age = age\\n\\n    @classmethod\\n    def set_species(cls, new_species):\\n        cls.species = new_species\\n\\n    @classmethod\\n    def from_string(cls, dog_str):\\n        name, breed, age = dog_str.split(\\\"-\\\")\\n        return cls(name, breed, int(age))\\n\\nDog.set_species(\\\"Canine\\\")\\nprint(Dog.species)  # Output: Canine\\n\\nbuddy = Dog.from_string(\\\"Buddy-Labrador-3\\\")\\nprint(buddy.name)  # Output: Buddy\\nprint(buddy.breed)  # Output: Labrador\\nprint(buddy.age)  # Output: 3\\n\")), mdx(\"p\", null, \"In this example, \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"set_species()\"), \" is a class method that modifies the class attribute \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"species\"), \". The \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"from_string()\"), \" method is another class method that creates a new instance of the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Dog\"), \" class from a string representation.\"), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Static Methods\"), \":\\nStatic methods are functions defined within a class but do not operate on the class or instance attributes. They are primarily used for utility or helper functions that are logically related to the class but don't require access to its data.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-python\"\n  }, \"class Dog:\\n    def __init__(self, name, breed, age):\\n        self.name = name\\n        self.breed = breed\\n        self.age = age\\n\\n    @staticmethod\\n    def is_adult(age):\\n        return age >= 2\\n\\nbuddy = Dog(\\\"Buddy\\\", \\\"Labrador\\\", 3)\\nprint(Dog.is_adult(buddy.age))  # Output: True\\n\")), mdx(\"p\", null, \"In this example, \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"is_adult()\"), \" is a static method that checks if the provided age is considered adult for a dog. It does not access any instance or class attributes and can be called directly on the class itself or through an instance.\"), mdx(\"h2\", {\n    \"id\": \"2-introduction-to-oop-concepts\"\n  }, mdx(\"a\", {\n    parentName: \"h2\",\n    \"href\": \"#2-introduction-to-oop-concepts\",\n    \"aria-hidden\": true,\n    \"className\": \"anchor\"\n  }, mdx(\"svg\", {\n    \"aria-hidden\": \"true\",\n    height: \"16\",\n    version: \"1.1\",\n    viewBox: \"0 0 16 16\",\n    width: \"16\"\n  }, mdx(\"path\", {\n    fillRule: \"evenodd\",\n    d: \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"2. Introduction to OOP Concepts\"), mdx(\"p\", null, \"OOP is built upon four fundamental principles: Encapsulation, Abstraction, Inheritance, and Polymorphism. These principles work together to create robust, scalable, and efficient software systems.\"), mdx(\"h3\", {\n    \"id\": \"i-encapsulation\"\n  }, mdx(\"a\", {\n    parentName: \"h3\",\n    \"href\": \"#i-encapsulation\",\n    \"aria-hidden\": true,\n    \"className\": \"anchor\"\n  }, mdx(\"svg\", {\n    \"aria-hidden\": \"true\",\n    height: \"16\",\n    version: \"1.1\",\n    viewBox: \"0 0 16 16\",\n    width: \"16\"\n  }, mdx(\"path\", {\n    fillRule: \"evenodd\",\n    d: \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"i. Encapsulation\"), mdx(\"p\", null, \"Encapsulation is the mechanism of bundling data (attributes) and methods (behaviors) together within a single unit, called a class. It enforces data hiding and access control, preventing direct access to the internal state of an object from outside the class. This helps in maintaining data integrity and ensuring that objects are used in a consistent and predictable manner.\"), mdx(\"p\", null, \"In Python, encapsulation is achieved through the use of naming conventions:\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"strong\", {\n    parentName: \"li\"\n  }, \"Public attributes and methods\"), \": These can be accessed from anywhere, both inside and outside the class.\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"strong\", {\n    parentName: \"li\"\n  }, \"Private attributes and methods\"), \": These are prefixed with a double underscore (\", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"__\"), \"), and they are accessible only within the class itself. Python uses name mangling to enforce this privacy.\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"strong\", {\n    parentName: \"li\"\n  }, \"Protected attributes and methods\"), \": These are prefixed with a single underscore (\", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"_\"), \"), indicating that they should be treated as private, but they can still be accessed from outside the class (although this should be avoided).\")), mdx(\"p\", null, \"Here's an example of encapsulation in Python:\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-python\"\n  }, \"class BankAccount:\\n    def __init__(self, name, balance):\\n        self.name = name  # Public attribute\\n        self.__balance = balance  # Private attribute (name mangled to _BankAccount__balance)\\n\\n    def deposit(self, amount):\\n        self.__balance += amount\\n\\n    def withdraw(self, amount):\\n        if self.__balance >= amount:\\n            self.__balance -= amount\\n        else:\\n            print(\\\"Insufficient balance.\\\")\\n\\n    def get_balance(self):  # Public method to access the private attribute\\n        return self.__balance\\n\")), mdx(\"p\", null, \"In this example, the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"__balance\"), \" attribute is private, and it can only be accessed or modified through the class's methods (\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"deposit()\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"withdraw()\"), \", and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"get_balance()\"), \"). This encapsulation ensures that the internal state of the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"BankAccount\"), \" object is protected and can only be modified in a controlled and consistent manner.\"), mdx(\"h3\", {\n    \"id\": \"ii-abstraction\"\n  }, mdx(\"a\", {\n    parentName: \"h3\",\n    \"href\": \"#ii-abstraction\",\n    \"aria-hidden\": true,\n    \"className\": \"anchor\"\n  }, mdx(\"svg\", {\n    \"aria-hidden\": \"true\",\n    height: \"16\",\n    version: \"1.1\",\n    viewBox: \"0 0 16 16\",\n    width: \"16\"\n  }, mdx(\"path\", {\n    fillRule: \"evenodd\",\n    d: \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"ii. Abstraction\"), mdx(\"p\", null, \"Abstraction is the process of exposing only the relevant details of an object to the outside world, while hiding the implementation details. It provides a simplified and high-level understanding of the object's functionality, allowing users to interact with the object without needing to know how it works internally.\"), mdx(\"p\", null, \"In Python, abstraction is achieved through the use of abstract base classes and abstract methods. The \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"abc\"), \" module provides the infrastructure for defining abstract base classes.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-python\"\n  }, \"from abc import ABC, abstractmethod\\n\\nclass Shape(ABC):\\n    @abstractmethod\\n    def area(self):\\n        pass\\n\\n    @abstractmethod\\n    def perimeter(self):\\n        pass\\n\\nclass Rectangle(Shape):\\n    def __init__(self, length, width):\\n        self.length = length\\n        self.width = width\\n\\n    def area(self):\\n        return self.length * self.width\\n\\n    def perimeter(self):\\n        return 2 * (self.length + self.width)\\n\")), mdx(\"p\", null, \"In this example, the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Shape\"), \" class is an abstract base class that defines two abstract methods: \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"area()\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"perimeter()\"), \". The \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Rectangle\"), \" class inherits from \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Shape\"), \" and provides concrete implementations of these methods.\"), mdx(\"p\", null, \"By using abstraction, you can create a common interface (the abstract base class) that defines a contract for derived classes to follow. This promotes code reusability and makes it easier to extend or modify the system in the future.\"), mdx(\"h3\", {\n    \"id\": \"iii-inheritance\"\n  }, mdx(\"a\", {\n    parentName: \"h3\",\n    \"href\": \"#iii-inheritance\",\n    \"aria-hidden\": true,\n    \"className\": \"anchor\"\n  }, mdx(\"svg\", {\n    \"aria-hidden\": \"true\",\n    height: \"16\",\n    version: \"1.1\",\n    viewBox: \"0 0 16 16\",\n    width: \"16\"\n  }, mdx(\"path\", {\n    fillRule: \"evenodd\",\n    d: \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"iii. Inheritance\"), mdx(\"p\", null, \"Inheritance is a mechanism that allows a new class (derived or child class) to inherit properties and behaviors from an existing class (base or parent class). The derived class inherits attributes and methods from the base class and can also add new attributes and methods or override the existing ones.\"), mdx(\"p\", null, \"Inheritance promotes code reuse and helps in creating a hierarchical structure of classes, which is a natural way of organizing and modeling real-world relationships.\"), mdx(\"p\", null, \"Python supports different types of inheritance, including single inheritance (inheriting from single base class), multiple inheritance (inheriting from multiple base classes), and multi-level inheritance (inheriting from a derived class).\"), mdx(\"h4\", {\n    \"id\": \"a-single-inheritance\"\n  }, mdx(\"a\", {\n    parentName: \"h4\",\n    \"href\": \"#a-single-inheritance\",\n    \"aria-hidden\": true,\n    \"className\": \"anchor\"\n  }, mdx(\"svg\", {\n    \"aria-hidden\": \"true\",\n    height: \"16\",\n    version: \"1.1\",\n    viewBox: \"0 0 16 16\",\n    width: \"16\"\n  }, mdx(\"path\", {\n    fillRule: \"evenodd\",\n    d: \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"a. Single Inheritance\"), mdx(\"p\", null, \"Single inheritance involves one subclass inheriting from one superclass. This is the simplest form of inheritance.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-python\"\n  }, \"class Animal:\\n    def __init__(self, name):\\n        self.name = name\\n\\n    def speak(self):\\n        print(f\\\"{self.name} makes a sound.\\\")\\n\\nclass Dog(Animal):\\n    def __init__(self, name, breed):\\n        super().__init__(name)  # Call the base class constructor\\n        self.breed = breed\\n\\n    def bark(self):\\n        print(f\\\"{self.name} says woof!\\\")\\n\")), mdx(\"p\", null, \"In this example, the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Dog\"), \" class inherits from the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Animal\"), \" class. The \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Dog\"), \" class has access to both the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"name\"), \" attribute and the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"speak()\"), \" method from the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Animal\"), \" class, as well as its own \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"breed\"), \" attribute and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"bark()\"), \" method.\"), mdx(\"h4\", {\n    \"id\": \"b-multiple-inheritance\"\n  }, mdx(\"a\", {\n    parentName: \"h4\",\n    \"href\": \"#b-multiple-inheritance\",\n    \"aria-hidden\": true,\n    \"className\": \"anchor\"\n  }, mdx(\"svg\", {\n    \"aria-hidden\": \"true\",\n    height: \"16\",\n    version: \"1.1\",\n    viewBox: \"0 0 16 16\",\n    width: \"16\"\n  }, mdx(\"path\", {\n    fillRule: \"evenodd\",\n    d: \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"b. Multiple Inheritance\"), mdx(\"p\", null, \"Python supports multiple inheritance, which means a class can inherit attributes and methods from multiple base classes. This can be useful when you need to combine behavior from different classes, but it can also lead to complex inheritance hierarchies and potential conflicts if not used carefully.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-python\"\n  }, \"class Animal:\\n    def speak(self):\\n        print(\\\"Animal speaks\\\")\\n\\nclass Mammal:\\n    def eat(self):\\n        print(\\\"Mammal eats\\\")\\n\\nclass Dog(Animal, Mammal):  # Dog inherits from both Animal and Mammal\\n    def bark(self):\\n        print(\\\"Dog barks\\\")\\n\\n# Multiple inheritance\\ndog = Dog()\\ndog.speak()  # Output: Animal speaks\\ndog.eat()    # Output: Mammal eats\\ndog.bark()   # Output: Dog barks\\n\")), mdx(\"p\", null, \"In this example, the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Dog\"), \" class inherits from both the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Animal\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Mammal\"), \" classes, thus having access to methods from both.\"), mdx(\"h4\", {\n    \"id\": \"c-multilevel-inheritance\"\n  }, mdx(\"a\", {\n    parentName: \"h4\",\n    \"href\": \"#c-multilevel-inheritance\",\n    \"aria-hidden\": true,\n    \"className\": \"anchor\"\n  }, mdx(\"svg\", {\n    \"aria-hidden\": \"true\",\n    height: \"16\",\n    version: \"1.1\",\n    viewBox: \"0 0 16 16\",\n    width: \"16\"\n  }, mdx(\"path\", {\n    fillRule: \"evenodd\",\n    d: \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"c. Multilevel Inheritance\"), mdx(\"p\", null, \"Multilevel inheritance involves a chain of inheritance where a subclass inherits from a superclass, and another subclass inherits from the first subclass, creating a hierarchical structure.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-python\"\n  }, \"class Animal:\\n    def speak(self):\\n        print(\\\"Animal speaks\\\")\\n\\nclass Dog(Animal):  # Dog inherits from Animal\\n    def bark(self):\\n        print(\\\"Dog barks\\\")\\n\\nclass Labrador(Dog):  # Labrador inherits from Dog\\n    def play(self):\\n        print(\\\"Labrador plays fetch\\\")\\n\\n# Multilevel inheritance\\nlabrador = Labrador()\\nlabrador.speak()  # Output: Animal speaks\\nlabrador.bark()   # Output: Dog barks\\nlabrador.play()   # Output: Labrador plays fetch\\n\")), mdx(\"p\", null, \"In this example, the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Labrador\"), \" class inherits from both the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Dog\"), \" class (which itself inherits from \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Animal\"), \"), creating a multilevel inheritance hierarchy.\"), mdx(\"p\", null, \"In Python, you can choose the appropriate type of inheritance based on your design needs. Single inheritance is straightforward and commonly used, while multiple inheritance and multilevel inheritance provide more complex inheritance structures, allowing for greater flexibility but requiring careful design to avoid ambiguity or the diamond problem.\"), mdx(\"h3\", {\n    \"id\": \"iv-polymorphism\"\n  }, mdx(\"a\", {\n    parentName: \"h3\",\n    \"href\": \"#iv-polymorphism\",\n    \"aria-hidden\": true,\n    \"className\": \"anchor\"\n  }, mdx(\"svg\", {\n    \"aria-hidden\": \"true\",\n    height: \"16\",\n    version: \"1.1\",\n    viewBox: \"0 0 16 16\",\n    width: \"16\"\n  }, mdx(\"path\", {\n    fillRule: \"evenodd\",\n    d: \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"iv. Polymorphism\"), mdx(\"p\", null, \"Polymorphism is the ability of an object to take on many forms or to have multiple behaviors. It allows objects of different classes to be treated as objects of a common superclass, enabling code flexibility and extensibility.\"), mdx(\"h4\", {\n    \"id\": \"a-runtime-polymorphism-dynamic-method-dispatch\"\n  }, mdx(\"a\", {\n    parentName: \"h4\",\n    \"href\": \"#a-runtime-polymorphism-dynamic-method-dispatch\",\n    \"aria-hidden\": true,\n    \"className\": \"anchor\"\n  }, mdx(\"svg\", {\n    \"aria-hidden\": \"true\",\n    height: \"16\",\n    version: \"1.1\",\n    viewBox: \"0 0 16 16\",\n    width: \"16\"\n  }, mdx(\"path\", {\n    fillRule: \"evenodd\",\n    d: \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"a. Runtime Polymorphism (Dynamic Method Dispatch):\"), mdx(\"p\", null, \"Runtime polymorphism, also known as dynamic method dispatch, allows a subclass to provide a specific implementation of a method that is already provided by one of its parent classes. This is achieved through method overriding. When a method is called on an object, the Python interpreter determines which implementation to execute based on the type of object at runtime.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-python\"\n  }, \"class Animal:\\n    def __init__(self, name):\\n        self.name = name\\n\\n    def speak(self):\\n        print(f\\\"{self.name} makes a sound.\\\")\\n\\nclass Dog(Animal):\\n    def speak(self):\\n        print(f\\\"{self.name} says woof!\\\")\\n\\nclass Cat(Animal):\\n    def speak(self):\\n        print(f\\\"{self.name} says meow!\\\")\\n\\nanimals = [Dog(\\\"Buddy\\\"), Cat(\\\"Whiskers\\\"), Animal(\\\"Generic\\\")]\\n\\nfor animal in animals:\\n    animal.speak()\\n\")), mdx(\"p\", null, \"In this example, both \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Dog\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Cat\"), \" classes inherit from the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Animal\"), \" class and override the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"speak()\"), \" method with their own implementations. The \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"speak()\"), \" method is called on each object in the animals list, and the appropriate implementation of \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"speak()\"), \" is executed based on the actual type of the object.\"), mdx(\"h4\", {\n    \"id\": \"b-compile-time-polymorphism\"\n  }, mdx(\"a\", {\n    parentName: \"h4\",\n    \"href\": \"#b-compile-time-polymorphism\",\n    \"aria-hidden\": true,\n    \"className\": \"anchor\"\n  }, mdx(\"svg\", {\n    \"aria-hidden\": \"true\",\n    height: \"16\",\n    version: \"1.1\",\n    viewBox: \"0 0 16 16\",\n    width: \"16\"\n  }, mdx(\"path\", {\n    fillRule: \"evenodd\",\n    d: \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"b. Compile-time Polymorphism:\"), mdx(\"p\", null, \"Python does not support traditional compile-time polymorphism directly through method overloading, as seen in languages like Java or C++. However, Python provides a form of polymorphism through function overloading using default arguments or variable-length arguments.\"), mdx(\"p\", null, \"Here's an example using default arguments:\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-python\"\n  }, \"class Calculator:\\n    def add(self, a, b=None):\\n        if b is None:\\n            return a\\n        else:\\n            return a + b\\n\\n# Compile-time polymorphism\\ncalc = Calculator()\\nprint(calc.add(5))      # Output: 5\\nprint(calc.add(5, 3))   # Output: 8\\n\")), mdx(\"p\", null, \"In this example, the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"add()\"), \" method of the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Calculator\"), \" class can behave differently based on the number of arguments passed.\"), mdx(\"p\", null, \"However, it's important to note that this is not true compile-time polymorphism since the method resolution is done at runtime, and the decision of which method to call is made dynamically by Python.\"), mdx(\"p\", null, \"Polymorphism allows for writing more flexible and extensible code, as new classes can be added to the system without modifying the existing code that interacts with the objects.\"), mdx(\"hr\", null), mdx(\"p\", null, \"We covered the fundamental concepts of Object-Oriented Programming (OOP) in Python, including classes, objects, inheritance, polymorphism, encapsulation, and abstraction. Understanding and applying these concepts will enable you to write modular, reusable, and maintainable code, making it easier to develop complex software systems. OOP promotes code organization, extensibility, and code reuse, making it a powerful paradigm in Python programming.\"));\n}\n;\nMDXContent.isMDXComponent = true;","tableOfContents":{"items":[{"url":"#object-oriented-programming-oop","title":"Object-Oriented Programming (OOP)","items":[{"url":"#1-classes-and-objects","title":"1. Classes and Objects","items":[{"url":"#i-defining-a-class","title":"i. Defining a Class"},{"url":"#ii-creating-objects","title":"ii. Creating Objects"},{"url":"#iii-accessing-attributes-and-methods","title":"iii. Accessing Attributes and Methods"},{"url":"#iv-class-and-instance-attributes","title":"iv. Class and Instance Attributes"},{"url":"#v-class-methods-and-static-methods","title":"v. Class Methods and Static Methods"}]},{"url":"#2-introduction-to-oop-concepts","title":"2. Introduction to OOP Concepts","items":[{"url":"#i-encapsulation","title":"i. Encapsulation"},{"url":"#ii-abstraction","title":"ii. Abstraction"},{"url":"#iii-inheritance","title":"iii. Inheritance","items":[{"url":"#a-single-inheritance","title":"a. Single Inheritance"},{"url":"#b-multiple-inheritance","title":"b. Multiple Inheritance"},{"url":"#c-multilevel-inheritance","title":"c. Multilevel Inheritance"}]},{"url":"#iv-polymorphism","title":"iv. Polymorphism","items":[{"url":"#a-runtime-polymorphism-dynamic-method-dispatch","title":"a. Runtime Polymorphism (Dynamic Method Dispatch):"},{"url":"#b-compile-time-polymorphism","title":"b. Compile-time Polymorphism:"}]}]}]}]}}},"pageContext":{"id":"a41994f8-a261-53d6-aa6a-cda4e83913f9"}},"staticQueryHashes":["1022386572","1122327541","1339625561","2140385554","3442269102","3597609067"]}