{"id":712,"date":"2026-04-19T00:00:00","date_gmt":"2026-04-19T00:00:00","guid":{"rendered":"https:\/\/www.askpython.com\/?p=712"},"modified":"2026-04-20T13:43:09","modified_gmt":"2026-04-20T13:43:09","slug":"python-classes-objects","status":"publish","type":"post","link":"https:\/\/www.askpython.com\/python\/oops\/python-classes-objects","title":{"rendered":"Python Classes and Objects"},"content":{"rendered":"<p>I keep coming back to Python classes because they are the foundation of every non-trivial program I write. After years of using them daily, I have a good sense of what actually helps someone grasp this material quickly and what just confuses people. This guide is the article I wish I had when I started.<\/p>\n<p>Python classes are not complicated once you understand a few core ideas. You define a class to create a blueprint, then you instantiate it to get objects that hold data and can perform actions. That is the whole idea. Everything else in object-oriented programming is just building on top of this simple foundation.<\/p>\n<h2 class=\"wp-block-heading\">TLDR<\/h2>\n<ul class=\"wp-block-list\">\n<li>A Python class is a blueprint that defines attributes (data) and methods (functions) bundled together as a single unit<\/li>\n<li>Instantiate a class by calling it like a function: <code>emp = Employee(1001, \"Alice\")<\/code><\/li>\n<li>The <code>__init__<\/code> method initializes each new object and always takes <code>self<\/code> as the first parameter<\/li>\n<li>Instance variables are unique to each object; class variables are shared across all instances<\/li>\n<li>Use <code>@classmethod<\/code> for methods that need access to the class itself, and <code>@staticmethod<\/code> for utility functions that do not need any implicit argument<\/li>\n<\/ul>\n\n\n<h2 class=\"wp-block-heading\">What Is a Python Class?<\/h2>\n<p>A class is a blueprint for creating objects. It bundles data (called attributes or properties) and functions (called methods) into a single unit. When you define a class, you are not creating any objects yet. You are just describing what those objects will look like and what they can do.<\/p>\n<p>For example, imagine you run a company with employees. You could create an Employee class that describes every employee: each one has an ID number and a name, and each one can perform work. The class itself does not represent a specific employee. It is just the template you use to create actual employee objects.<\/p>\n<p>Here is the simplest possible class in Python:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n\n\n\nclass Employee:\n    pass\n\n\n\n<\/pre><\/div>\n<p>An empty class is not useful on its own, but it shows the basic syntax. You use the <code>class<\/code> keyword followed by the class name and a colon. Everything indented below belongs to the class.<\/p>\n<p>Let me add some actual attributes and methods to make this class do something:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n\n\n\nclass Employee:\n    company_name = &quot;Acme Corp&quot;\n\n    def __init__(self, employee_id, name):\n        self.employee_id = employee_id\n        self.name = name\n\n    def work(self):\n        print(f&quot;{self.name} (ID: {self.employee_id}) is working&quot;)\n\n    def get_info(self):\n        return f&quot;{self.name} - {self.employee_id} - {self.company_name}&quot;\n\n\n\n<\/pre><\/div>\n<h2 class=\"wp-block-heading\">How to Create an Object from a Class<\/h2>\n<p>Creating an object from a class is called instantiation. You call the class as if it were a function, and Python returns a new object that is an instance of that class.<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n\n\n\nemp1 = Employee(1001, &quot;Alice&quot;)\nemp2 = Employee(1002, &quot;Bob&quot;)\n\nemp1.work()\nprint(emp2.get_info())\n\n\n\n<\/pre><\/div>\n<p>The output looks like this:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n\n\n\nAlice (ID: 1001) is working\nBob - 1002 - Acme Corp\n\n\n\n<\/pre><\/div>\n<p>Each object has its own identity. emp1 and emp2 are distinct objects, even though they come from the same class. Changing emp1&#8217;s name does not affect emp2&#8217;s name.<\/p>\n<h2 class=\"wp-block-heading\">Understanding the __init__ Method<\/h2>\n<p>The <code>__init__<\/code> method is a special method that Python calls automatically when you create a new object. People call it a constructor, which is mostly accurate, though technically Python does not have true constructors like Java or C++. The <code>__init__<\/code> method sets up the object with initial values.<\/p>\n<p>The first parameter of every method in a class is always <code>self<\/code>. <code>self<\/code> refers to the current instance of the class. When I call <code>emp1.work()<\/code>, Python passes emp1 as the <code>self<\/code> argument. This is how each object knows which data belongs to itself.<\/p>\n<p>Here is what happens when you forget to pass the required arguments:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n\n\n\nemp3 = Employee()\n\n\n\n<\/pre><\/div>\n<p>Running that code produces:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n\n\n\nTypeError: __init__() missing 2 required positional arguments: &#039;employee_id&#039; and &#039;name&#039;\n\n\n\n<\/pre><\/div>\n<h2 class=\"wp-block-heading\">Default Values in __init__<\/h2>\n<p>You can give parameters default values by assigning them in the method signature. This lets callers omit arguments they do not want to specify:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n\n\n\nclass Employee:\n    def __init__(self, employee_id, name, department=&quot;General&quot;):\n        self.employee_id = employee_id\n        self.name = name\n        self.department = department\n\n    def get_info(self):\n        return f&quot;{self.name} (ID: {self.employee_id}) - {self.department}&quot;\n\nemp1 = Employee(1001, &quot;Alice&quot;)\nemp2 = Employee(1002, &quot;Bob&quot;, &quot;Engineering&quot;)\n\nprint(emp1.get_info())\nprint(emp2.get_info())\n\n\n\n<\/pre><\/div>\n<p>The output:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n\n\n\nAlice (1001) - General\nBob (1002) - Engineering\n\n\n\n<\/pre><\/div>\n<h2 class=\"wp-block-heading\">Class Variables vs Instance Variables<\/h2>\n<p>There are two kinds of attributes in a Python class: class variables and instance variables.<\/p>\n<p>Instance variables are defined inside <code>__init__<\/code> and are unique to each object. In the Employee class, <code>employee_id<\/code> and <code>name<\/code> are instance variables. Each Employee object has its own copy of these values.<\/p>\n<p>Class variables are defined directly inside the class but outside any method. They are shared across all instances of the class. In the Employee class, <code>company_name<\/code> is a class variable. Every Employee object sees the same value for <code>company_name<\/code>.<\/p>\n<p>Here is an example that shows the difference clearly:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n\n\n\nclass Employee:\n    company_name = &quot;Acme Corp&quot;\n    total_employees = 0\n\n    def __init__(self, employee_id, name):\n        self.employee_id = employee_id\n        self.name = name\n        Employee.total_employees += 1\n\n    def get_info(self):\n        return f&quot;{self.name} (ID: {self.employee_id}) at {self.company_name}&quot;\n\n\nprint(f&quot;Before hiring: {Employee.total_employees}&quot;)\nemp1 = Employee(1001, &quot;Alice&quot;)\nemp2 = Employee(1002, &quot;Bob&quot;)\nprint(f&quot;After hiring: {Employee.total_employees}&quot;)\n\nprint(emp1.get_info())\nprint(emp2.get_info())\n\nEmployee.company_name = &quot;NewCorp&quot;\nprint(emp1.get_info())\nprint(emp2.get_info())\n\n\n\n<\/pre><\/div>\n<p>The output demonstrates how class variables work:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n\n\n\nBefore hiring: 0\nAfter hiring: 2\nAlice (ID: 1001) at Acme Corp\nBob (ID: 1002) at Acme Corp\nAlice (ID: 1001) at NewCorp\nBob (ID: 1002) at NewCorp\n\n\n\n<\/pre><\/div>\n<p>When I changed <code>company_name<\/code> on the class, it affected all objects. That is the key property of class variables: they are shared. If you modify a class variable through one object, all objects see that change because they all reference the same underlying value.<\/p>\n<h2 class=\"wp-block-heading\">The Base Class object<\/h2>\n<p>Every class in Python automatically inherits from a base class called <code>object<\/code>. You do not need to write anything for this to happen. When you define <code>class Employee:<\/code>, Python internally makes it <code>class Employee(object):<\/code>.<\/p>\n<p>This inheritance is why every class in Python has methods like <code>__str__<\/code>, <code>__repr__<\/code>, and <code>__eq__<\/code>. These methods come from the <code>object<\/code> base class and can be overridden in your own class.<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n\n\n\nemp1 = Employee(1001, &quot;Alice&quot;)\nprint(type(emp1))\nprint(emp1.__class__)\nprint(emp1.__class__.__bases__)\n\n\n\n<\/pre><\/div>\n<p>Output:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n\n\n\n&lt;class &#039;__main__.Employee&#039;&gt;\n&lt;class &#039;__main__.Employee&#039;&gt;\n(&lt;class &#039;object&#039;&gt;,)\n\n\n\n<\/pre><\/div>\n<h2 class=\"wp-block-heading\">Data Encapsulation in Python<\/h2>\n<p>Encapsulation means bundling data and methods that operate on that data inside a single unit (the class). Python uses naming conventions to indicate whether an attribute is meant to be private or public.<\/p>\n<p>A single underscore <code>_attribute<\/code> signals to other developers that the attribute is intended for internal use. A double underscore <code>__attribute<\/code> triggers name mangling, which makes it harder to access from outside the class by accident.<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n\n\n\nclass Employee:\n    def __init__(self, employee_id, name, salary):\n        self.employee_id = employee_id\n        self.name = name\n        self.__salary = salary  # private attribute\n\n    def get_salary(self):\n        return f&quot;{self.name} earns ${self.__salary}&quot;\n\n    def set_salary(self, new_salary):\n        if new_salary &gt; 0:\n            self.__salary = new_salary\n        else:\n            print(&quot;Salary must be positive&quot;)\n\n\nemp = Employee(1001, &quot;Alice&quot;, 50000)\nprint(emp.get_salary())\nemp.set_salary(55000)\nprint(emp.get_salary())\n\n# Name mangling makes this harder to access accidentally\nprint(emp._Employee__salary)\n\n\n\n<\/pre><\/div>\n<p>Output:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n\n\n\nAlice earns $50000\nAlice earns $55000\n55000\n\n\n\n<\/pre><\/div>\n<p>Python&#8217;s name mangling changes <code>__salary<\/code> to <code>_Employee__salary<\/code>, which is harder to accidentally access. It is not true privacy like you get in Java or C++, but it signals intent and prevents casual mistakes.<\/p>\n<h2 class=\"wp-block-heading\">The __str__ and __repr__ Methods<\/h2>\n<p>When you print an object, Python calls the object&#8217;s <code>__str__<\/code> method. When you display it in the interactive interpreter or use <code>repr()<\/code>, Python calls <code>__repr__<\/code>. Providing these methods makes your objects easier to debug and more informative when printed.<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n\n\n\nclass Employee:\n    def __init__(self, employee_id, name):\n        self.employee_id = employee_id\n        self.name = name\n\n    def __repr__(self):\n        return f&quot;Employee(employee_id={self.employee_id}, name=&#039;{self.name}&#039;)&quot;\n\n    def __str__(self):\n        return f&quot;{self.name} (ID: {self.employee_id})&quot;\n\n\nemp = Employee(1001, &quot;Alice&quot;)\nprint(repr(emp))\nprint(str(emp))\nprint(emp)\n\n\n\n<\/pre><\/div>\n<p>Output:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n\n\n\nEmployee(employee_id=1001, name=&#039;Alice&#039;)\nAlice (ID: 1001)\nAlice (ID: 1001)\n\n\n\n<\/pre><\/div>\n<h2 class=\"wp-block-heading\">Class Methods and Static Methods<\/h2>\n<p>So far I have shown instance methods, which operate on specific objects. Python also supports class methods and static methods, which operate at the class level rather than on individual instances.<\/p>\n<p>Class methods receive the class itself as the first argument, denoted by <code>cls<\/code>. Use the <code>@classmethod<\/code> decorator. Static methods do not receive any implicit first argument. Use the <code>@staticmethod<\/code> decorator.<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n\n\n\nclass Employee:\n    company_name = &quot;Acme Corp&quot;\n    minimum_wage = 30000\n\n    def __init__(self, employee_id, name, salary):\n        self.employee_id = employee_id\n        self.name = name\n        self.salary = salary\n\n    @classmethod\n    def set_minimum_wage(cls, amount):\n        cls.minimum_wage = amount\n\n    @staticmethod\n    def validate_employee_id(employee_id):\n        return isinstance(employee_id, int) and employee_id &gt; 0\n\n    def get_info(self):\n        return f&quot;{self.name} earns ${self.salary}&quot;\n\n\n# Static method call - no instance needed\nprint(Employee.validate_employee_id(1001))\nprint(Employee.validate_employee_id(-5))\n\n# Class method call - affects the class variable\nEmployee.set_minimum_wage(35000)\nprint(Employee.minimum_wage)\n\n\n\n<\/pre><\/div>\n<p>Output:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n\n\n\nTrue\nFalse\n35000\n\n\n\n<\/pre><\/div>\n<h2 class=\"wp-block-heading\">A Practical Example: Bank Account<\/h2>\n<p>Let me put everything together with a realistic example. A bank account class needs to track a balance, allow deposits and withdrawals, and prevent invalid operations like withdrawing more than the available balance.<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n\n\n\nclass BankAccount:\n    def __init__(self, account_holder, initial_balance=0):\n        self.account_holder = account_holder\n        self.__balance = initial_balance\n        self.transaction_count = 0\n\n    def deposit(self, amount):\n        if amount &lt;= 0:\n            print(&quot;Deposit amount must be positive&quot;)\n            return False\n        self.__balance += amount\n        self.transaction_count += 1\n        print(f&quot;Deposited ${amount}. New balance: ${self.__balance}&quot;)\n        return True\n\n    def withdraw(self, amount):\n        if amount &lt;= 0:\n            print(&quot;Withdrawal amount must be positive&quot;)\n            return False\n        if amount &gt; self.__balance:\n            print(f&quot;Insufficient funds. Available balance: ${self.__balance}&quot;)\n            return False\n        self.__balance -= amount\n        self.transaction_count += 1\n        print(f&quot;Withdrew ${amount}. New balance: ${self.__balance}&quot;)\n        return True\n\n    def get_balance(self):\n        return self.__balance\n\n    def __repr__(self):\n        return f&quot;BankAccount(holder=&#039;{self.account_holder}&#039;, balance={self.__balance})&quot;\n\n\n# Example usage\naccount = BankAccount(&quot;Alice&quot;, 1000)\naccount.deposit(500)\naccount.withdraw(200)\naccount.withdraw(2000)\nprint(f&quot;Final balance: ${account.get_balance()}&quot;)\nprint(f&quot;Total transactions: {account.transaction_count}&quot;)\nprint(repr(account))\n\n\n\n<\/pre><\/div>\n<p>Output:<\/p>\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n\n\n\nDeposited $500. New balance: $1500\nWithdrew $200. New balance: $1300\nInsufficient funds. Available balance: $1300\nFinal balance: $1300\nTotal transactions: 2\nBankAccount(holder=&#039;Alice&#039;, balance=1300)\n\n\n\n<\/pre><\/div>\n<p>This example shows encapsulation (the <code>__balance<\/code> attribute cannot be modified directly), validation (deposits and withdrawals must be positive), and proper state management (tracking the transaction count).<\/p>\n<h2 class=\"wp-block-heading\">Frequently Asked Questions<\/h2>\n<p><strong>What is the difference between a class and an object?<\/strong><\/p>\n<p>A class is the blueprint. An object is the actual thing created from that blueprint. Think of it like a house blueprint (the class) and an actual house built from that blueprint (the object). One blueprint can produce many houses, and each house is an independent object.<\/p>\n<p><strong>What does the self parameter do in Python classes?<\/strong><\/p>\n<p><code>self<\/code> refers to the specific instance of the class on which a method is called. When you write <code>emp.work()<\/code>, Python passes emp as the <code>self<\/code> argument to the <code>work<\/code> method. This is how each object knows which data belongs to itself versus shared with other instances.<\/p>\n<p><strong>Are Python classes only for object-oriented programming?<\/strong><\/p>\n<p>Not exclusively. Python supports multiple programming paradigms. You can write functional code, procedural code, or object-oriented code. Classes are a tool. You reach for them when the problem naturally fits the concept of multiple related objects with shared behavior or shared data. For simple scripts, a class may be overkill.<\/p>\n<p><strong>What is the difference between __str__ and __repr__?<\/strong><\/p>\n<p><code>__repr__<\/code> is meant for unambiguous debugging output &#8211; ideally it is valid Python code that recreates the object. <code>__str__<\/code> is for human-readable output. If you print an object, Python prefers <code>__str__<\/code>. In the interactive interpreter, <code>__repr__<\/code> takes priority. If you only implement one, implement <code>__repr__<\/code> &#8211; Python falls back to it when <code>__str__<\/code> is missing.<\/p>\n<p><strong>Can a class have multiple __init__ methods?<\/strong><\/p>\n<p>No. Python only ever calls one <code>__init__<\/code> method. If you need different ways to create an object, use factory methods with <code>@classmethod<\/code>. For example, <code>Employee.from_dictionary(data)<\/code> creates an Employee from a dictionary instead of individual arguments.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I keep coming back to Python classes because they are the foundation of every non-trivial program I write. After years of using them daily, I have a good sense of what actually helps someone grasp this material quickly and what just confuses people. This guide is the article I wish I had when I started. [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":39824,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11],"tags":[481],"class_list":["post-712","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oops","tag-python-classes-and-objects"],"blocksy_meta":[],"_links":{"self":[{"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/posts\/712","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/comments?post=712"}],"version-history":[{"count":0,"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/posts\/712\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/media\/39824"}],"wp:attachment":[{"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/media?parent=712"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/categories?post=712"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.askpython.com\/wp-json\/wp\/v2\/tags?post=712"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}