الدالة functools.update_wrapper()
في بايثون
تُحدّث الدّالة functools.update_wrapper()
دالّة مُحيطةً (wrapper) لتبدوَ مثل الدّالة المُحاطة (wrapped).
المُعاملات الاختياريّة هي صفوفٌ تُستخدم لتحديد أيّ خاصيّات الدّالة الأصليّة ستُعيّن مُباشرة للخاصيّات الموافقة لها على الدّالة المُحيطة وأيّ الخاصيّات من خاصيّات الدّالة المُحيطة ستُحدَّثُ بالخاصيّات المُوافقة لها في الدّالة الأصليّة. القيم الافتراضيّة لهذه المُعاملات هي الثّوابت المُتاحة على مستوى الوحدة:
WRAPPER_ASSIGNMENTS
: والتي تُعيّن كلّا من__module__
، و__name__
، و__qualname__
، و__annotations__
، و__doc__
، التي تُعدّ خاصيّاتٍ تُضيف معلومات حول الدّالة.WRAPPER_UPDATES
: التي تُحدّث خاصيّة__dict__
الخاصّة بالدّالة المُحيطة، أي قاموس النّسخة (the instance dictionary) الخاصّ بها.
تُضيف هذه الدّالة الخاصيّة __wrapped__
إلى الدّالة المُحيطة، وهذه الخاصيّة تُشير إلى الدّالة المُحاطة، وذلك للتّمكن من الوصول إلى الدّالة الأصليّة للتحقيق فيها (تجاهل مُزخرف تخبئة مثل المزخرف functools.lru_cache()
مثلًا).
تُستخدم هذه الدّالة أساسًا في الدّوال المُزخرِفة (decorator functions) التي تُحيط الدّالة المُزخرفَة وتُعيد الدّالة المُحيطة. إن لم تُحدَّث الدّالة المُحيطة، فالبيانات الوصفيّة (metadata) الخاصّة بالدّالة المُعادة ستُشير إلى تعريف الدّالة المُحيطة عوضًا عن تعريف الدّالة الأصليّة، الشيء الذي لا يكون مُفيدًا عادةً.
يُمكن استخدام الدّالة functools.update_wrapper()
مع الكائنات القابلة للاستدعاء الأخرى التي لا تكون دوالا. الخاصيّات التي تكون في الصّف assigned
أو الصّف updated
والتي تكون مفقودةً في الكائن المُحاط ستُتجاهَل (ولن تُحاول هذه الدّالة ضبط قيم لهذه الخاصيّات على الدّالة المُحيطة). يُطلق الاستثناء AttributeError
إن كانت الدّالة المُحيطة تفتقد أحد الخاصيّات المذكورة في الصّف updated
.
البنية العامة
functools.update_wrapper(wrapper, wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)
المعاملات
wrapper
الدّالة المُحيطة.
wrapped
الدّالة المُحاطة.
assigned
الخاصيّات التي ستُعيّن.
updated
الخاصيّات التي ستُحدّث.
القيمة المعادة
تُحدّث دالّة مُحيطةً لتبدوَ مثل الدّالة المُحاطة.
أمثلة
المثال التّالي يوضّح كيفيّة إنشاء دالة مُحيطة دون تحديثها بالدّالة، لاحظ أنّ اسم الدّالة خطأ:
>>> def to_str(function):
... def str_val(*args, **kwargs):
... result = function(*args, **kwargs)
... return str(result)
... return str_val # هنا نُعيد الدّالة المُحيطة
...
>>> @to_str
... def square(n):
... return n*n
...
>>> square(40)
'1600'
>>> square.__name__ # اسم الدّالة خطأ
'to_str'
وهنا نُحدّث الدّالة المُحيطة لتبدو مثل الدّالة المُحاطة، لاحظ أنّ اسم الدّالة المُحاطة أصبح يُعبّر عنها بشكل صحيح:
>>> def to_str(function):
... def str_val(*args, **kwargs):
... result = function(*args, **kwargs)
... return str(result)
... return functools.update_wrapper(str_val, function) # نُحدّث الدّالة المُحيطة بالدّالة الأصليّة قبل إعادتها
...
>>> @to_str
... def _square(n):
... return n*n
...
>>> _square.__name__ # اسم الدّالة صحيح
'_square'