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
'hello'
But what I found in line 133 and 134 of 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
'goodbye'
The self parameter is a reference to the current instance of the class, and is used to access variables that belongs to the class.
Technically both self and this are used for the same thing. They are used to access the variable associated with the current instance. Only difference is, you have to include self explicitly as first parameter to an instance method in Python, whereas this is not the case with Java.
The self in keyword in Python is used to all the instances in a class. By using the self keyword, one can easily access all the instances defined within a class, including its methods and attributes. init. __init__ is one of the reserved methods in Python. In object oriented programming, it is known as a constructor.
self represents the instance of the class. By using the “self” we can access the attributes and methods of the class in python. It binds the attributes with the given arguments. The reason you need to use self. is because Python does not use the @ syntax to refer to instance attributes.
There are several major implications:
Using self.__dict__
to add an attribute circumvents __setattr__
, which might be overloaded with a certain behaviour 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
You can see that nothing was printed for attribute b
.
It is less flexible in some cases
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
You can't do that outside a class definition.
The overall purpose is to circumvent the default manner in which Python sets a variable. A particular use-case for this technique is to hide property values. Compare the following two classes:
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']
Both classes define a read-only property x
. However, the first one ends up with an extra _x
attribute that is directly modifiable by the user, while the second does not. While nothing is truly private in Python, the second class creates a much better approximation of a true read-only value, and it doesn't proliferate unnecessarily visible attributes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With