Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically defining instance fields in Python classes

Tags:

python

I am new to Python having come from mainly Java programming.

I am currently pondering over how classes in Python are instantiated.

I understand that __init__(): is like the constructor in Java. However, sometimes python classes do not have an __init__() method which in this case I assume there is a default constructor just like in Java?

Another thing that makes the transition from Java to python slightly difficult is that in Java you have to define all the instance fields of the class with the type and sometimes an initial value. In python all of this just seems to disappear and developers can just define new fields on the fly.

For example I have come across a program like so:

class A(Command.UICommand):
    FIELDS = [
        Field( 'runTimeStepSummary', BOOL_TYPE)
        ]

    def __init__(self, runTimeStepSummary=False):
        self.runTimeStepSummary = runTimeStepSummary

    """Other methods"""

    def execute(self, cont, result):
        self.timeStepSummaries = {}
        """ other code"""

The thing that confuses (and slightly irritates me) is that this A class does not have a field called timeStepSummaries yet how can a developer in the middle of a method just define a new field? or is my understanding incorrect?

So to be clear, my question is in Python can we dynamically define new fields to a class during runtime like in this example or is this timeStepSummaries variable an instance of a java like private variable?

EDIT: I am using python 2.7

like image 441
SeekingAlpha Avatar asked Feb 02 '14 23:02

SeekingAlpha


People also ask

How do you create an instance of a class dynamically in Python?

Python Code can be dynamically imported and classes can be dynamically created at run-time. Classes can be dynamically created using the type() function in Python. The type() function is used to return the type of the object. The above syntax returns the type of object.

Where are instance variables defined in a Python class?

Let's start on class and instance variables. Class variables are declared inside a class but outside of any function. Instance variables are declared inside the constructor which is the __init__method.

What are dynamic attributes in Python?

Dynamic attributes in Python are terminologies for attributes that are defined at runtime, after creating the objects or instances. In Python we call all functions, methods also as an object. So you can define a dynamic instance attribute for nearly anything in Python.

Which is the correct way of defining instance method of any class in Python?

Using the instance method, we can access or modify the calling object's attributes. Instance methods are defined inside a class, and it is pretty similar to defining a regular function. Use the def keyword to define an instance method in Python. Use self as the first parameter in the instance method when defining it.


2 Answers

I understand that __init__(): is like the constructor in Java.

To be more precise, in Python __new__ is the constructor method, __init__ is the initializer. When you do SomeClass('foo', bar='baz'), the type.__call__ method basically does:

def __call__(cls, *args, **kwargs):
    instance = cls.__new__(*args, **kwargs)
    instance.__init__(*args, **kwargs)
    return instance

Generally, most classes will define an __init__ if necessary, while __new__ is more commonly used for immutable objects.

However, sometimes python classes do not have an init() method which in this case I assume there is a default constructor just like in Java?

I'm not sure about old-style classes, but this is the case for new-style ones:

>>>> object.__init__
<slot wrapper '__init__' of 'object' objects>

If no explicit __init__ is defined, the default will be called.

So to be clear, my question is in Python can we dynamically define new fields to a class during runtime like in this example

Yes.

>>> class A(object):
...     def __init__(self):
...         self.one_attribute = 'one'
...     def add_attr(self):
...         self.new_attribute = 'new'
...

>>> a = A()
>>> a.one_attribute
'one'
>>> a.new_attribute
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute 'new_attribute'
>>> a.add_attr()
>>> a.new_attribute
'new'

Attributes can be added to an instance at any time:

>>> a.third_attribute = 'three'
>>> a.third_attribute
'three'

However, it's possible to restrict the instance attributes that can be added through the class attribute __slots__:

>>> class B(object):
...     __slots__ = ['only_one_attribute']
...     def __init__(self):
...         self.only_one_attribute = 'one'
...     def add_attr(self):
...         self.another_attribute = 'two'
...

>>> b = B()
>>> b.add_attr()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in add_attr
AttributeError: 'B' object has no attribute 'another_attribute'

(It's probably important to note that __slots__ is primarily intended as a memory optimization - by not requiring an object have a dictionary for storing attributes - rather than as a form of run-time modification prevention.)

like image 85
Matthew Trevor Avatar answered Oct 16 '22 02:10

Matthew Trevor


Attributes of Python objects are generally stored in a dictionary, just like the ones you create with {}. Since you can add new items to a dictionary at any time, you can add attributes to an object at any time. And since any type of object can be stored in a dictionary without previous declaration of type, any type of object can be stored as an attribute of an object.

In short, my_object.abc = 42 is (often) just a shorthand for my_object.__dict__["abc"] = 42.

It is possible to define objects without a __dict__ by defining the __slots__ attribute, or to override certain special methods and store attributes in some other way, though most of the time you shouldn't do that.

like image 20
kindall Avatar answered Oct 16 '22 02:10

kindall