حفظ kwarg الافتراضي في Python

هذه هي الطريقة التي يمكنك من خلالها حفظ وظيفة Python:

def memo_square(a, cache={}): if a not in cache: cache[a] = a*a return cache[a] 

الاستقبال غير معروف بشكل غير مستحق ، لذلك تحت القطع ، سنقوم بتحليل كيفية عمله وما الغرض منه.

أولا ، كيف ولماذا يعمل. memo_square (مثل أي وظيفة أخرى) هو كائن من فئة الوظائف ، والذي يحتوي ، من بين السمات الأخرى ، على memo_square.__defaults__ المملوءة عند إنشاء الكائن. أولاً ، يحتوي على قاموس فارغ ، كما هو موضح في رأس الوظيفة:

 >>> memo_square.__defaults__ ({},) 

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

 >>> def test(a=1, b=2): ... print(a, b) ... >>> test.__defaults__ (1, 2) >>> test() 1 2 >>> test.__defaults__ = (', ', '') >>> test() ,  >>> test.__defaults__[1] = '' Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'tuple' object does not support item assignment >>> test.__defaults__ = {0: ', ', 1: ''} Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: __defaults__ must be set to a tuple object 

سوريان ، لن تصل هذه المقالة إلى Picaba. حسنًا ، حسنًا ، هذا ليس مهمًا. الشيء المهم هو أنه باستثناء الشفرة الماكرة للغاية ، يتم إنشاء func.__defaults__ مرة واحدة خلال وقت البرنامج مع جميع عناصره. لن يتم إعادة إنشاء مجموعة tuple وعناصرها مع كل استدعاء دالة ، وسيتم استخدامها طالما كانت الوظيفة موجودة. لكن التغيير ، إذا كانت العناصر نفسها قابلة للتغيير ، فلا أحد يمنعها. تعد عدم القدرة على العمل مع هذه العناصر من أكثر الطرق شيوعًا لتصوير نفسك في الثعبان . ولكن في الواقع يمكن أن يكون حفظ القيم بين استدعاءات الوظائف مفيدًا جدًا. بعد عدة مكالمات ، memo_square.__defaults__ كما يلي:

 >>> memo_square(2) 4 >>> memo_square.__defaults__ ({2: 4},) >>> memo_square(5) 25 >>> memo_square.__defaults__ ({2: 4, 5: 25},) >>> memo_square(2) 4 >>> memo_square.__defaults__ ({2: 4, 5: 25},) 

إذا كانت الوظيفة قد تم استدعاؤها بالفعل للقيمة نفسها ، فسيتم حساب القيمة ، وبالتالي ، لا يتم تجديد ذاكرة التخزين المؤقت. بالنسبة للمربع ، تكون الفائدة صغيرة (بشكل دقيق ، بالنسبة للمربع ، تكون الفائدة سلبية ، لأن البحث في القاموس أغلى من ضرب رقمين) ، ولكن يمكن أن يكون استرجاع / تخزين مؤقت للوظائف باهظة الثمن مفيدًا. بالطبع ، يمكنك توفيره في بيثون بأكثر من طريقة. إليك البدائل المتاحة لدينا:

  • @ functools.lru_cache . مصمم من وحدة functools يتذكر آخر مكالمات الوظيفة. إنها موثوقة وبسيطة ، ولكنها تستخدم جميع معلمات الوظيفة كمفاتيح ، مما يعني أنها تتطلب قابلية للتجزئة ولا يمكنها ملاحظة أن هناك قيمتين مختلفتين رسميًا متساويين. مع المطلب الأول ، كل شيء واضح ، حول الوظائف من المجموعات ، على سبيل المثال ، يمكنك نسيانها. حسنًا ، أو عند الاتصال ، قم بتحويلها إلى frozenset. أما بالنسبة للثاني ، على سبيل المثال ، لدي وظيفة تأخذ اتصال SQL ورقم كمدخل وتقوم ببعض التلاعب بالبيانات المرتبطة بهذا الرقم. قد يتم قطع الاتصال وإعادة تأسيسه جيدًا أثناء تشغيل البرنامج ، وستنتقل ذاكرة التخزين المؤقت lru_cache بعد ذلك. لكنه يعرف كيفية تخزين عدد محدود فقط من المكالمات (تجنب تسرب الذاكرة) وموثق جيدًا.
  • وظيفة التخزين المؤقت خارج:

     def square(a): return a**a cache = {} for x in values: if x not in cache: cache[x] = x**x print cache[x] 

    المعنى هو نفسه ، ولكن أكثر تعقيدًا. بالإضافة إلى ذلك ، يكون متغير ذاكرة التخزين المؤقت مرئيًا خارج الوظيفة ، على الرغم من أنه لا يتم استخدامه لأي شيء بخلاف تدوينه. يمكن الوصول إلى ذاكرة التخزين المؤقت أثناء الحفظ باستخدام الوسيطة الافتراضية خارجيًا فقط من خلال func.__defaults__ ، والتي يصعب الوصول إليها عن طريق الخطأ.
  • امسح كائن كامل بذاكرة تخزين مؤقت واجعل وظيفته طريقة. جيد من حيث الهندسة المعمارية والقابلية للاختبار ، فهو يسمح لك بالحفاظ على منطق تخزين مؤقت معقد بشكل تعسفي ، ولكن أكثر تعقيدًا بسبب الصفيحة في رمز الكائن. بالإضافة إلى ذلك ، ليس من الواضح ما الذي ترث منه وما إذا كنت تريد أن ترث من أي شيء على الإطلاق ، إذا كان هناك أكثر من وظيفة يمكن تذكرها.

الشيء الرئيسي الذي تفقده هذه الطريقة في التذكر هو أنها ليست اصطلاحية للغاية. شخصيا ، عندما عثرت على هذا القرار لأول مرة ، فكرت لبضع دقائق في ما يجري هنا ولماذا. من ناحية أخرى ، في هاتين الدقيقتين بدأت أفهم بشكل أفضل قليلاً كيف يتم ترتيب وظائف Python وحججها. لذلك حتى إذا كنت لا تستخدم الوسيطات الافتراضية (للتذكير أو ، على سبيل المثال ، لتسريع تحليل الاسم ) ، فإن معرفة هذه التقنية لا تزال مفيدة لأي خبير تغذية.

Source: https://habr.com/ru/post/ar426341/


All Articles