Tutorial Material

Metadasturlash (metaprogramming)

Share to
Python metaprogramming

Metaprogramming - bu dastur boshqa dasturlarni data sifatida ko'ra oladigan tushuncha. Ya'ni dastur boshqa kodni o'qishi, generatsiya qilishi, tahlil qilishi, o'zgartirishi, hatto ish paytida o'zini ham modifikatsiya qilishi mumkin. Qisqacha: kod yozadigan kod.

Python'da bu juda chuqur va murakkab mavzu, lekin to'g'ri ishlatilsa juda kuchli. Python metaprogramming'ining asosiy elementlaridan biri - metaclass.

1. Class nima?

Metaclass'ni tushunishdan oldin eslab qoling: Python'da class ham object. Siz class yozganingizda, Python uni bajaradi va xotirada class object yaratadi.

class ObjectCreator:
    pass

my_obj = ObjectCreator()
print(my_obj) # Instance of ObjectCreator

print(ObjectCreator) # ObjectCreator itself is an object!

Class object bo'lgani uchun:

2. "Sehrli" type() funksiyasi

Odatda type()ni data turini ko'rish uchun ishlatamiz:

print(type(1)) # <class 'int'>

Lekin type() yordamida class'larni dinamik yaratish ham mumkin.

Sintaksis: type(name, bases, attrs)

# Oddiy usul
class Monkey:
    def eat(self):
        print("Eating banana")

# Metaprogramming usuli (aynan bir xil!)
def eat_function(self):
    print("Eating banana")

DynamicMonkey = type('DynamicMonkey', (), {'eat': eat_function})

m = DynamicMonkey()
m.eat() # Natija: Eating banana

3. Metaclass

Metaclass - class'larni yaratadigan "factory".

Python'da default metaclass - type.

class MyClass:
    pass

print(type(MyClass)) # <class 'type'>

Custom metaclass yaratish

Class qanday yaratilishini nazorat qilish uchun o'zingiz metaclass yozishingiz mumkin. Bu ko'pincha class atributlarini validatsiya qilish yoki strict API yaratishda (masalan Django Models) ishlatiladi.

Metaclass yaratish uchun typedan meros oling. Class ta'rifida metaclass= argumentidan foydalanamiz.

Misol: barcha atribut nomlarini Uppercase qilish

class UpperAttrMeta(type):
    # __new__ is called before __init__
    def __new__(upperattr_metaclass, future_class_name, 
                future_class_parents, future_class_attr):
        
        # Katta harfli kalitlar bilan yangi atribut lug'ati yaratish
        uppercase_attr = {}
        for name, val in future_class_attr.items():
            if not name.startswith('__'): # Don't change magic methods
                uppercase_attr[name.upper()] = val
            else:
                uppercase_attr[name] = val
        
        # Class yaratish uchun type.__new__ ni chaqirish
        return type(future_class_name, future_class_parents, uppercase_attr)

# Metaclass ishlatish
class Foo(metaclass=UpperAttrMeta):
    bar = 'bip'

print(hasattr(Foo, 'bar')) # False (because changed to BAR)
print(hasattr(Foo, 'BAR')) # True
print(Foo.BAR) # 'bip'

4. Metaclass qachon kerak?

Javob: deyarli hech qachon, agar freymvork (framework) qurmayotgan bo'lsangiz.

"Metaclasses are deeper magic than 99% of users should ever worry about. If you wonder whether you need them, you don't." - Tim Peters (Python Guru)

Lekin mavzuni tushunish Python qanday ishlashini chuqurroq anglashga yordam beradi.

Xulosa