


So definieren Sie die Überladung mehrerer Konstruktormethoden und generische Methoden in Python-Klassen
Was ist eine „generische Methode“?
Eine Methode, die aus mehreren Methoden besteht, die denselben Vorgang für verschiedene Typen implementieren.
Zum Beispiel
Jetzt gibt es eine Anforderung, die erfordert, dass Sie eine benutzerdefinierte Datumsklasse (CustomDate
) auf folgende Weise erstellen: CustomDate
):
时间戳
年、月、日(包含三个整数的元组)
ISO 格式的字符串
Datetime
类
一般实现
from datetime import date, datetime class CustomDate: def __init__(self, arg): if isinstance(arg, (int, float)): self.__date = date.fromtimestamp(arg) elif isinstance(arg, tuple) and len(arg) == 3 and all(map(lambda x: isinstance(x, int), arg): self.__date = date(*arg) elif isinstance(arg, str): self.__date = date.fromisoformat(arg) elif isinstance(arg, datetime): self.__date = datetime.date() else: raise TypeError("could not create instance from " + type(arg).__name__) @property def date(): return self.__date
注:这里暂不讨论传入的日期/时间戳合不合法,仅仅只对类型做大致判断。
有没有更好的方式?
我们可以将不同的构建方式拆分为多个方法,并利用 functools
中的 singledispatchmethod
装饰器来根据传入的参数类型决定调用哪个方法。
from datetime import date, datetime from functools import singledispatchmethod class CustomDate: @singledispatchmethod def __init__(self, arg): raise TypeError("could not create instance from " + type(arg).__name__) @__init__.register(int) @__init__.register(float) def __from_timestamp(self, arg): self.__date = date.fromtimestamp(arg) @__init__.register(tuple) def __from_tuple(self, arg): if len(arg) == 3 and all(map(lambda x: isinstance(x, int), arg)): self.__date = date(*arg) else: raise ValueError("could not create instance from a malformed tuple") @__init__.register(str) def __from_isoformat(self, arg): self.__date = date.fromisoformat(arg) @__init__.register(datetime) def __from_datetime(self, arg): self.__date = arg.date() @property def date(self): return self.__date
这样一来,我们便能将每种参数类型的初始化独立成一个个的方法了。
缺点
#1 单分派
在调用期间应该使用哪个方法实现由分派算法决定。如果该算法只基于单个参数的类型来决定使用哪个方法实现,则称其为单分派。
singledispatchmethod
就是就是单分派的。也就是说,只有第一个参数会作为考量。这在实际业务中是远远不足的。
#2 不支持 typing
然而,如上,对元组中元素类型判断还是需要我们用 if
/else
实现。也就是说,我们不能使用 typing.Tuple[int, int, int]
。
作为一种折中的方案,或许我们可以定义一个 ThreeIntTuple
类来对其进行限定,将这些判断从 CustomDate
类中隔离开来。
这里仅提供一个思路让大家参考,我就不实现了(因为我们有更好的方式 xD)。
替代方案:multimethod 库
这个库不是标准库之一,需要通过 pip 安装:
pip install multimethod
优势
multimethod
采用的是多分派算法,能更好地满足更复杂的场景。此外,该库对 typing
中的类型也有不错的支持。
更更好的实践方式
回到上面的问题,我们可以这么改进:
使用
multimethod
方法来替代singledispatchmethod
;使用
Tuple[int, int, int]
来替代tuple
,不再需要手动校验元组的长度和元素类型了;
from datetime import date, datetime from typing import Tuple, Union from multimethod import multimethod class CustomDate: @multimethod def __init__(self, arg): raise TypeError("could not create instance from " + type(arg).__name__) @__init__.register def __from_timestamp(self, arg: Union[int, float]): self.__date = date.fromtimestamp(arg) @__init__.register def __from_tuple(self, arg: Tuple[int, int, int]): self.__date = date(*arg) @__init__.register def __from_isoformat(self, arg: str): self.__date = date.fromisoformat(arg) @__init__.register def __from_datetime(self, arg: datetime): self.__date = arg.date() @property def date(self): return self.__date
究极好的实践方式(真正的方法重载)
在此之前,先问大家一个简单的问题(这跟我们之后的内容有很大的联系):
class A: def a(self): print(1) def a(self): print(2) A().a()
以上这段代码会输出什么?还是会抛出错误?
输出 2
。
在 Python 中,如果定义了重名的方法,最后一个方法是会覆盖掉之前的方法的。
但你或许不知,我们可以通过元类(metaclass)来改变这一行为:
class MetaA(type): class __prepare__(dict): def __init__(*args): pass def __setitem__(self, key, value): if self.get('a'): # Line 7 super().__setitem__('b', value) # Line 8 else: super().__setitem__(key, value) class A(metaclass=MetaA): def a(self): print(1) def a(self): print(2) A().a() # => 1 A().b() # => 2 # Line 22
在第 7 和第 8 行,我们将重名的 a
方法改名为 b
,并在第 22 行成功地调用它了。
multimethod
的维护者们很好地运用了这一点,对重名的方法进行了处理,以达到一种“特殊的效果”。
回到正题,我们可以做出如下改进:
将
multimethod.multidata
设置为CustomDate
类的元类;将所有方法命名为
__init__
- < li>Zeitstempel
Jahr, Monat, Tag (Tupel mit drei ganzen Zahlen)
🎜Datetime</code > Allgemeine Implementierung der Klasse 🎜 🎜🎜🎜🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>from datetime import date, datetime
from typing import Tuple, Union
from multimethod import multimeta
class CustomDate(metaclass=multimeta):
def __init__(self, arg: Union[int, float]):
self.__date = date.fromtimestamp(arg)
def __init__(self, arg: Tuple[int, int, int]):
self.__date = date(*arg)
def __init__(self, arg: str):
self.__date = date.fromisoformat(arg)
def __init__(self, arg: datetime):
self.__date = arg.date()
def __init__(self, arg):
raise TypeError("could not create instance from " + type(arg).__name__)
@property
def date(self):
return self.__date</pre><div class="contentsignin">Nach dem Login kopieren</div></div>🎜 Hinweis: Wir werden nicht diskutieren, ob der eingehende Datums-/Zeitstempel legal ist oder nicht, sondern nur eine grobe Beurteilung des Typs vornehmen. 🎜🎜Gibt es einen besseren Weg? 🎜🎜Wir können verschiedene Erstellungsmethoden in mehrere Methoden aufteilen und den <code>singledispatchmethod
-Dekorator in functools
verwenden, um basierend auf dem Typ der übergebenen Parameter zu entscheiden, welche Methode aufgerufen werden soll. 🎜rrreee🎜Auf diese Weise können wir die Initialisierung jedes Parametertyps in separate Methoden aufteilen. 🎜🎜Nachteile🎜#1 Einzelversand
🎜Welche Methodenimplementierung während des Aufrufs verwendet werden soll, wird durch den Versandalgorithmus bestimmt. Wenn der Algorithmus nur anhand des Typs eines einzelnen Parameters entscheidet, welche Methodenimplementierung verwendet werden soll, spricht man von Single Dispatch. 🎜🎜singledispatchmethod
ist Einzelversand. Das heißt, es wird nur der erste Parameter berücksichtigt. Das reicht in der Praxis bei weitem nicht aus. 🎜#2 unterstützt keine Eingabe
🎜Wie oben erwähnt müssen wir jedoch immer nochif
/else
verwenden, um den Typ der Elemente in zu bestimmen ein Tupel. Das heißt, wir können typing.Tuple[int, int, int]
nicht verwenden. 🎜🎜Als Kompromiss können wir vielleicht eine ThreeIntTuple
-Klasse definieren, um sie einzuschränken und diese Urteile von der CustomDate
-Klasse zu isolieren. 🎜🎜Hier ist nur eine Idee als Referenz, ich werde sie nicht umsetzen (weil wir einen besseren Weg haben xD). 🎜🎜Alternative: Multimethod-Bibliothek🎜🎜Diese Bibliothek gehört nicht zu den Standardbibliotheken und muss über pip installiert werden: 🎜rrreee🎜Vorteile🎜🎜multimethod
verwendet einen Multi-Dispatch-Algorithmus, der besser erfüllen kann komplexere Anforderungsszene. Darüber hinaus bietet die Bibliothek eine gute Unterstützung für Typen in typing
. 🎜🎜Bessere Vorgehensweise🎜🎜Zurück zur obigen Frage, wir können sie folgendermaßen verbessern:🎜- 🎜Verwenden Sie die
multimethod
-Methode anstelle vonsingledispatchmethod
; 🎜🎜 - 🎜Verwenden Sie
Tuple[int, int, int]
, umtuple
zu ersetzen. Die Länge und die Länge von Tupeln müssen nicht mehr manuell überprüft werden Elementtyp von): 🎜rrreee🎜Was wird der obige Code ausgeben? Oder wird es einen Fehler auslösen? 🎜🎜Ausgabe2
. 🎜🎜Wenn in Python Methoden mit demselben Namen definiert sind, überschreibt die letzte Methode die vorherige Methode. 🎜🎜Aber Sie wissen vielleicht nicht, dass wir dieses Verhalten durch die Metaklasse ändern können: 🎜rrreee🎜In den Zeilen 7 und 8 benennen wir die gleichnamige Methodea
inb
um und ruft es erfolgreich in Zeile 22 auf. 🎜🎜Die Betreuer vonmultimethod
haben dies sinnvoll genutzt und Methoden mit doppelten Namen verarbeitet, um einen „Spezialeffekt“ zu erzielen. 🎜🎜Zurück zum Thema, wir können folgende Verbesserungen vornehmen: 🎜- 🎜Setzen Sie
multimethod.multidata
aufCustomDate
Metaklasse der Klasse; 🎜🎜 - 🎜Name aller Methoden
__init__
. 🎜🎜🎜rrreee🎜In Bezug auf die Wirkung ist dies genau das Gleiche wie das Überladen statischer Sprachmethoden! 🎜
- 🎜Setzen Sie
Das obige ist der detaillierte Inhalt vonSo definieren Sie die Überladung mehrerer Konstruktormethoden und generische Methoden in Python-Klassen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

Video Face Swap
Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen











PHP ist hauptsächlich prozedurale Programmierung, unterstützt aber auch die objektorientierte Programmierung (OOP). Python unterstützt eine Vielzahl von Paradigmen, einschließlich OOP, funktionaler und prozeduraler Programmierung. PHP ist für die Webentwicklung geeignet, und Python eignet sich für eine Vielzahl von Anwendungen wie Datenanalyse und maschinelles Lernen.

PHP eignet sich für Webentwicklung und schnelles Prototyping, und Python eignet sich für Datenwissenschaft und maschinelles Lernen. 1.PHP wird für die dynamische Webentwicklung verwendet, mit einfacher Syntax und für schnelle Entwicklung geeignet. 2. Python hat eine kurze Syntax, ist für mehrere Felder geeignet und ein starkes Bibliotheksökosystem.

Um den Python-Code im Sublime-Text auszuführen, müssen Sie zuerst das Python-Plug-In installieren, dann eine .py-Datei erstellen und den Code schreiben, und drücken Sie schließlich Strg B, um den Code auszuführen, und die Ausgabe wird in der Konsole angezeigt.

PHP entstand 1994 und wurde von Rasmuslerdorf entwickelt. Es wurde ursprünglich verwendet, um Website-Besucher zu verfolgen und sich nach und nach zu einer serverseitigen Skriptsprache entwickelt und in der Webentwicklung häufig verwendet. Python wurde Ende der 1980er Jahre von Guidovan Rossum entwickelt und erstmals 1991 veröffentlicht. Es betont die Lesbarkeit und Einfachheit der Code und ist für wissenschaftliche Computer, Datenanalysen und andere Bereiche geeignet.

Python eignet sich besser für Anfänger mit einer reibungslosen Lernkurve und einer kurzen Syntax. JavaScript ist für die Front-End-Entwicklung mit einer steilen Lernkurve und einer flexiblen Syntax geeignet. 1. Python-Syntax ist intuitiv und für die Entwicklung von Datenwissenschaften und Back-End-Entwicklung geeignet. 2. JavaScript ist flexibel und in Front-End- und serverseitiger Programmierung weit verbreitet.

Golang ist in Bezug auf Leistung und Skalierbarkeit besser als Python. 1) Golangs Kompilierungseigenschaften und effizientes Parallelitätsmodell machen es in hohen Parallelitätsszenarien gut ab. 2) Python wird als interpretierte Sprache langsam ausgeführt, kann aber die Leistung durch Tools wie Cython optimieren.

Das Schreiben von Code in Visual Studio Code (VSCODE) ist einfach und einfach zu bedienen. Installieren Sie einfach VSCODE, erstellen Sie ein Projekt, wählen Sie eine Sprache aus, erstellen Sie eine Datei, schreiben Sie Code, speichern und führen Sie es aus. Die Vorteile von VSCODE umfassen plattformübergreifende, freie und open Source, leistungsstarke Funktionen, reichhaltige Erweiterungen sowie leichte und schnelle.

Das Ausführen von Python-Code in Notepad erfordert, dass das ausführbare Python-ausführbare Datum und das NPPEXEC-Plug-In installiert werden. Konfigurieren Sie nach dem Installieren von Python und dem Hinzufügen des Pfades den Befehl "Python" und den Parameter "{current_directory} {file_name}" im NPPExec-Plug-In, um Python-Code über den Shortcut-Taste "F6" in Notoza auszuführen.
