Metaprogramming dalam Python dan aplikasinya

PHPz
Lepaskan: 2023-05-07 14:16:15
ke hadapan
1245 orang telah melayarinya

Apakah itu metaprogramming

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 pengaturcaraan meta

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.

Pertempuran sebenar yang komprehensif

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()
Salin selepas log masuk

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
Salin selepas log masuk

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()
Salin selepas log masuk

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)
Salin selepas log masuk

在这个示例中,我们定义了一个装饰器类 memoize,它接受一个函数作为参数,并使用一个字典来保存函数的输入和输出。在 call 方法中,我们首先检查函数的输入是否已经在字典中,如果是,则直接返回字典中对应的输出;否则,就调用原来的函数计算输出,并将输入和输出保存到字典中,最后返回输出。这样,如果我们多次调用带有 @memoize 装饰器的函数,对于相同的输入,就只会计算一次,从而大大提高了性能。

5.使用元编程技术动态生成代码

class DynamicClass(type):
    def __new__(mcs, name, bases, attrs):
        # 添加属性
        attrs[&#39;author&#39;] = &#39;John Doe&#39;

        # 添加方法
        def hello(self):
            return f&#39;Hello, I am {self.name}&#39;

        attrs[&#39;hello&#39;] = hello

        return super().__new__(mcs, name, bases, attrs)

# 使用元类创建类
MyClass = DynamicClass(&#39;MyClass&#39;, (), {&#39;name&#39;: &#39;Alice&#39;})

# 访问属性和方法
print(MyClass.name) # 输出:Alice
print(MyClass.author) # 输出:John Doe
obj = MyClass()
print(obj.hello()) # 输出:Hello, I am Alice
Salin selepas log masuk

在上面的示例中,使用了元类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!

Label berkaitan:
sumber:yisu.com
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
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan