A brief discussion of the methods of python 2EN__ and 3en__

  • 2020-06-12 09:47:53
  • OfStack

preface

___, 5EN__ and 6en__ 3EN

In the object-oriented programming model of programming languages, objects have a similar fate: creation, initialization, use, garbage collection, and different phases are performed by different methods (roles).

Per class, the most common method is the method of 11EN__, and less 12en__ and 13en__. This article tries to help you explain the proper use and scenario of each of these methods.

We won't talk much about Python new class and old class in this article, because the old class is a concept in Python2 and almost no one USES the old class anymore. The new class must inherit from object explicitly, while in Python3, only the new class inherits from object by default and does not need to be specified. The code in this article is based on Python3.

__init__ method

The method of ___ is responsible for initializing the object. The object already exists before the system executes it. Let's look at an example:


# class A(object): python2  Must be explicitly inherited object
class A:
 def __init__(self):
  print("__init__ ")
  super(A, self).__init__()

 def __new__(cls):
  print("__new__ ")
  return super(A, cls).__new__(cls)

 def __call__(self): #  You can define any parameter 
  print('__call__ ')

A()

The output


__new__
__init__

From the output, the method of ___ is called first, returning an instance object, and then ___ 35EN__. The method of ___ has not been called. Let's leave this to the end. Let's start with the first two methods, rewritten slightly:


def __init__(self):
 print("__init__ ")
 print(self)
 super(A, self).__init__()

def __new__(cls):
 print("__new__ ")
 self = super(A, cls).__new__(cls)
 print(self)
 return self

Output:


__new__ 
<__main__.A object at 0x1007a95f8>
__init__ 
<__main__.A object at 0x1007a95f8>

From the output, the return value of the method with succnew__ is the instance object of the class that is passed to the self argument defined in the method with succinit__, so that the instance object can be initialized correctly.

If the method does not return a value (or return None) per ___, then ___ 50en__ will not be called, which makes sense as it makes no sense to call init because the instance objects have not been created, and also Python stipulates that ___, 53en__ should return only the value of None, otherwise leave it to you to try.

The method with ___ 57EN__ can be used to do some initialization work, such as initializing the state of the instance object:


def __init__(self, a, b):
 self.a = a
 self.b = b
 super(A, self).__init__()

In addition, the arguments defined in the method with each ___ 61en__ other than self will be the same as in the method with ___ 63en__ other than the cls argument.


class B:
 def __init__(self, *args, **kwargs):
  print("init", args, kwargs)

 def __new__(cls, *args, **kwargs):
  print("new", args, kwargs)
  return super().__new__(cls)

B(1, 2, 3)

#  The output 

new (1, 2, 3) {}
init (1, 2, 3) {}

__new__ method

We're not going to override this method unless you know exactly how to do it, and when you're going to care about it, it ACTS as a constructor for creating objects, a factory function, dedicated to producing instance objects. The famous design pattern 1, singleton pattern, can be implemented in this way. You may use it when writing your own frame-level code, but you can also find its application scenarios in the open source code, such as the micro Web framework Bootle.


class BaseController(object):
 _singleton = None
 def __new__(cls, *a, **k):
  if not cls._singleton:
   cls._singleton = object.__new__(cls, *a, **k)
  return cls._singleton

This code from https: / / github com bottlepy/bottle/blob/release - 0.6 / bottle py

This is one way of implementing the singleton pattern with the method of succnew__, returning the instance if it exists or creating an instance if it doesn't already. Of course, there is more than one way to implement the singleton pattern. Python zen says:

There should be one-- and preferably only one --obvious way to do it.

One way, preferably only one way to do one thing

__call__ method

About __call__ method, have to mention a concept, is a callable object (callable), our usual custom function, built-in functions and classes are callable object, but who can put 1 in parentheses () is applied to an object can be called a callable object, for callable object function can be used to judge whether the object callable

If the method of ___ 105EN__ is implemented in the class, then the instance object will also be a callable object. Let's go back to the original example:


a = A()
print(callable(a)) # True

a is an instance object and also a callable object, so I can call it like function 1. Try:


a() # __call__

Not surprisingly, instance objects can also be used as callable objects like function 1. So, where does this feature come into play? This is combined with the class property that classes can record data (properties) and functions can't (closures are also possible in some sense). This property can be used to implement class-based decorators that record state in the class. For example, the following example is used to record the number of times a function is called:


class Counter:
 def __init__(self, func):
  self.func = func
  self.count = 0

 def __call__(self, *args, **kwargs):
  self.count += 1
  return self.func(*args, **kwargs)

@Counter
def foo():
 pass

for i in range(10):
 foo()

print(foo.count) # 10

In Bottle, there are examples of call's methods, and stackoverflow has a few practical examples of call. If you need more abstract, framework code in your project, these advanced features will work.

conclusion


Related articles: