2013-11-14 2 views
0

확률 분포를 나타 내기 위해 (간체화 된) 클래스를 작성하고 있습니다. 내가 원하는 것은 유형과 매개 변수만으로 오브젝트 분배를 초기화하고 유형에 따라 할당 된 일부 기능이 있다는 것입니다. I 타입 (dist.pdf) 나는 그 람다 함수 얻을 수 있지만이 기능을 실행하면, dist.pdf (4.0) TypeError가 말을 실행하면 이제클래스 정의의 유형 오류

functions = {'exp':{ 
       'parameters': ['l'], 
       'pdf': lambda x,p: exp(x/p[0])*p[0], 
       'cdf': lambda x,p: 1-exp(x/p[0]) }, 
      'uniform':{ 
       'parameters': ['x1','x2'], 
       'pdf': lambda x,p: 1/(p[1]-p[0]), 
       'cdf': lambda x,p: (x-p[0])/(p[1]-p[0]) } 
      } 
class Distribution: 
    def __init__(self,dist_type,**parameters): 
     self.dist_type = dist_type 
     self.parameters = parameters 
     self.p = [ self.parameters[z] for z in functions[dist_type]['parameters'] ] 

     for key,val in functions[dist_type].items(): 
      if key == 'parameters': 
       pass 
      else 
       setattr(self, key, lambda x:val(x,self.p)) 


dist = Distribution('exp',l=3.5) 

는 '리스트'객체는 아니다 호출 가능.

사이드 노트에서 코드의 스타일/복잡성은 어떻습니까?

답변

1

파이썬의 범위 지정 문제에 물린 것입니다. 이 라인에서 :

setattr(self, key, lambda x:val(x,self.p)) 

vallambda가, 결국은 lambda를 정의 할 때 참조하는 객체라는 하지 않는 경우 조회됩니다 단지 이름입니다. 한 가지 해결 방법은 이 정의시를 바인딩되는 기본 값으로 두 번째 인수를 추가하는 것입니다

for key,val in functions[dist_type].items(): 
    if key == 'parameters': 
     pass 
    else: 
     setattr(self, key, lambda x,val=val: val(x,self.p)) 
내가 같이 사전에 서브 클래스 정의를 포함하려고 것을 모르는

너 시도하고있어. 이

exp_dist = make_distribution('exp') 
d = exp_dist(l=3.5) 
d.pdf(4.0) 
이러한 솔루션의 복잡성은 사용 사례에 따라

같은 뭔가 적절한 클래스를 생성 할 수있는 사용할 수있는 여러 가지 기술 (클래스 공장, 메타 클래스)을, 그리고 당신이 선택한 이유 functions 사전을 구성하는 네가 가진 방식이야. 예를 들어, 명명 된 매개 변수는 pdfcdf 함수에는 필요하지 않지만 내성 검사에 유용 할 수 있습니다. 또한 생성 된 모든 배포판에 정확하게 두 가지 방법 인 pdfcdf이 있다고 가정하거나 인스턴스에 추가 메서드가있을 수 있다고 가정 할 수 있습니까? 나는() dist.pdf를 실행하려고하면

+0

감사합니다. 언급 한 기술을 확인해 보겠습니다. 나는 그 함수가 매개 변수 세트에 의존하는 클래스를 원한다. 필자가 필요로하는 매개 변수가 'dist_type'에 의존하기 때문에 더 복잡 해졌다. 그래서 사전을 사용했다. – chuse

-3

, 내가 얻을 : 나는 자기에 너무 많은 않은 setattr에 조금 주저하지만

Traceback (most recent call last): 
    File "./dist-pdf", line 30, in <module> 
    dist.pdf() 
TypeError: <lambda>() missing 1 required positional argument: 'x' 

코드 스타일, 합리적인 보인다. 또한 변수 이름은 좀 더 설명하기 쉽지만, 수학을하기 때문에 그럴 수도 있습니다. 종종 수학은 빈약 한 변수 이름을 사용합니다.

2

당신은 폐쇄의 희생자입니다. 다음은 가능한 수정입니다 : 사고로

for key,val in functions[dist_type].items(): 
     if key == 'parameters': 
      pass 
     else: 
      def f(x, dist=val): 
       return dist(x, self.p) 
      setattr(self, key, f) 

이 반복 동안 val의 마지막 값은 list 될 일이 당신의 functions DICT의 "parameters" 요소였다. val은 람다에 의해 캡처되었으므로 나중에 호출 할 때 ['l'](4.5, 3.5) - ['l']"parameters" 항목의 값으로 호출하려고 시도합니다.

class Distribution: 
    def __init__(self,dist_type,**parameters): 
     self.dist_type = dist_type 
     self.parameters = parameters 
     self.p = [self.parameters[z] for z in functions[dist_type]['parameters']] 

     for key,val in functions[dist_type].items(): 
      if key == 'parameters': 
       pass 
      else: 
       setattr(self, key, lambda x: val) 


dist = Distribution('exp',l=3.5) 

print dist.pdf(4.0) 

출력 :

['l']

인수의 기본 값으로 속임수가 작동하는 이유는,이 함수의 정의시 평가되는 점입니다하지

이 조각으로 입증 할 수 언제 부르는지.

관련 문제