This article brings you an introduction to the new class method, init instance method and singleton mode in Python (with examples). It has certain reference value. Friends in need can refer to it. I hope it will help You helped.
"Are all classes in Python singleton mode?" One day, a colleague asked me such a question. This is a strange question, maybe you think so too. Without explanation here, let’s take a look at the __new__ and __init__ methods first. The
new and init
__new__ methods belong to the new-style class, that is, they belong to the object class. It is a static method, but its first parameter must be a class (cls), which is a bit like a classmethod. In fact, it can also be regarded as a class method. When this special method is called, a new instance of the class (cls) will be created and returned. After the instance is created, the interpreter will pass the instance and other parameters to the instance's initialization function __init__ to initialize the instance.
So, the __new__ method is a class method, used to create an instance, and the __init__ method is an instance method, used to initialize an instance.
__new__ method is called when instantiating a class. Overriding this method should look like the following:
class A(object): def __new__(cls, *args, **kwargs) return super(A, cls).__new__(cls, *args, **kwargs)
If the __new__ method does not return an instance of cls, then the new instance's __init__ The method will not be called. It should be noted that after Python 3.3, the new method no longer receives additional parameters, otherwise there will be an exception TypeError: object() takes no parameters.
__init__ method is called after the instance is created. This method only performs some initialization operations on the instance created by the __new__ method. Note that if the new method returns an instance, the init method will always be called (this should be paid special attention to when using the new method to implement a singleton)
You can do some verification:
class Foo(object): def __new__(cls, m, n): print "__new__ is called" return super(Foo, cls).__new__(cls, m, n) def __init__(self, m, n): print "__init__ is called" self.m = m self.n = n def __repr__(self): return "Foo(m={self.m}, n={self.n})".format(self=self) def __str__(self): return self.__repr__() if __name__ == "__main__": f = Foo(1, 2) print f
Output result:
__new__ is called __init__ is called Foo(m=1, n=2)
So we can draw the conclusion:
1. __new__ is a class-level method. Even if it is not decorated by classmethod, it determines the process of generating instances.
2. __init__ is an instance-level method that determines the instance initialization process, such as adding attributes, judging and converting initialization parameters, etc.
It should be noted that the parameters of the rewritten __new__ method and the __init__ method should be consistent, otherwise TypeError will occur. If you call object.__new__() directly, incoming parameters are no longer supported in Python 3.3 and later versions. This reference is from: https://stackoverflow.com/questions/34777773/typeerror...
## The #__init__ method is generally involved when defining a class and is also commonly used. The __new__ method is rarely used, so what is its use? New method function #__new__ The more commonly used functions of the method are probably: 1. When inheriting built-in immutable types (such as int, str, tuple), provide self- Define the instantiation process. Because if you do all the write operations in the __init__ method, it may be invalid. For example:class CustomInt(int): def __init__(self, v): super(CustomInt, self).__init__(self, abs(v)) print CustomInt(-1) # 输出:-1
__new__method:
class CustomInt(int): def __new__(cls, v): return super(CustomInt, cls).__new__(cls, abs(v)) print CustomInt(-1) # 输出:1
__new__method, it is very convenient to rewrite this method to use the singleton mode:
class Singleton(object): def __new__(cls): if not hasattr(cls, "_instance"): cls._instance = super(Singleton, cls).__new__(cls) return cls._instance assert Singleton() is Singleton() # 断言成功
print Singleton(), Singleton()
<__main__.Singleton object at 0x10d698650> <__main__.Singleton object at 0x10d698650>
__new__method, there are some other ways, such as decorators, metaclasses, etc. Different ways of implementation have different effects. Metaclasses are more advanced features in Python and will not be discussed in this article. Let’s take a look at how to use decorators to implement singletons.
from functools import wraps def singleton(cls): instances = {} @wraps(cls) def getinstance(*args, **kwargs): if cls not in instances: instances[cls] = cls(*args, **kwargs) return instances[cls] return getinstance @singleton class MyClass(object): def __init__(self): pass
When using a decorator to implement a singleton, the class has become a Functions, not classes anymore.When initializing the instance using MyClass in the above example, what is actually called is the getinstance function returned after being decorated.
The difference between using__new__to implement a singleton and using decoration to implement a singleton is that the former will call the
__init__method, which means that every time it is initialized With different parameters, although the returned instance is the same, the properties of the instance have been reset; and the latter always returns the example created and the properties set during the first initialization, even if different parameters are passed in later.
接着,我们再来看一个“奇怪”的现象:
>>> class A(object): ... pass ... >>> print A(), A() <__main__.A object at 0x104765450> <__main__.A object at 0x104765450> >>> print A(), A() <__main__.A object at 0x104765450> <__main__.A object at 0x104765450> >>> print A(), A() <__main__.A object at 0x104765450> <__main__.A object at 0x104765450>
是不是感觉有些难以置信,print 语句后两次创建的对象应该是不一样的,而他们却莫名奇妙的一样。这就是我讨论本文内容的原因。
一次同事问我,Python 中的类都是单例模式?我当时一脸懵逼,听了他的描述,我自己也试了下,果然存在如上所示的“奇怪”现象。于是我就去了解了 Python 单例模式的实现,在了解到__new__
的实现方式时,就想对__new__
和__init__
有一个更加深入的了解。于是就有了本文所讨论的内容。
然后,我想着用 is 来判断下他们是否真的是同一个实例:
>>> A() is A() False
我没有对 CPython 的源码进行过全面的阅读,所以对其很多内部的实现机制不是太了解。我猜 Python 解释器在内部可能做了优化,像print A(), A()
这样的语句,解释器认为没有必要创建不同的对象,直接返回同一个实例的引用得了。是不是觉得解释器有些自作聪明!而当A() is A()
这样的表达式出现时,解释器想,我不能再自作聪明,那样可能会误导别人。可是,在 print 语句那样的用法时,就已经误导我了,我都差点开始怀疑人生了!
从语法来看,大家应该知道,我在测试时使用的 Python 2。我后来也试了下 Python 3:
>>> class A(): ... pass ... >>> print(A(), A()) <__console__.A object at 0x10fe7afd0> <__console__.A object at 0x10fed79e8> >>> print(A(), A()) <__console__.A object at 0x10fec0cc0> <__console__.A object at 0x10feda160> >>> print(A(), A()) <__console__.A object at 0x10fe7afd0> <__console__.A object at 0x10fed7940> >>> A() is A() False
我想,这样的结果才是不会让人困惑的。可能是 Python 社区意识到了这个问题并在 Python3 中进行了修正。这样的修正是好的,否则对于像我同事那样初次使用 Python 的人来说是很困惑的。
个人认为,Python3 对过去的一些“错误”的修正是好的。例如将 print 改为函数,提供了丰富的参数来控制输出的样式;对编码的调整等等。
The above is the detailed content of Introduction to new class method, init instance method and singleton mode in Python (with examples). For more information, please follow other related articles on the PHP Chinese website!