Dynamically defining instance fields in Python classes

后端 未结 3 1467
闹比i
闹比i 2021-02-05 10:48

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 __ini

3条回答
  •  伪装坚强ぢ
    2021-02-05 11:19

    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__
    
    

    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 "", line 1, in 
    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 "", line 1, in 
      File "", 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.)

提交回复
热议问题