난독 화 된 다중 기능이있는 데시퍼
-
18-09-2019 - |
문제
이번 주에 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 : 맞습니까?
오른쪽.