Rumah >pembangunan bahagian belakang >Tutorial Python >Bagaimana untuk mentakrifkan kaedah lebihan kaedah pembina dan kaedah generik dalam kelas Python
Kaedah yang terdiri daripada berbilang kaedah yang melaksanakan operasi yang sama untuk jenis yang berbeza.
Kini terdapat keperluan yang memerlukan anda membuat kelas tarikh tersuai (CustomDate
) dengan cara berikut:
Cap masa
Tahun, bulan, hari (tuple mengandungi tiga integer)
rentetan format ISO
Datetime
Kelas
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
Nota: Kami tidak akan membincangkan sama ada cop tarikh/masa yang masuk adalah sah atau tidak , hanya membuat pertimbangan kasar pada jenis.
Kami boleh membahagikan kaedah pembinaan yang berbeza kepada berbilang kaedah dan menggunakan functools
penghias dalam singledispatchmethod
untuk memutuskan kaedah yang hendak dipanggil berdasarkan jenis parameter yang dihantar.
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
Dengan cara ini, kita boleh mengasingkan pemulaan setiap jenis parameter kepada kaedah yang berasingan.
Pelaksanaan kaedah yang manakah harus digunakan semasa panggilan ditentukan oleh algoritma penghantaran. Jika algoritma memutuskan pelaksanaan kaedah untuk digunakan hanya berdasarkan jenis parameter tunggal, ia dipanggil penghantaran tunggal.
singledispatchmethod
Ia adalah satu penghantaran. Iaitu, hanya parameter pertama akan dipertimbangkan. Ini adalah jauh dari cukup dalam perniagaan sebenar.
Walau bagaimanapun, seperti di atas, kita masih perlu menggunakan if
/else
untuk menentukan jenis elemen dalam tuple. Iaitu, kita tidak boleh menggunakan typing.Tuple[int, int, int]
.
Sebagai kompromi, mungkin kita boleh mentakrifkan kelas ThreeIntTuple
untuk melayakkannya dan mengasingkan pertimbangan ini daripada kelas CustomDate
.
Ini hanya idea untuk rujukan anda, saya tidak akan melaksanakannya (kerana kita ada cara yang lebih baik xD).
Pustaka ini bukan salah satu perpustakaan standard dan perlu dipasang melalui pip:
pip install multimethod
multimethod
Algoritma Berbilang penghantaran yang digunakan boleh memenuhi senario yang lebih kompleks dengan lebih baik. Selain itu, perpustakaan mempunyai sokongan yang baik untuk jenis dalam typing
.
Berbalik kepada soalan di atas, kita boleh memperbaikinya seperti ini:
Gunakan kaedah multimethod
dan bukannya singledispatchmethod
;
Gunakan Tuple[int, int, int]
bukannya tuple
, tidak perlu lagi menyemak panjang dan jenis elemen tuple secara manual; >Kaedah praktikal muktamad (pembebanan kaedah sebenar)
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
Output
. Dalam Python, jika kaedah dengan nama yang sama ditakrifkan, kaedah terakhir akan menimpa kaedah sebelumnya.2
Tetapi anda mungkin tidak tahu bahawa kami boleh mengubah tingkah laku ini melalui metaclass:
class A: def a(self): print(1) def a(self): print(2) A().a()
Dalam baris 7 dan 8, kami menamakan semula kaedah
pendua untuk, dan berjaya memanggilnya pada baris 22. Penyelenggara
a
telah menggunakan ini dengan baik dan telah berurusan dengan nama pendua untuk mencapai "kesan khas". b
multimethod
Tetapkan
sebagai kelas meta bagi kelas menamakan semua kaedah multimethod.multidata
. CustomDate
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
Atas ialah kandungan terperinci Bagaimana untuk mentakrifkan kaedah lebihan kaedah pembina dan kaedah generik dalam kelas Python. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!