سؤال

هذا الأسبوع على comp.lang.python، كان قطعة من الكود "مثيرة للاهتمام" نشر بواسطة ستيفن d'Aprano كإجابة نكتة لسؤال الواجبات المنزلية. ها هو:

class MultiplierFactory(object):
    def __init__(self, factor=1):
        self.__factor = factor
    @property
    def factor(self):
        return getattr(self, '_%s__factor' % self.__class__.__name__)
    def __call__(self, factor=None):
        if not factor is not None is True:
            factor = self.factor
        class Multiplier(object):
            def __init__(self, factor=None):
                self.__factor = factor
            @property
            def factor(self):
                return getattr(self,
                '_%s__factor' % self.__class__.__name__)
            def __call__(self, n):
                return self.factor*n
        Multiplier.__init__.im_func.func_defaults = (factor,)
        return Multiplier(factor)

twice = MultiplierFactory(2)() 

نحن نعلم ذلك twice هو ما يعادل الجواب:

def twice(x):
    return 2*x

من الأسماء Multiplier و MultiplierFactory نحصل على فكرة ما تفعله الرمز، لكننا لسنا متأكدين من المخادين الدقيقين. دعونا تبسيط ذلك أولا.

منطق

if not factor is not None is True:
    factor = self.factor

not factor is not None is True أي ما يعادل not factor is not None, ، وهو ايضا factor is None. وبعد نتيجة:

if factor is None:
    factor = self.factor

حتى الآن، كان ذلك سهلا :)

الوصول إلى السمة

نقطة أخرى مثيرة للاهتمام هي الغريب factor الملحق.

def factor(self):
    return getattr(self, '_%s__factor' % self.__class__.__name__)

أثناء تهيئة MultiplierFactory, self.__factor تم تعيين. ولكن في وقت لاحق، الوصول إلى التعليمات البرمجية self.factor.

ثم يبدو أن:

getattr(self, '_%s__factor' % self.__class__.__name__)

يفعل بالضبط "self.__factor".

هل يمكننا دائما الوصول إلى السمات في هذه الأزياء؟

def mygetattr(self, attr):
    return getattr(self, '_%s%s' % (self.__class__.__name__, attr))

تغيير ديناميكيا تواقيع وظيفة

على أي حال، في هذه المرحلة، هنا هو التعليمات البرمجية المبسطة:

class MultiplierFactory(object):
    def __init__(self, factor=1):
        self.factor = factor
    def __call__(self, factor=None):
        if factor is None:
            factor = self.factor
        class Multiplier(object):
            def __init__(self, factor=None):
                self.factor = factor
            def __call__(self, n):
                return self.factor*n
        Multiplier.__init__.im_func.func_defaults = (factor,)
        return Multiplier(factor)

twice = MultiplierFactory(2)() 

الكود هو تنظيف تقريبا الآن. الخط الوحيد المحير، ربما، سيكون:

Multiplier.__init__.im_func.func_defaults = (factor,)

ما في هناك؟ نظرت إلى Datamodel Doc., ، ووجدت ذلك func_defaults كنت "Tuple يحتوي على قيم الوسيطة الافتراضية لهذه الوسائط التي لها إعدادات افتراضية، أو لا شيء في حالة عدم وجود قيمة افتراضية". هل نحن فقط تغيير القيمة الافتراضية factor حجة في __init__ هنا؟ سيكون رمز الناتج بعد ذلك:

class MultiplierFactory(object):
    def __init__(self, factor=1):
        self.factor = factor
    def __call__(self, factor=None):
        if factor is None:
            factor = self.factor
        class Multiplier(object):
            def __init__(self, innerfactor=factor):
                self.factor = innerfactor
            def __call__(self, n):
                return self.factor*n
        return Multiplier(factor)

twice = MultiplierFactory(2)() 

مما يعني أن تحديد القيمة الافتراضية ديناميكيا كانت مجرد ضوضاء عديمة الفائدة Multiplier لا يطلق عليه أبدا بدون معلمة افتراضية، الصحيح?

وربما يمكننا تبسيطها إلى:

class MultiplierFactory(object):
    def __init__(self, factor=1):
        self.factor = factor
    def __call__(self, factor=None):
        if factor is None:
            factor = self.factor
        def my_multiplier(n):
            return factor*n
        return my_multiplier

twice = MultiplierFactory(2)() # similar to MultiplierFactory()(2)

صيح؟

ولأولئك الذين يروجون "هذا ليس سؤالا حقيقيا" ... اقرأ مرة أخرى، أسئلتي في غامق + مائل

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

المحلول

q1. هل يمكننا دائما الوصول إلى السمات في هذه الأزياء؟

ج: لا. إنها فقط تلك السمات التي تبدأ بتشكيل السفلات المزدوجة. يتم تبديدهم بهذه الطريقة، لمنع الوصول العرضي / الغالق من خارج الفصل.

q2: هل نحن فقط تغيير القيمة الافتراضية لوسيطة عامل في __init__ هنا؟

ج: نعم.

q2: أليس كذلك؟

حق.

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