Jadual Kandungan
Saiz iterator" >Saiz iterator
" >Metaprogramming
自省(introspection)" >自省(introspection)
魔法属性" >魔法属性
创建自己魔法方法?" >创建自己魔法方法?

Kaedah ajaib dalam Python

Apr 13, 2023 am 10:25 AM
python pengendali

Kaedah ajaib dalam Python ialah kaedah khas yang membolehkan anda menambah "ajaib" pada kelas Ia sering dinamakan dengan dua garis bawah.

Kaedah ajaib dalam Python

Kaedah ajaib Python, juga dikenali sebagai kaedah dunder (garis bawah berganda). Selalunya, kami menggunakannya untuk perkara mudah seperti pembina (init), perwakilan rentetan (str, repr) atau pengendali aritmetik (tambah/mul). Sebenarnya, terdapat banyak kaedah yang mungkin anda tidak pernah dengar tetapi sangat berguna Dalam artikel ini, kami akan menyelesaikan kaedah ajaib ini!

Saiz iterator

Kita semua tahu kaedah __len__, yang boleh digunakan untuk melaksanakan fungsi len() pada kelas kontena. Tetapi bagaimana jika anda ingin mendapatkan panjang objek kelas yang melaksanakan iterator

it = iter(range(100))
 print(it.__length_hint__())
 # 100
 next(it)
 print(it.__length_hint__())
 # 99
 
 a = [1, 2, 3, 4, 5]
 it = iter(a)
 print(it.__length_hint__())
 # 5
 next(it)
 print(it.__length_hint__())
 # 4
 a.append(6)
 print(it.__length_hint__())
 # 5
Salin selepas log masuk
Apa yang anda perlu lakukan ialah melaksanakan kaedah __length_hint__, iaitu kaedah terbina dalam pada iterator (tidak dihasilkan? penukar), seperti yang anda lihat di atas, dan juga menyokong perubahan panjang dinamik. Walau bagaimanapun, sesuai dengan namanya, ini hanyalah pembayang dan tidak dijamin tepat sepenuhnya: untuk lelang senarai, anda boleh mendapatkan hasil yang tepat, tetapi untuk lelaran lain ia tidak pasti. Tetapi walaupun ia tidak tepat, ia boleh membantu kami mendapatkan maklumat yang kami perlukan, seperti yang dijelaskan dalam PEP 424.

length_hint mesti mengembalikan integer (selain itu TypeError dinaikkan) atau NotImplemented, dan tidak diperlukan untuk tepat. Ia mungkin mengembalikan nilai yang sama ada lebih besar atau lebih kecil daripada saiz sebenar bekas. Nilai pulangan NotImplemented menunjukkan bahawa tiada anggaran panjang terhingga Ia mungkin tidak mengembalikan nilai negatif (selain itu ValueError dinaikkan).

Metaprogramming

Kebanyakan kaedah ajaib yang jarang dilihat adalah berkaitan dengan metaprogramming, dan sementara metaprogramming mungkin bukan sesuatu yang kita perlu gunakan setiap hari, terdapat beberapa helah berguna yang boleh Menggunakannya.

Salah satu helah tersebut ialah menggunakan __init_subclass__ sebagai jalan pintas untuk melanjutkan fungsi kelas asas tanpa perlu berurusan dengan metaclass:

 class Pet:
def __init_subclass__(cls, /, default_breed, **kwargs):
super().__init_subclass__(**kwargs)
cls.default_breed = default_breed
 
 class Dog(Pet, default_name="German Shepherd"):
pass
Salin selepas log masuk
Dalam kod di atas kami menambah hujah kata kunci pada kelas asas, parameter ini boleh ditetapkan apabila menentukan subkelas. Kes penggunaan sebenar mungkin menggunakan kaedah ini apabila anda ingin mengendalikan parameter yang dibekalkan dan bukannya hanya menyerahkan kepada harta.

kelihatan sangat kabur dan jarang digunakan, tetapi sebenarnya anda mungkin pernah menemuinya berkali-kali, kerana ia biasanya digunakan semasa membina API, seperti dalam SQLAlchemy atau Flask Views tiba.

Kaedah sihir metaclass yang lain ialah __call__. Kaedah ini membenarkan penyesuaian perkara yang berlaku apabila contoh kelas dipanggil:

 class CallableClass:
def __call__(self, *args, **kwargs):
print("I was called!")
 
 instance = CallableClass()
 
 instance()
 # I was called!
Salin selepas log masuk
Anda boleh menggunakan ini untuk mencipta kelas yang tidak boleh dipanggil:

 class NoInstances(type):
def __call__(cls, *args, **kwargs):
raise TypeError("Can't create instance of this class")
 
 class SomeClass(metaclass=NoInstances):
@staticmethod
def func(x):
print('A static method')
 
 instance = SomeClass()
 # TypeError: Can't create instance of this class
Salin selepas log masuk
Untuk kelas dengan statik sahaja kaedah, Kaedah ini digunakan tanpa membuat contoh kelas.

Satu lagi senario serupa ialah corak tunggal - kelas hanya boleh mempunyai paling banyak satu contoh:

 class Singleton(type):
def __init__(cls, *args, **kwargs):
cls.__instance = None
super().__init__(*args, **kwargs)
 
def __call__(cls, *args, **kwargs):
if cls.__instance is None:
cls.__instance = super().__call__(*args, **kwargs)
return cls.__instance
else:
return cls.__instance
 
 class Logger(metaclass=Singleton):
def __init__(self):
print("Creating global Logger instance")
Salin selepas log masuk
Kelas tunggal mempunyai __contoh peribadi - jika tidak, ia akan menjadi Cipta dan tetapkan nilai, ia hanya akan dikembalikan jika ia sudah wujud.

Andaikan anda mempunyai kelas dan anda ingin mencipta contoh kelas itu tanpa memanggil __init__. Kaedah __new__ boleh membantu dengan perkara ini:

 class Document:
def __init__(self, text):
self.text = text
 
 bare_document = Document.__new__(Document)
 print(bare_document.text)
 # AttributeError: 'Document' object has no attribute 'text'
 
 setattr(bare_document, "text", "Text of the document")
Salin selepas log masuk
Dalam sesetengah kes, kita mungkin perlu memintas proses biasa untuk mencipta tika, dan kod di atas menunjukkan cara untuk melakukannya. Daripada memanggil Document(…), kami memanggil Document.__new__(Document), yang mencipta contoh kosong tanpa memanggil __init__. Oleh itu, atribut contoh (teks dalam kes ini) tidak dimulakan, jadi kita perlu menggunakan fungsi setattr tambahan untuk menetapkan nilai (ia juga kaedah ajaib __setattr__).

Mengapa anda melakukan ini? Kerana kita mungkin mahu menggantikan pembina, seperti:

 class Document:
def __init__(self, text):
self.text = text
 
@classmethod
def from_file(cls, file): # Alternative constructor
d = cls.__new__(cls)
# Do stuff...
return d
Salin selepas log masuk
Kaedah from_file ditakrifkan di sini, yang bertindak sebagai pembina, mula-mula menggunakan __new__ untuk mencipta contoh, dan kemudian mengkonfigurasinya tanpa memanggil __init__ itu .

Kaedah ajaib seterusnya yang berkaitan dengan pengaturcaraan meta ialah __getattr__. Kaedah ini dipanggil apabila akses harta biasa gagal. Ini boleh digunakan untuk mewakilkan akses/panggilan kepada kaedah yang hilang kepada kelas lain:

 class String:
def __init__(self, value):
self._value = str(value)
 
def custom_operation(self):
pass
 
def __getattr__(self, name):
return getattr(self._value, name)
 
 s = String("some text")
 s.custom_operation() # Calls String.custom_operation()
 print(s.split()) # Calls String.__getattr__("split") and delegates to str.split
 # ['some', 'text']
 
 print("some text" + "more text")
 # ... works
 print(s + "more text")
 # TypeError: unsupported operand type(s) for +: 'String' and 'str'
Salin selepas log masuk
Kami ingin menambah beberapa fungsi tambahan pada kelas (seperti custom_operation di atas) untuk menentukan pelaksanaan tersuai rentetan. Tetapi kami tidak mahu melaksanakan semula setiap kaedah rentetan, seperti split, join, capitalize, dsb. Di sini kita boleh menggunakan __getattr__ untuk memanggil kaedah rentetan sedia ada ini.

Walaupun ini berfungsi untuk kaedah biasa, ambil perhatian bahawa dalam contoh di atas, kaedah ajaib __add__ (yang menyediakan operasi seperti sambungan) tidak mendapat perwakilan. Jadi, jika kita mahu mereka bekerja juga, kita perlu melaksanakannya semula.

自省(introspection)

最后一个与元编程相关的方法是__getattribute__。它一个看起来非常类似于前面的__getattr__,但是他们有一个细微的区别,__getattr__只在属性查找失败时被调用,而__getattribute__是在尝试属性查找之前被调用。

所以可以使用__getattribute__来控制对属性的访问,或者你可以创建一个装饰器来记录每次访问实例属性的尝试:

 def logger(cls):
original_getattribute = cls.__getattribute__
 
def getattribute(self, name):
print(f"Getting: '{name}'")
return original_getattribute(self, name)
 
cls.__getattribute__ = getattribute
return cls
 
 @logger
 class SomeClass:
def __init__(self, attr):
self.attr = attr
 
def func(self):
...
 
 instance = SomeClass("value")
 instance.attr
 # Getting: 'attr'
 instance.func()
 # Getting: 'func'
Salin selepas log masuk

装饰器函数logger 首先记录它所装饰的类的原始__getattribute__方法。然后将其替换为自定义方法,该方法在调用原始的__getattribute__方法之前记录了被访问属性的名称。

魔法属性

到目前为止,我们只讨论了魔法方法,但在Python中也有相当多的魔法变量/属性。其中一个是__all__:

 # some_module/__init__.py
 __all__ = ["func", "some_var"]
 
 some_var = "data"
 some_other_var = "more data"
 
 def func():
return "hello"
 
 # -----------
 
 from some_module import *
 
 print(some_var)
 # "data"
 print(func())
 # "hello"
 
 print(some_other_var)
 # Exception, "some_other_var" is not exported by the module
Salin selepas log masuk

这个属性可用于定义从模块导出哪些变量和函数。我们创建了一个Python模块…/some_module/单独文件(__init__.py)。在这个文件中定义了2个变量和一个函数,只导出其中的2个(func和some_var)。如果我们尝试在其他Python程序中导入some_module的内容,我们只能得到2个内容。

但是要注意,__all__变量只影响上面所示的* import,我们仍然可以使用显式的名称导入函数和变量,比如import some_other_var from some_module。

另一个常见的双下划线变量(模块属性)是__file__。这个变量标识了访问它的文件的路径:

 from pathlib import Path
 
 print(__file__)
 print(Path(__file__).resolve())
 # /home/.../directory/examples.py
 
 # Or the old way:
 import os
 print(os.path.dirname(os.path.abspath(__file__)))
 # /home/.../directory/
Salin selepas log masuk

这样我们就可以结合__all__和__file__,可以在一个文件夹中加载所有模块:

# Directory structure:
 # .
 # |____some_dir
 # |____module_three.py
 # |____module_two.py
 # |____module_one.py
 
 from pathlib import Path, PurePath
 modules = list(Path(__file__).parent.glob("*.py"))
 print([PurePath(f).stem for f in modules if f.is_file() and not f.name == "__init__.py"])
 # ['module_one', 'module_two', 'module_three']
Salin selepas log masuk

最后一个我重要的属性是的是__debug__。它可以用于调试,但更具体地说,它可以用于更好地控制断言:

 # example.py
 def func():
if __debug__:
print("debugging logs")
 
# Do stuff...
 
 func()
Salin selepas log masuk

如果我们使用python example.py正常运行这段代码,我们将看到打印出“调试日志”,但是如果我们使用python -O example.py,优化标志(-O)将把__debug__设置为false并删除调试消息。因此,如果在生产环境中使用-O运行代码,就不必担心调试过程中被遗忘的打印调用,因为它们都不会显示。

创建自己魔法方法?

我们可以创建自己的方法和属性吗?是的,你可以,但你不应该这么做。

双下划线名称是为Python语言的未来扩展保留的,不应该用于自己的代码。如果你决定在你的代码中使用这样的名称,那么将来如果它们被添加到Python解释器中,这就与你的代码不兼容了。所以对于这些方法,我们只要记住和使用就好了。

Atas ialah kandungan terperinci Kaedah ajaib dalam Python. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Adakah kelajuan penukaran cepat apabila menukar XML ke PDF pada telefon bimbit? Adakah kelajuan penukaran cepat apabila menukar XML ke PDF pada telefon bimbit? Apr 02, 2025 pm 10:09 PM

Kelajuan XML mudah alih ke PDF bergantung kepada faktor -faktor berikut: kerumitan struktur XML. Kaedah Penukaran Konfigurasi Perkakasan Mudah Alih (Perpustakaan, Algoritma) Kaedah Pengoptimuman Kualiti Kod (Pilih perpustakaan yang cekap, mengoptimumkan algoritma, data cache, dan menggunakan pelbagai threading). Secara keseluruhannya, tidak ada jawapan mutlak dan ia perlu dioptimumkan mengikut keadaan tertentu.

Bagaimana cara menukar fail XML ke PDF di telefon anda? Bagaimana cara menukar fail XML ke PDF di telefon anda? Apr 02, 2025 pm 10:12 PM

Tidak mustahil untuk menyelesaikan penukaran XML ke PDF secara langsung di telefon anda dengan satu aplikasi. Ia perlu menggunakan perkhidmatan awan, yang boleh dicapai melalui dua langkah: 1. Tukar XML ke PDF di awan, 2. Akses atau muat turun fail PDF yang ditukar pada telefon bimbit.

Apakah fungsi jumlah bahasa C? Apakah fungsi jumlah bahasa C? Apr 03, 2025 pm 02:21 PM

Tiada fungsi jumlah terbina dalam dalam bahasa C, jadi ia perlu ditulis sendiri. Jumlah boleh dicapai dengan melintasi unsur -unsur array dan terkumpul: Versi gelung: SUM dikira menggunakan panjang gelung dan panjang. Versi Pointer: Gunakan petunjuk untuk menunjuk kepada unsur-unsur array, dan penjumlahan yang cekap dicapai melalui penunjuk diri sendiri. Secara dinamik memperuntukkan versi Array: Perlawanan secara dinamik dan uruskan memori sendiri, memastikan memori yang diperuntukkan dibebaskan untuk mengelakkan kebocoran ingatan.

Cara menukar XML ke dalam gambar Cara menukar XML ke dalam gambar Apr 03, 2025 am 07:39 AM

XML boleh ditukar kepada imej dengan menggunakan perpustakaan penukar XSLT atau imej. XSLT Converter: Gunakan pemproses XSLT dan stylesheet untuk menukar XML ke imej. Perpustakaan Imej: Gunakan perpustakaan seperti PIL atau ImageMagick untuk membuat imej dari data XML, seperti bentuk lukisan dan teks.

Adakah terdapat aplikasi mudah alih yang boleh menukar XML ke PDF? Adakah terdapat aplikasi mudah alih yang boleh menukar XML ke PDF? Apr 02, 2025 pm 08:54 PM

Permohonan yang menukarkan XML terus ke PDF tidak dapat dijumpai kerana mereka adalah dua format yang berbeza. XML digunakan untuk menyimpan data, manakala PDF digunakan untuk memaparkan dokumen. Untuk melengkapkan transformasi, anda boleh menggunakan bahasa pengaturcaraan dan perpustakaan seperti Python dan ReportLab untuk menghuraikan data XML dan menghasilkan dokumen PDF.

Adakah terdapat aplikasi mudah alih yang boleh menukar XML ke PDF? Adakah terdapat aplikasi mudah alih yang boleh menukar XML ke PDF? Apr 02, 2025 pm 09:45 PM

Tiada aplikasi yang boleh menukar semua fail XML ke dalam PDF kerana struktur XML adalah fleksibel dan pelbagai. Inti XML ke PDF adalah untuk menukar struktur data ke dalam susun atur halaman, yang memerlukan parsing XML dan menjana PDF. Kaedah umum termasuk parsing XML menggunakan perpustakaan python seperti ElementTree dan menjana PDF menggunakan perpustakaan ReportLab. Untuk XML yang kompleks, mungkin perlu menggunakan struktur transformasi XSLT. Apabila mengoptimumkan prestasi, pertimbangkan untuk menggunakan multithreaded atau multiprocesses dan pilih perpustakaan yang sesuai.

Alat pemformatan XML yang disyorkan Alat pemformatan XML yang disyorkan Apr 02, 2025 pm 09:03 PM

Alat pemformatan XML boleh menaip kod mengikut peraturan untuk meningkatkan kebolehbacaan dan pemahaman. Apabila memilih alat, perhatikan keupayaan penyesuaian, pengendalian keadaan khas, prestasi dan kemudahan penggunaan. Jenis alat yang biasa digunakan termasuk alat dalam talian, pemalam IDE, dan alat baris arahan.

Cara Membuka Format XML Cara Membuka Format XML Apr 02, 2025 pm 09:00 PM

Gunakan kebanyakan editor teks untuk membuka fail XML; Jika anda memerlukan paparan pokok yang lebih intuitif, anda boleh menggunakan editor XML, seperti editor XML oksigen atau XMLSPY; Jika anda memproses data XML dalam program, anda perlu menggunakan bahasa pengaturcaraan (seperti Python) dan perpustakaan XML (seperti XML.Etree.ElementTree) untuk menghuraikan.

See all articles