문제

이번 주에 comp.lang.python에서 "흥미로운"코드는 게시 Steven 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 였다 "기본값이있는 인수에 대한 기본 인수 값을 포함하는 튜플 또는 인수가 기본값이없는 경우 없음". 우리는 단지 기본값을 변경하고 있습니까? 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)

옳은?

그리고 "이것은 진짜 질문이 아닙니다"라는 서두르는 사람들을 위해 ... 다시 읽으십시오. 내 질문은 Bold+Italic입니다.

도움이 되었습니까?

해결책

Q1. 이 방식으로 항상 속성에 액세스 할 수 있습니까?

A : 아니요. 이중 밑줄로 시작하는 속성 일뿐입니다. 그들은 수업 외부에서 우발적 인 접근/재정의를 방지하기 위해 그런 식으로 난독 화됩니다.

Q2 : 요인 인수에 대한 기본값을 변경하고 있습니까? __init__ 여기?

A : 그렇습니다.

Q2 : 맞습니까?

오른쪽.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top