Heim  >  Artikel  >  Backend-Entwicklung  >  Eine kurze Einführung in die drei Methoden __init__, __new__ und __call__ in Python

Eine kurze Einführung in die drei Methoden __init__, __new__ und __call__ in Python

黄舟
黄舟Original
2017-07-18 11:38:311326Durchsuche

Dieser Artikel stellt Ihnen hauptsächlich die relevanten Informationen zu den Methoden __init__, __new__ und __call__ in Python vor. Der Artikel stellt sie ausführlich anhand von Beispielcode vor, der für jeden, der ihn benötigt, einen gewissen Referenz- und Lernwert hat Referenzstudie, folgen wir dem Herausgeber und werfen einen Blick darauf.

Vorwort

Dieser Artikel führt Sie hauptsächlich in die relevanten Inhalte zu den Methoden __init__, __new__ und __call__ in Python ein und teilen Sie sie als Referenz Lassen Sie uns als Referenz lernen. Im Folgenden gibt es nicht viel zu sagen. Werfen wir einen Blick auf die detaillierte Einführung:

Alles hat einen Prozess von der Erstellung über die Verwendung bis zum Tod. Im objektorientierten Programmiermodell der Programmiersprache Objekte haben auch ein ähnliches Schicksal: Erstellung, Initialisierung, Verwendung und Speicherbereinigung. Verschiedene Phasen werden durch unterschiedliche Methoden (Rollen) ausgeführt.

Beim Definieren einer Klasse ist die Methode __init__ die am häufigsten verwendete Methode, während __new__ und __call__ seltener verwendet werden. Dieser Artikel soll Ihnen helfen, die korrekte Verwendung und die Anwendungsszenarien dieser drei Methoden zu erklären separat.

Ich werde in diesem Artikel nicht zu viel über Pythons Klassen im neuen und alten Stil diskutieren, da Klassen im alten Stil ein Konzept in Python2 sind und fast niemand mehr Klassen im alten Stil verwenden wird . Klassen neuen Stils müssen Objekte explizit erben. In Python3 gibt es nur Klassen neuen Stils, die standardmäßig Objekte erben und nicht explizit angegeben werden müssen.

__init__-Methode

Die __init__-Methode ist für die Initialisierung des Objekts verantwortlich, bevor das System diese Methode ausführt , andernfalls Was soll initialisiert werden? Schauen wir uns zunächst das Beispiel an:


# class A(object): python2 必须显示地继承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): # 可以定义任意参数
  print('__call__ ')

A()

Ausgabe


__new__
__init__

Aus dem Ausgabeergebnis, __new__ Methode Es wird zuerst aufgerufen, gibt ein Instanzobjekt zurück und dann wird __init__ aufgerufen. Die __call__-Methode wurde nicht aufgerufen. Lassen Sie uns zunächst über die ersten beiden Methoden sprechen, leicht umgeschrieben als:


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

Ausgabe:


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

Der Ausgabe nach zu urteilen, ist der Rückgabewert der Methode __new__ das Instanzobjekt der Klasse. Dieses Instanzobjekt wird an den in __init__ definierten Parameter self übergeben. Methode, damit die Instanz Das Objekt kann korrekt initialisiert werden.

Wenn die Methode __new__ keinen Wert zurückgibt (oder None zurückgibt), wird __init__ nicht aufgerufen. Dies ist nicht sinnvoll, da das Instanzobjekt nicht erstellt wurde und der Aufruf von init außerdem keine Bedeutung hat Python legt außerdem fest, dass __init__ nur einen None-Wert zurückgeben kann, andernfalls wird ein Fehler gemeldet. Dies bleibt jedem selbst überlassen.

__init__-Methode kann verwendet werden, um einige Initialisierungsarbeiten durchzuführen, z. B. die Initialisierung des Status des Instanzobjekts:


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

Darüber hinaus in der __init__-Methode Die mit Ausnahme von self definierten Parameter müssen mit den Parametern in der __new__-Methode mit Ausnahme des cls-Parameters konsistent oder gleichwertig sein.


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)

# 输出

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

__new__ Methode

Im Allgemeinen werden wir diese Methode nicht außer Kraft setzen, es sei denn, Sie wissen genau, wie Um dies zu tun, und wann werden Sie sich darum kümmern? Es wird als Konstruktor zum Erstellen von Objekten verwendet. Es handelt sich um eine Fabrikfunktion, die der Erstellung von Instanzobjekten gewidmet ist. Mit dieser Methode kann eines der bekanntesten Entwurfsmuster, das Singleton-Muster, implementiert werden. Sie können es verwenden, wenn Sie selbst Code auf Framework-Ebene schreiben. Wir können seine Anwendungsszenarien auch aus Open-Source-Code finden, beispielsweise dem 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

Dieser Code stammt von https://github.com/bottlepy/bottle/blob/release-0.6/bottle.py

Dies Die Methode __new__ ist eine Möglichkeit, den Singleton-Modus zu implementieren. Wenn das Instanzobjekt vorhanden ist, geben Sie es einfach zurück. Wenn es nicht vorhanden ist, erstellen Sie zuerst eine Instanz und kehren Sie dann zurück. Natürlich gibt es mehr als eine Möglichkeit, das Singleton-Muster zu implementieren:

Es sollte eine – und vorzugsweise nur eine – offensichtliche Möglichkeit geben, dies zu tun.

Verwenden Sie eine Methode, es ist am besten, nur eine Möglichkeit zu haben, eine Sache zu tun

__call__-Methode

Über die __call__-Methode , nein Lassen Sie uns zunächst kein Konzept erwähnen, nämlich aufrufbare Objekte. Unsere üblichen benutzerdefinierten Funktionen, integrierten Funktionen und Klassen sind alle aufrufbare Objekte, aber alles, was ein Klammerpaar () auf ein Objekt anwenden kann, kann aufgerufen werden ein aufrufbares Objekt. Sie können die Funktion callable

verwenden, um festzustellen, ob das Objekt ein aufrufbares Objekt ist. Wenn die __call__-Methode in der Klasse implementiert ist, wird das Instanzobjekt auch zu einem aufrufbaren Objekt Zum Anfang. Das Beispiel:


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

a ist ein Instanzobjekt und auch ein aufrufbares Objekt, dann kann ich es wie eine Funktion aufrufen. Versuchen Sie:


a() # __call__

很神奇不是,实例对象也可以像函数一样作为可调用对象来用,那么,这个特点在什么场景用得上呢?这个要结合类的特性来说,类可以记录数据(属性),而函数不行(闭包某种意义上也可行),利用这种特性可以实现基于类的装饰器,在类里面记录状态,比如,下面这个例子用于记录函数被调用的次数:


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

在 Bottle 中也有 call 方法 的使用案例,另外,stackoverflow 也有一些关于 call 的实践例子,推荐看看,如果你的项目中,需要更加抽象化、框架代码,那么这些高级特性往往能发挥出它作用。

总结

Das obige ist der detaillierte Inhalt vonEine kurze Einführung in die drei Methoden __init__, __new__ und __call__ in Python. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn