pythonpython-3.xpython-object

Can I declare Python class fields outside the constructor method?


I am absolutely new to Python (I came from Java) and I have the following doubts about class fields.

Considering code like this:

class Toy():
    def __init__(self, color, age):
        self.color = color
        self.age = age

action_figure = Toy('red', 10)

What is done is clear and very simple:

it is defining a Toy class. The constructor is defining two fields setting their values. Finally (in main) a new Toy instance is created, passing the values of the fields in the constructor call.

In Java to define the same class I do something like this:

public class Toy {
    private String color;
    private int age;

    // CONSTRUCTOR:
    public Dog(String color, int age) {
        this.color = color;
        this.age = age;
    }
}

It is similar, but I have figured out a pretty big difference. In my Java code I declare the class fields as variables outside my constructor. In Python I am defining the class fields directly inside the constructor. So it means that in Java I can declare several fields and use the constructor method to initialize only a subset of these fields, for example something like this:

public class Toy {
    private String color;
    private int age;
    private String field3;
    private String field4;
    private String field5;

    // CONSTRUCTOR:
    public Dog(String color, int age) {
        this.color = color;
        this.age = age;
    }
}

where I also have the field3, field4 and field5 fields that will be not initialized by my constructor. (In case I can set their value subsequently with a setter method.)

Can I do something similar in Python? Can I declare class fields outside the constructor method?


Solution

  • Classes in python vs in c++/java are fundamentally different in that a c++/java class has a fixed data structure and size (bytes) because each attribute is declared or defined outside of all methods (normally as private variables) but in python everything is on the fly(dynamically typed).

    Choice of defining attribute in constructor vs other methods is about other people being able to quickly understand your code/data structure (although due to dynamic-ness calling python classes data structures would be inappropriate)

    As an example of dynamic-ness You can even add new methods and attributes to classes and even instances at run time:

    class A:
        pass
    

    Adding stuff to a class at runtime (These will be added to all existing and future instances of the class):

    A.key = val
    
    def f(self):
        return 0
    
    A.myfunction = f
    a = A()
    a.myfunction()
    # 0
    

    Adding stuff to a single instance at runtime:

    a=A()
    a.attr='something'
    
    def f(self):
        return 0
    
    a.fun=f.__get__(a)
    a.fun()
    # 0