fbpx

تعلم لغة البايثون – الدرس الثالث والعشرون المزخرفات في بايثون Python Decorators



يتيح لك الديكور إجراء تعديلات بسيطة على الأشياء القابلة للاستدعاء مثل الوظائف أو الأساليب أو الفئات. سنتعامل مع وظائف لهذا البرنامج التعليمي. بناء الجملة

@decorator
def functions(arg):
    return "value"

تعادل:

def function(arg):
    return "value"
function = decorator(function) # هذا يمرر الوظيفة إلى الديكور ، ويعيد تعيينها إلى الوظائف

كما رأيت ، الديكور هو مجرد وظيفة أخرى تأخذ وظائف وتعيد واحدة. على سبيل المثال ، يمكنك القيام بذلك:

def repeater(old_function):
    def new_function(*args, **kwds): # انظر Learnpython.org/en/Multiple٪20Function٪20Arguments لكيفية * args و **kwds works
        old_function(*args, **kwds) # ندير الوظيفة القديمة
        old_function(*args, **kwds) # نقوم بذلك مرتين
     return new_function # يجب أن نعيد new_function ، أو لن يعيد تعيينها إلى القيمة

هذا سيجعل وظيفة تتكرر مرتين.

>>> @repeater
def multiply(num1, num2):
    print(num1 * num2)

>>> multiply(2, 3)
6
6

يمكنك أيضًا جعلها تغير الناتج

def double_out(old_function):
    def new_function(*args, **kwds):
        return 2 * old_function(*args, **kwds) # تعديل القيمة المعادة
    return new_function

تغيير المدخلات

def double_Ii(old_function):
    def new_function(arg): # يعمل فقط إذا كانت الوظيفة القديمة لها وسيطة واحدة
        return old_function(arg * 2) # تعديل الحجة التي تم تمريرها
    return new_function

والقيام بالتحقق.

def check(old_function):
    def new_function(arg):
        if arg < 0: raise (ValueError, "Negative Argument") # هذا يتسبب في خطأ ، وهو أفضل من فعل الشيء الخطأ
        old_function(arg)
    return new_function

لنفترض أنك تريد ضرب الناتج بمقدار متغير. يمكنك تحديد الديكور واستخدامه على النحو التالي:

def multiply(multiplier):
    def multiply_generator(old_function):
        def new_function(*args, **kwds):
            return multiplier * old_function(*args, **kwds)
        return new_function
    return multiply_generator # تقوم بإرجاع المولد الجديد

# الاستخدام
@multiply(3) # الضرب ليس مولدا ، ولكن الضرب (3)
def return_num(num):
    return num

# الآن تم تزيين return_num وإعادة تعيينه في نفسه
return_num(5) # should return 15

سنحصل على النتيجة التالية عند التشغيل

Out[1]: 15

يمكنك فعل أي شيء تريده مع الوظيفة القديمة ، حتى تجاهلها تمامًا! يمكن للمصممين المتقدمين أيضًا معالجة سلسلة المستندات ورقم الوسيطة. بالنسبة لبعض الديكورات الرائعة ، انتقل إلى http://wiki.python.org/moin/PythonDecoratorLibrary.

تمرين

اصنع مصنعًا للديكور يعيد الديكور الذي يزين الوظائف بحجة واحدة. يجب أن يأخذ المصنع وسيطة واحدة ، ونوعًا ، ثم يعيد مصممًا يجعل الوظيفة يجب أن تتحقق مما إذا كان الإدخال هو النوع الصحيح. إذا كانت خاطئة ، يجب أن تطبع (“Bad Type”) (في الواقع ، يجب أن تثير خطأ ، ولكن رفع الخطأ ليس في هذا البرنامج التعليمي). انظر إلى رمز البرنامج التعليمي والمخرجات المتوقعة لمعرفة ما إذا كنت مرتبكًا (أعلم أنني سأكون كذلك). قد يساعد استخدام isinstance (كائن ، type_of_object) أو نوع (كائن).

def type_check(correct_type):
# كود الإدخال هنا

@type_check(int)
def times2(num):
    return num*2

print(times2(2))
times2('Not A Number')

@type_check(str)
def first_letter(word):
    return word[0]

print(first_letter('Hello World'))
first_letter(['Not', 'A', 'String'])

الحل

def type_check(correct_type):
    def check(old_function):
        def new_function(arg):
            if (isinstance(arg, correct_type)):
                return old_function(arg)
            else:
                print("Bad Type")
        return new_function
    return check

@type_check(int)
def times2(num):
    return num*2

print(times2(2))
times2('Not A Number')

@type_check(str)
def first_letter(word):
    return word[0]

print(first_letter('Hello World'))
first_letter(['Not', 'A', 'String'])

سنحصل على النتيجة التالية عند التشغيل

<script.py> output:
    4
    Bad Type
    H
    Bad Type





Leave a Reply