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

0

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

@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

اترك رد

لن يتم نشر عنوان بريدك الإلكتروني.