Difference between self.arg = arg and self .__ dict __ ['arg'] = arg in Python

When I make a class definition, I always go

Class A(object):
    def __init__(self, arg):
        self.arg = arg
    def print_arg(self):
        print(self.arg)

a = A ('hello')

print a.arg

'Hi'

But what I found on lines 133 and 134   https://github.com/Pylons/webob/blob/master/src/webob/request.py made me think what is the difference between what I did in class A , with:

Class B(object):
    def __init__(self, arg):
        self.__dict__['arg'] = arg
    def print_arg(self):
            print(self.arg)

b = B (goodbye)

print b.arg

'bye'

+4
source share
3 answers

There are several important consequences:

  • Using self.__dict__to add an attribute is bypassed __setattr__, which can be overloaded with certain behavior that you might want to avoid in some places.

    In [15]: class Test(object):
        ...:     def __init__(self, a, b):
        ...:         self.a = a
        ...:         self.__dict__['b'] = b
        ...:     def __setattr__(self, name, value):
        ...:         print('Setting attribute "{}" to {}'.format(name, value))
        ...:         super(Test, self).__setattr__(name, value)
        ...:               
    
    In [16]: t = Test(1, 2)
    Setting attribute "a" to 1
    

    , b.

  • In [9]: class WithSlots(object):
       ...:     __slots__ = ('a',)
       ...:     def __init__(self, a):
       ...:         self.__dict__['a'] = a
       ...:         
    
    In [10]: instance = WithSlots(1)
    ---------------------------------------------------------------------------
    AttributeError                            Traceback (most recent call last)
    <ipython-input-10-c717fcc835a7> in <module>()
    ----> 1 instance = WithSlots(1)
    
    <ipython-input-9-2d23b670e0fc> in __init__(self, a)
          2     __slots__ = ('a',)
          3     def __init__(self, a):
    ----> 4         self.__dict__['a'] = a
          5 
    
    AttributeError: 'WithSlots' object has no attribute '__dict__'
    
    In [11]: class WithSlots(object):
        ...:     __slots__ = ('a',)
        ...:     def __init__(self, a):
        ...:         self.a = a
        ...:         
        ...:         
    
    In [12]: instance = WithSlots(1) # -> works fine
    
  • .

+5

, , Python . . :

class Exposed:
    def __init__(self, x):
        self._x = x
    @property
    def x(self):
        rerurn self._x

class Hidden:
    def __init__(self, x):
        self.__dict__['x'] = x
    @property
    def x(self):
        return self.__dict__['x']

x. _x, , - . Python, .

+2

request, __dict__, , , .

+1

Source: https://habr.com/ru/post/1691514/


All Articles