Extending bp's answer, I wanted to show you what he meant by immutable types.

First, this is okay:

>>> class TestB():
...     def __init__(self, attr=1):
...         self.attr = attr
...     
>>> a = TestB()
>>> b = TestB()
>>> a.attr = 2
>>> a.attr
2
>>> b.attr
1

However, this only works for immutable (unchangable) types. If the default value was mutable (meaning it can be replaced), this would happen instead:

>>> class Test():
...     def __init__(self, attr=[]):
...         self.attr = attr
...     
>>> a = Test()
>>> b = Test()
>>> a.attr.append(1)
>>> a.attr
[1]
>>> b.attr
[1]
>>> 

Note that both a and b have a shared attribute. This is often unwanted.

This is the Pythonic way of defining default values for instance variables, when the type is mutable:

>>> class TestC():
...     def __init__(self, attr=None):
...         if attr is None:
...             attr = []
...         self.attr = attr
...     
>>> a = TestC()
>>> b = TestC()
>>> a.attr.append(1)
>>> a.attr
[1]
>>> b.attr
[]

The reason my first snippet of code works is because, with immutable types, Python creates a new instance of it whenever you want one. If you needed to add 1 to 1, Python makes a new 2 for you, because the old 1 cannot be changed. The reason is mostly for hashing, I believe.

Answer from Xavier Ho on Stack Overflow
Top answer
1 of 6
187

Extending bp's answer, I wanted to show you what he meant by immutable types.

First, this is okay:

>>> class TestB():
...     def __init__(self, attr=1):
...         self.attr = attr
...     
>>> a = TestB()
>>> b = TestB()
>>> a.attr = 2
>>> a.attr
2
>>> b.attr
1

However, this only works for immutable (unchangable) types. If the default value was mutable (meaning it can be replaced), this would happen instead:

>>> class Test():
...     def __init__(self, attr=[]):
...         self.attr = attr
...     
>>> a = Test()
>>> b = Test()
>>> a.attr.append(1)
>>> a.attr
[1]
>>> b.attr
[1]
>>> 

Note that both a and b have a shared attribute. This is often unwanted.

This is the Pythonic way of defining default values for instance variables, when the type is mutable:

>>> class TestC():
...     def __init__(self, attr=None):
...         if attr is None:
...             attr = []
...         self.attr = attr
...     
>>> a = TestC()
>>> b = TestC()
>>> a.attr.append(1)
>>> a.attr
[1]
>>> b.attr
[]

The reason my first snippet of code works is because, with immutable types, Python creates a new instance of it whenever you want one. If you needed to add 1 to 1, Python makes a new 2 for you, because the old 1 cannot be changed. The reason is mostly for hashing, I believe.

2 of 6
83

The two snippets do different things, so it's not a matter of taste but a matter of what's the right behaviour in your context. Python documentation explains the difference, but here are some examples:

Exhibit A

class Foo:
  def __init__(self):
    self.num = 1

This binds num to the Foo instances. Change to this field is not propagated to other instances.

Thus:

>>> foo1 = Foo()
>>> foo2 = Foo()
>>> foo1.num = 2
>>> foo2.num
1

Exhibit B

class Bar:
  num = 1

This binds num to the Bar class. Changes are propagated!

>>> bar1 = Bar()
>>> bar2 = Bar()
>>> bar1.num = 2 #this creates an INSTANCE variable that HIDES the propagation
>>> bar2.num
1
>>> Bar.num = 3
>>> bar2.num
3
>>> bar1.num
2
>>> bar1.__class__.num
3

Actual answer

If I do not require a class variable, but only need to set a default value for my instance variables, are both methods equally good? Or one of them more 'pythonic' than the other?

The code in exhibit B is plain wrong for this: why would you want to bind a class attribute (default value on instance creation) to the single instance?

The code in exhibit A is okay.

If you want to give defaults for instance variables in your constructor I would however do this:

class Foo:
  def __init__(self, num = None):
    self.num = num if num is not None else 1

...or even:

class Foo:
  DEFAULT_NUM = 1
  def __init__(self, num = None):
    self.num = num if num is not None else DEFAULT_NUM

...or even: (preferrable, but if and only if you are dealing with immutable types!)

class Foo:
  def __init__(self, num = 1):
    self.num = num

This way you can do:

foo1 = Foo(4)
foo2 = Foo() #use default
🌐
Reddit
reddit.com › r/learnpython › class init method: best way for default value assignments
r/learnpython on Reddit: class init method: best way for default value assignments
December 18, 2021 -

I am learning linked lists in python using classes.

One place that I am learning from is doing:

class Node:
    def __init__(self, value):
        self.value = value
        self.next = None

The other place is doing:

class Node:
    def __init__(self, value, next = None):
        self.value = value
        self.next = next

I can't figure out what difference it makes to use either init method. I tried to search this answer out using StackOverflow, but I had no luck.

I get that one is able to define 'next' during instantiation and the other would need to be defined after instantiation, but when would and why would you use one over the other?

edit: Thanks all. I am just starting to understand classes and still overthinking a little.

🌐
Rip Tutorial
riptutorial.com › default values for instance variables
Python Language Tutorial => Default values for instance variables
Similarities in syntax, Differences in meaning: Python vs. JavaScript ... If the variable contains a value of an immutable type (e.g. a string) then it is okay to assign a default value like this · class Rectangle(object): def __init__(self, width, height, color='blue'): self.width = width self.height = height self.color = color def area(self): return self.width * self.height # Create some instances of the class default_rectangle = Rectangle(2, 3) print(default_rectangle.color) # blue red_rectangle = Rectangle(2, 3, 'red') print(red_rectangle.color) # red
🌐
Python Examples
pythonexamples.org › python-default-values-for-properties-in-class
Set Default Values for Properties in Class in Python
class Person: name="NA" age="0" ... Person Details Name : Mike Age : 21 · As we already mentioned, we can use named parameters in __init__() function definition to set default value for the properties....
🌐
Abdul Wahab Junaid
awjunaid.com › home › default values for instance variables in python
Default values for instance variables in python | Abdul Wahab Junaid
August 14, 2023 - By assigning default values in the constructor, you can ensure that instances are created with specific initial values for those attributes. ... class Person: def __init__(self, name, age=18): self.name = name self.age = age # Create instances ...
🌐
GeeksforGeeks
geeksforgeeks.org › python › __init__-in-python
__init__ in Python - GeeksforGeeks
Like regular functions, __init__() can have parameters with default values. ... class Dog: def __init__(self, name, breed="Mixed", age=1): self.name = name self.breed = breed self.age = age a = Dog("Buddy") b = Dog("Max", "Golden Retriever", 5) print(a.name, a.breed, a.age) print(b.name, b.breed, b.age) ... When creating Dog("Buddy"), Python uses the defaults, breed = "Mixed", age = 1.
Published: May 11, 2026
🌐
Stack Overflow
stackoverflow.com › questions › 71934568 › python-are-these-default-values-being-passed-to-the-init-function-necessary
Python: Are these default values being passed to the __init__ function necessary? - Stack Overflow
If someone using the class, for whatever reason, does del mypizza.slices, then future access to mypizza.slices will still "work", but will retrieve the value from the class attribute (since the instance attribute was blown away). Sane code should almost never do this. In all other ways, there is no relationship between the class level attributes and the defaults defined for the __init__ initializer method; the moment __init__ assigns to self.slices and self.temperature, it shadows the class level attributes so they cannot be directly accessed from that instance of the class (without deleting the instance attributes or bypassing the instance to look at the values on the class itself).
Find elsewhere
🌐
Bruceeckel
bruceeckel.com › 2022 › 05 › 11 › misunderstanding-python-class-attributes
Misunderstanding Python Class Attributes
May 11, 2022 - After doing a few simple experiments as in 1_like_default_values.py, a C++ or Java programmer might well conclude that Python does indeed work that way. And, because a class attribute is a single variable that is “global to the class,” it can be mistaken for a default value. The worst thing about this is that code written with the assumption that class attributes are just default initialization values seems to work most of the time for simple situations like the one I encountered.
🌐
W3Schools
w3schools.com › PYTHON › python_class_init.asp
Python __init__() Method
With __init__(), you can set initial values when creating the object: class Person: def __init__(self, name, age): self.name = name self.age = age p1 = Person("Linus", 28) print(p1.name) print(p1.age) Try it Yourself » · You can also set default values for parameters in the __init__() method:
🌐
LabEx
labex.io › tutorials › python-how-to-initialize-data-in-a-python-class-417302
How to initialize data in a Python class | LabEx
In this example, the __init__() method takes two parameters, name and age, and assigns them to the corresponding attributes of the Person class. You can also define class attributes directly within the class definition, outside of any methods. These attributes are shared among all instances of the class and are often used to store default or constant values.
🌐
Anvil
anvil.works › anvil q&a
Understand the behavior of default params in python classes - Anvil Q&A - Anvil Community Forum
September 30, 2021 - What I’m trying to do: Understand the behavior of default params in python classes. I made a sort of random change to the class init, which achieves the behavior I want, but I don’t understand why it does. What I’ve tried and what’s not working: Originally in the Week Custom component the init looked like: def __init__(self, week_number, days = [], **properties): self.days = days self.week_number = week_number self.init_components(**properties) When printing the length of the ...
🌐
Great Learning
mygreatlearning.com › blog › it/software development › python __init__: an overview
Python __init__: An Overview
October 14, 2024 - The python __init__ method is declared within a class and is used to initialize the attributes of an object as soon as the object is formed. While giving the definition for an __init__(self) method, a default parameter, named ‘self’ is always passed in its argument. This self represents the object of the class itself. Like in any other method of a class, in case of __init__ also ‘self’ is used as a dummy object variable for assigning values to the data members of an object.
🌐
pythontutorials
pythontutorials.net › blog › how-should-i-declare-default-values-for-instance-variables-in-python
How to Declare Default Values for Instance Variables in Python: Class vs __init__ – Which is More Pythonic?
Python offers two primary ways to declare default values for instance variables: 1. **Class-level declaration**: Assigning the default directly in the class body (outside the `__init__` method).
🌐
Mimo
mimo.org › glossary › python › init-function
Python __init__() Function: Syntax, Usage, and Examples
The Python __init__() function is a special method defined within a class. It runs automatically when a class is instantiated, which makes it ideal for setting default values or handling any setup required for new objects.
🌐
Udacity
udacity.com › blog › 2021 › 11 › __init__-in-python-an-overview.html
__init__ in Python: An Overview | Udacity
June 10, 2026 - Each one would hold different values. They all came from the same class. This is the pattern you will use most often. Required parameters make it clear what data each object needs to work properly. Python’s __init__ supports default parameter values, just like any other function.
🌐
Copahost
copahost.com › home › init in python: how object initialisation works
init python: Learn how to use __init__ to initialize objects in ...
August 29, 2023 - Writing Car("Toyota", "Corolla") runs it, and the arguments you pass go to its parameters — all of them except self, which Python supplies. ⚠️ And it isn’t a constructor, strictly speaking. The object already exists by the time __init__ runs; its job is to fill it in. This guide covers self, default values, inheritance with super(), the mutable default trap, and when a dataclass makes __init__ unnecessary. ... class ClassName: def __init__(self, parameter1, parameter2): self.attribute1 = parameter1 self.attribute2 = parameter2
🌐
Quora
quora.com › In-Python-how-do-you-stop-the-default-argument-value-from-initializing-a-class
In Python, how do you stop the default argument value from initializing a class? - Quora
Answer (1 of 6): This pattern is a very bad idea. Please remove this code from wherever you’ve used it as soon as possible, some injuries may happen. A common mistake made by python programmers is to forget what are the objects the language is managing, and relax thanks to the soft typing featu...
Top answer
1 of 2
2

As explained by user2357112, the problem with this is that __init__ only sometimes defines the type parameter, and that explicit types can fail.

To express defaults in this way, you would need to restrict the default option to the corresponding type. You can do this with overload with a restriction on self. For example

class IntOrStrReplicator(Generic[T1]):
    @overload
    def __init__(self: "IntOrStrReplicator[int]") -> None:
        # int variant, only, allows leaving the parameter implied
        ...

    @overload
    def __init__(self: "IntOrStrReplicator[T1]", a:T1) -> None:
        # supplying the parameter requires that the type match.
        ...

    def __init__(self, a = 4) -> None:
        # This function needs programmer care because `a` still isn't checked
        # but consumers of the class take the overload definitions.
        self.a: T1 = a
2 of 2
2

When a Generic class has a default value in an init parameter, MyPy complains about the possibility of a type mismatch even though the init parameter defines the type.

The problem here is that the __init__ parameter does not define the type. You can do something like

x = IntOrStrReplicatorstr

where the type variable is bound to str, but the default value is still 4.

Your code isn't saying that IntOrStrReplicator() defaults to IntOrStrReplicatorint. Your code is saying that both IntOrStrReplicatorint and IntOrStrReplicatorstr use a default argument of 4. IntOrStrReplicatorstr a type error, which is why your default value is invalid.

I don't think there's any way to express what you seem to have intended.


In the absence of an explicit type argument, type checkers will attempt to infer the type, but even then, it doesn't just go by the constructor arguments. It also takes the context into account, so in the following code:

from typing import Generic, TypeVar

T = TypeVar('T')

class Foo(Generic[T]):
    def __init__(self, x: T):
        self.x = x

def f(x: Foo[int]): pass
def g(x: Foo[object]): pass

f(Foo(3))
g(Foo(3))

T is deduced as int for the first Foo(3) and object for the second Foo(3).