Python metaprogramming merujuk kepada teknologi pengendalian kod Python pada masa jalan Ia boleh menjana, mengubah suai dan melaksanakan kod secara dinamik untuk mencapai beberapa kemahiran pengaturcaraan lanjutan. Pemrograman meta Python termasuk teknologi seperti kelas meta, penghias, atribut dinamik dan import dinamik Teknologi ini boleh membantu kami memahami dan menguasai ciri dan mekanisme bahasa Python dengan lebih baik. Metaprogramming sangat berguna dalam beberapa senario, seperti melaksanakan rangka kerja ORM, melaksanakan DSL dalam bidang tertentu, mengubah suai tingkah laku kelas secara dinamik, dsb. Menguasai teknologi metaprogramming Python boleh meningkatkan keupayaan pengaturcaraan dan kualiti kod kami.
Untuk menguasai pengaturcaraan meta, anda mesti memahami dan menguasai teknologi pengaturcaraan meta dalam Python:
Refleksi: Python menyediakan banyak fungsi dan modul terbina dalam, seperti getattr( ) , setattr(), hasattr(), inspect, dsb., boleh secara dinamik mendapatkan atribut objek dan maklumat kaedah semasa runtime, dengan itu merealisasikan refleksi.
Penghias: Penghias ialah teknik pengaturcaraan meta biasa dalam Python yang boleh mengubah suai gelagat fungsi atau kelas secara dinamik tanpa mengubah suai kod sumbernya. Penghias boleh digunakan untuk semakan parameter fungsi, analisis prestasi, caching, pembalakan, dsb.
Penghias kelas: Penghias kelas ialah penghias yang menghiasi kelas dan boleh mengubah suai gelagat kelas secara dinamik apabila ia ditakrifkan. Penghias kelas boleh digunakan untuk melaksanakan mod tunggal, mod proksi, campuran masuk, dsb.
Metaclass: Metaclass ialah teknik pengaturcaraan meta lanjutan dalam Python yang mencipta kelas secara dinamik dan bukannya contoh. Metaclasses boleh digunakan untuk mengawal tingkah laku penciptaan kelas, menambah sifat dan kaedah kelas, melaksanakan rangka kerja ORM, dsb.
Dalam pembangunan sebenar, pengaturcaraan meta boleh digunakan untuk melaksanakan beberapa teknologi canggih, seperti rangka kerja ORM, rangka kerja RPC, penghalaan dinamik, dsb. Menguasai teknologi metaprogramming Python boleh membolehkan pembangun memahami dengan lebih baik ciri bahasa Python dan meningkatkan kebolehbacaan dan kebolehselenggaraan kod.
Senario aplikasi sebenar pengaturcaraan Python sangat luas, seperti senario biasa berikut:
Penghias dan penghias Kelas pengaturcaraan meta dan metaclass ialah teknik metaprogramming biasa dalam Python Melalui kedua-dua teknologi ini, kelas dan fungsi boleh diubah suai dan diperluaskan secara dinamik. Contohnya, anda boleh menggunakan penghias untuk meningkatkan kefungsian fungsi, atau menggunakan metaclass untuk menjana kelas secara dinamik.
Penjanaan kod dinamik Fungsi eval dan exec dalam Python boleh digunakan untuk menjana kod secara dinamik dan melaksanakannya, yang merupakan senario aplikasi biasa pengaturcaraan meta. Contohnya, pernyataan SQL atau kod lain boleh dijana secara dinamik berdasarkan input pengguna.
Seni bina pemalam Dalam seni bina pemalam, atur cara boleh memuatkan dan memunggah pemalam secara dinamik semasa masa jalan. Mekanisme modul dan pakej dalam Python boleh digunakan untuk melaksanakan seni bina pemalam, dan teknik pengaturcaraan meta boleh digunakan untuk melaksanakan pemuatan dan pemunggahan pemalam dinamik.
Pengaturcaraan coroutine dan tak segerak Dalam pengaturcaraan coroutine dan asynchronous, kod tersebut perlu diubah suai dan dibina semula secara dinamik untuk mencapai pemprosesan serentak yang cekap. Perpustakaan seperti asyncio dan curio dalam Python dilaksanakan berdasarkan teknik metaprogramming.
Pengaturcaraan berasaskan atribut Atribut dalam Python boleh digunakan untuk mengakses sifat objek secara dinamik, yang merupakan senario aplikasi biasa pengaturcaraan meta. Contohnya, sifat boleh digunakan untuk melaksanakan fungsi seperti penukaran jenis dinamik, pengesahan data dan sifat yang dikira.
Python metaprogramming mempunyai pelbagai senario aplikasi dan boleh digunakan untuk melaksanakan pelbagai fungsi pengaturcaraan dinamik dan lanjutan.
1 Gunakan metaclass untuk melaksanakan rangka kerja ORM yang mudah
class ModelMetaClass(type): def __new__(cls, name, bases, attrs): if name == 'Model': return super().__new__(cls, name, bases, attrs) table_name = attrs.get('table_name', name.lower()) mappings = {} fields = [] for k, v in attrs.items(): if isinstance(v, Field): mappings[k] = v fields.append(k) for k in mappings.keys(): attrs.pop(k) attrs['__table__'] = table_name attrs['__mappings__'] = mappings attrs['__fields__'] = fields return super().__new__(cls, name, bases, attrs) class Model(metaclass=ModelMetaClass): def __init__(self, **kwargs): for k, v in kwargs.items(): setattr(self, k, v) def save(self): fields = [] values = [] for k, v in self.__mappings__.items(): fields.append(v.db_column or k) values.append(getattr(self, k, None)) sql = 'INSERT INTO {} ({}) VALUES ({})'.format( self.__table__, ', '.join(fields), ', '.join(['%s'] * len(values)) ) print('SQL:', sql) print('VALUES:', values) class Field: def __init__(self, db_column=None): self.db_column = db_column class StringField(Field): def __init__(self, db_column=None): super().__init__(db_column) class IntegerField(Field): def __init__(self, db_column=None): super().__init__(db_column) class User(Model): name = StringField(db_column='user_name') age = IntegerField(db_column='user_age') email = StringField(db_column='user_email') if __name__ == '__main__': user = User(name='Tantianran', age=31, email='ttr@bbgops.com') user.save()
Dalam kod di atas, gunakan metaclass ModelMetaClass untuk mencipta kelas secara dinamik dan menetapkan kelas berdasarkan kelas Definisi atribut menjana struktur jadual pangkalan data yang sepadan dan pernyataan SQL. Khususnya, metaclass akan menghasilkan hubungan pemetaan ORM yang sepadan dan pernyataan SQL melalui atribut kelas __mappings__, __fields__ dan __table__. Dengan menggunakan kaedah ini, kita boleh mencipta rangka kerja ORM yang mudah dan melaksanakan pemetaan pangkalan data objek-ke-hubungan tanpa menulis kod berulang.
2. Gunakan metaclass untuk melaksanakan corak tunggal
class Singleton(type): _instances = {} def __call__(cls, *args, **kwargs): if cls not in cls._instances: cls._instances[cls] = super().__call__(*args, **kwargs) return cls._instances[cls] class MyClass(metaclass=Singleton): pass
Dalam contoh ini, kami mentakrifkan metaclass Singleton, yang mengekalkan kamus _instances untuk menyimpan kejadian yang dibuat. Dalam kaedah panggilan metaclass, kami menyemak sama ada kelas semasa sudah wujud dalam kamus _instances Jika ia tidak wujud, gunakan kaedah super().panggilan untuk mencipta tika baharu. . , dan simpan ke kamus _instances, dan akhirnya kembalikan contoh itu. Dengan cara ini, tidak kira berapa banyak contoh kelas MyClass yang kita buat, kita hanya akan mendapat contoh yang sama.
3. Gunakan metaclass untuk melaksanakan penghias
class my_decorator(object): def __init__(self, func): self.func = func def __call__(self, *args, **kwargs): print("Before the function is called.") self.func(*args, **kwargs) print("After the function is called.") class Myclass(object): @my_decorator def my_method(self): print("Hello world.") obj = Myclass() obj.my_method()
Dalam contoh ini, kami mentakrifkan kelas penghias my_decorator, yang menerima fungsi sebagai parameter dan mengeluarkan beberapa maklumat sebelum dan selepas panggilan fungsi . Menggunakan penghias @my_decorator pada kaedah my_method kelas Myclass adalah bersamaan dengan menggantikan kaedah my_method dengan kaedah baharu yang akan mengeluarkan maklumat sebelum dan selepas kaedah asal.
4. Gunakan metaclass untuk melaksanakan kaedah caching
class memoize(object): def __init__(self, func): self.func = func self.cache = {} def __call__(self, *args): if args in self.cache: return self.cache[args] else: value = self.func(*args) self.cache[args] = value return value @memoize def fibonacci(n): if n <= 1: return n else: return fibonacci(n-1) + fibonacci(n-2)
在这个示例中,我们定义了一个装饰器类 memoize,它接受一个函数作为参数,并使用一个字典来保存函数的输入和输出。在 call 方法中,我们首先检查函数的输入是否已经在字典中,如果是,则直接返回字典中对应的输出;否则,就调用原来的函数计算输出,并将输入和输出保存到字典中,最后返回输出。这样,如果我们多次调用带有 @memoize 装饰器的函数,对于相同的输入,就只会计算一次,从而大大提高了性能。
5.使用元编程技术动态生成代码
class DynamicClass(type): def __new__(mcs, name, bases, attrs): # 添加属性 attrs['author'] = 'John Doe' # 添加方法 def hello(self): return f'Hello, I am {self.name}' attrs['hello'] = hello return super().__new__(mcs, name, bases, attrs) # 使用元类创建类 MyClass = DynamicClass('MyClass', (), {'name': 'Alice'}) # 访问属性和方法 print(MyClass.name) # 输出:Alice print(MyClass.author) # 输出:John Doe obj = MyClass() print(obj.hello()) # 输出:Hello, I am Alice
在上面的示例中,使用了元类DynamicClass来动态创建类,__new__方法在类创建时被调用,用来动态添加属性和方法。在这个例子中,我们通过__new__方法向MyClass类中添加了一个author属性和一个hello方法。最后创建了MyClass类的一个实例,并调用了它的hello方法。
Atas ialah kandungan terperinci Metaprogramming dalam Python dan aplikasinya. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!