سؤال

هذا من المدونة المصدر من CSV2REC في Matplotlib

كيف يمكن أن تعمل هذه الوظيفة، إذا كانت المعلمات الوحيدة هي "Func أو الافتراضي"؟

def with_default_value(func, default):
    def newfunc(name, val):
        if ismissing(name, val):
            return default
        else:
            return func(val)
    return newfunc

يأخذ ISCISSING اسما قيمة وقيمة وتحدد ما إذا كان يجب ملثمين الصف في صفيف Numpy.

ستكون Func إما Str أو int أو Float أو DeateParser ... يحول البيانات. ربما ليست مهمة. أنا فقط أتساءل كيف يمكن أن تحصل على "اسم" و "قيمة"

انا مبتدئ. شكرا لأي 2 سنتس! آمل أن أحصل على ما يكفي لمساعدة الآخرين!

هل كانت مفيدة؟

المحلول

هذه with_default_value الوظيفة هي ما يشار إليه في كثير من الأحيان (بشكل غير دقيق) ك "إغلاق" (من الناحية الفنية، الإغلاق بالأحرى داخلي وظيفة التي يتم إرجاعها، هنا newfunc - انظر على سبيل المثال هنا). أكثر واقعية، with_default_value هو وظيفة ذات طلب أعلى ("هف"): يستغرق وظيفة (func) كحجة، فإنه يعيد أيضا وظيفة (newfunc) كنتيجة.

رأيت إجابات مربكة هذا مع ديكور مفهوم وبناء في بيثون، وهذا بالتأكيد ليس القضية - خاصة منذ أن تذكر func غالبا ما تكون مدمجة مثل int. وبعد الديكورات هي أيضا وظائف ذات ترتيب أعلى، ولكنها محددة إلى حد ما: تلك التي ترجع زينت، أي إثراء "، نسخة من وسيطة وظائفها (التي يجب أن تكون فقط حجة - يتم الحصول على "الديكور مع الحجج" من خلال مستوى آخر من التعشيش / الإغلاق، ليس من خلال إعطاء Decorator HOF أكثر من حجة واحدة)، والتي يتم إعادة تعيينها بنفس الاسم تماما مثل هذه الوسيطة الوظيفية (وهكذا عادة ما يكون لها نفس التوقيع - باستخدام ديكور خلاف ذلك سيكون الى ابعد حد غريبة، الأمم المتحدة الاصطديية وغير قابلة للقراءة وغيرها).

لذلك انسى ديكور، والتي لا علاقة لها بالتأكيد مع القضية، والتركيز على newfunc إنهاء. يمكن أن تشير وظيفة متداخلة متعمدة إلى (وإن لم تكن ريدا) جميع الأسماء المتغيرة المحلية (بما في ذلك أسماء الوسائط، نظرا لأن الحجج هي المتغيرات المحلية) من الوظائف (الوظائف) المرفق - لهذا السبب تعرف باسم الإغلاق: إنه "مغلق" "المتغيرات الحرة". هنا، newfunc يمكن أن تشير إلى func و default -- و اعمل.

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

هذا كل ما يتعلق الأمر بهذا المثال - فلا تتردد في تحرير سؤالك وتعليقه هنا، إلخ، إذا كان هناك بعض الجانب المحدد الآخر الذي تظل فيه في شك!

يحرر: لذلك علق OP بالتوليد طلب المزيد من الأمثلة على "مصانع الإغلاق". إليك واحدة - تخيل بعض أنواع أدوات Gui Toolkit، وأنت تحاول القيام به:

for i in range(len(buttons)):
  buttons[i].onclick(lambda: mainwin.settitle("button %d click!" % i))

ولكن هذا لا يعمل بشكل صحيح - i في حدود lambda متأخرا، لذلك يتم النقر فوق زر واحد iالقيمة ستكون دائما مؤشر الاخير زر، بغض النظر عن أي واحد تم النقر فوق. هناك العديد من الحلول الممكنة، ولكن مصنع الإغلاق هو احتمال أنيق:

def makeOnclick(message):
  return lambda: mainwin.settitle(message)

for i in range(len(buttons)):
  buttons[i].onclick(makeOnClick("button %d click!" % i))

هنا، نحن نستخدم مصنع الإغلاق لتوجيه وقت الملزم للمتغيرات! -) في شكل واحد معين أو آخر، هذه حالة الاستخدام الشائعة جدا لمصانع الإغلاق.

نصائح أخرى

هذا هو الديكور بيثون - أساسا غلاف وظيفة. (اقرأ كل شيء عن الديكور في بيب 318 - http://www.python.org/dev/peps/peps/pep-0318/)

إذا نظرت من خلال التعليمات البرمجية، فمن المحتمل أن تجد شيئا مثل هذا:

def some_func(name, val):
    # ...
some_func = with_default_value(some_func, 'the_default_value')

يبدو أن نية هذا المزخرف توفر قيمة افتراضية إذا كانت حجج الاسم أو VAL مفقودة (يفترض، إذا تم ضبطها على أي).

أما لماذا تعمل:

with_default_value إرجاع كائن وظيفة، وهو أساسا سيكون ينسخ من تلك newfunc، مع استدعاء "func" والقيمة الافتراضية المفتوحة مع كل ما تم تمريره إلى with_default_value.

إذا قام شخص ما ب "foo = with_default_value (bar، 3)، فستكون قيمة الإرجاع أساسا وظيفة جديدة:

def foo(name, val):
    ifismissing(name, val):
        return 3
    else:
        return bar(val)

لذلك يمكنك بعد ذلك أخذ قيمة الإرجاع هذه، واتصل بها.

هذه هي الوظيفة التي ترجع دالة أخرى. name و value هي معلمات الوظيفة التي تم إرجاعها.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top