Since I'm almost a beginner in python, I'll first look at the class (something like a habit) with simple code.
class sampleCls():
pass
Define an empty class. If you try to output the members of the class in this state,
from pprint import pprint
class sampleCls():
pass
pprint (inspect.getmembers(sampleCls))
When executed,
[('__doc__', None), ('__module__', '__main__')]
Like this.
Add one line (instead of pass).
class sampleCls():
abc = 111
pprint (inspect.getmembers(sampleCls))
When executed,
[('__doc__', None), ('__module__', '__main__'), ('abc', 111)]
Like this.
After passing the class definition, a class object is created. Class objects can be modified. Try modifying the class object without instantiating it yet.
class sampleCls():
abc = 111
#sampleCls.def = 222
sampleCls.efg = 222
pprint (inspect.getmembers(sampleCls))
[('__doc__', None), ('__module__', '__main__'), ('abc', 111), ('efg', 222)]
You can change it like this. (In sampleCls.def, def is a reserved word and an error occurs (; ´∀ `))
If you create an instance of this class in this state,
class sampleCls():
abc = 111
sampleCls.efg = 222
i = sampleCls()
pprint (inspect.getmembers(sampleCls))
print "------------------------------"
pprint (inspect.getmembers(i))
[('__doc__', None), ('__module__', '__main__'), ('abc', 111), ('efg', 222)]
------------------------------
[('__doc__', None), ('__module__', '__main__'), ('abc', 111), ('efg', 222)]
With that feeling, the efg added later is also included in the instance. By the way, you can also delete variables from the class object.
class sampleCls():
abc = 111
sampleCls.efg = 222
pprint (inspect.getmembers(sampleCls))
print "------------------------------"
del sampleCls.abc
pprint (inspect.getmembers(sampleCls))
When executed,
[('__doc__', None), ('__module__', '__main__'), ('abc', 111), ('efg', 222)]
------------------------------
[('__doc__', None), ('__module__', '__main__'), ('efg', 222)]
It's gone. This area is similar to JavaScript.
The site below says that python doesn't have a constructor.
Also, such a thing was written in the book. [* 1](# 1) </ sub> As for the definition of the constructor, it seems that memory allocation is also done by the constructor.
From the standpoint of programming, memory allocation is built into the language, so instances can be initialized, so I thought it would be okay to think of init as a general constructor. Regarding \ __ new__, it seems a little different, so I'll write a little more next.
First, let's write a simple code.
class sampleCls(object):
abc = 111
print "chkpnt10"
def __new__(cls):
cls.efg = 777
print "chkpnt20"
return super(sampleCls, cls).__new__(cls)
def __init__(self):
self.hij = 999
print "chkpnt30"
pprint(dir(sampleCls))
When you do this,
chkpnt10
['__class__',
'__delattr__',
'__dict__',
'__doc__',
'__format__',
'__getattribute__',
'__hash__',
'__init__',
'__module__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'abc']
chkpnt10 is output, but chkpnt20 and chkpnt30 are not displayed. Neither efg nor hij is included in the class object dump. What happens when you create an instance?
class sampleCls(object):
abc = 111
print "chkpnt10"
def __new__(cls):
cls.efg = 777
print "chkpnt20"
return super(sampleCls, cls).__new__(cls)
def __init__(self):
self.hij = 999
print "chkpnt30"
i = sampleCls()
pprint (inspect.getmembers(sampleCls))
pprint (inspect.getmembers(i))
chkpnt10
chkpnt20
chkpnt30
['__class__',
'__delattr__',
'__dict__',
'__doc__',
'__format__',
'__getattribute__',
'__hash__',
'__init__',
'__module__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'abc',
'efg']
['__class__',
'__delattr__',
'__dict__',
'__doc__',
'__format__',
'__getattribute__',
'__hash__',
'__init__',
'__module__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'abc',
'efg',
'hij']
The output is in the order of chkpnt10, chkpnt20, chkpnt30 (the code is running).
The class object contains abc and efg, but not hij. The instance object contains all abc, evg, and hij.
The first argument of \ __ new__ is a class object, and in the above code, efg is set, so efg is added to the class object as a result.
With super (sampleCls, cls) .__ new __ (cls)
, an instance object is created from the class object and returned as a return value.
The return value of \ __ new__ should be an instance object of that class. If the return value is other than that, the instance object will not be created by the class object.
init is called with the instance object created by \ __ new__ as the first argument.
So \ new is for creating an instance object from a class object.
As in the code above, overriding \ __ new__ allows you to change the class object from which the instance object is created, and this change will be reflected in the generated instance object as well.
From the above, I thought that \ __ new__ was not a constructor.
By the way, in the class, ・ Type (new style class) and ・ Class object (old style class) The above sample is a new style class. It seems.
Since I am using python which is installed by default when DataNitro is installed, the above is the one executed in 2.7. In 2.7, in order to call (overridden?) New, you need to inherit object or something. [* 2](# 2) </ sub> [* 3](# 3) </ sub> (Since 3.0 or later, object is inherited by default, so it is no longer necessary to specify inheriting the class.)
I've been researching python for the past few days, and there is a mechanism that allows me to control it fairly finely with a program, so even if I focus on the class, I still feel that something is hazy. You can check one after another ... But I don't hate it. If you do it, you may be addicted to it in a good way.
As an aside, since 3.0, there have been changes that affect the implementation level, such as changing from sentences to expressions and having to put parentheses. It seems that the interface of the library has also changed.
I wonder if I will continue studying python for a while.
* 1. Perhaps some books have init as a constructor. Rather more? * 2. I'm trying to find out the causal relationship between inheriting an object and calling \ __ new__, and I wonder if the attribute value controls the call to \ __ new__. I looked it up, but I couldn't find it. Even if * 3. type is inherited, \ __ new__ is called. However, in this case, the meaning may be slightly different due to the relationship with the metaclass. Future research issues on type.
Recommended Posts