2009-09-30 6 views
2

이런 식으로 뭔가를 할 어쨌든 거기 방법에 액세스 할 객체의 클래스를 확인할 수 있습니다 ?파이썬은

편집 : 결국

, 나는 제안의 일부를 기반으로 이것을 함께 넣어 :

그것은 제공하는 모든 이유에 대해 완벽 하진
import inspect 
... 
def check_caller(self, klass): 
    frame = inspect.currentframe() 
    current = lambda : frame.f_locals.get('self') 
    while not current() is None: 
     if isinstance(current(), klass): return True 
     frame = frame.f_back 
    return False 

하지만, 감사 응답 : 그들은 큰 도움이되었습니다.

+2

당신은 서로를 호출하는 많은 클래스가 있다고 말씀하셨습니다. 어떤 클래스가 무엇을 할 수 있는지를 제한하는 "보안"을 삽입하려고하는 것 같습니다. 이것은 일반적으로 나쁜 생각입니다. 왜 이렇게하고 싶은지 설명해주십시오. 어쩌면 누군가가 유스 케이스에 대한 더 나은 해결책을 제시 할 수 있습니다. –

+2

하시는 일이 울어도 – Triptych

답변

6

이 방법, 당신이 할 수있는 예, 이전 프레임에보고하고, 지역 주민의 self을 따기에 의해.

class Reciever: 
    def themethod(self): 
     frame = sys._getframe(1) 
     arguments = frame.f_code.co_argcount 
     if arguments == 0: 
      print "Not called from a method" 
      return 
     caller_calls_self = frame.f_code.co_varnames[0] 
     thecaller = frame.f_locals[caller_calls_self] 
     print "Called from a", thecaller.__class__.__name__, "instance" 

ŷglck와 마찬가지로 작동하지만 작동합니다. 이제 왜 이렇게하고 싶은지에 대한 또 다른 질문입니다. 더 좋은 방법이 있다고 생각합니다. A의 전체 개념은 B를 호출하는 것이 허용되지 않으므로 실수 일 수 있습니다.

class A(object): 
    def foo(self): 
     # do stuff 

class B(A): 
    def foo(self): 
     raise NotImplementedError 

class C(A): 
    pass 

을 ...하지만 당신이해야 할 노력하고 정확히 모른 채 말을 어려운이 같은

+2

은 메소드의 최상위 레벨 호출, 자유 함수에서의 메소드 호출,'self'에 대한 다른 이름 사용 ('self'의 사용은 단지 관습입니다) 등 많은 경우에 실패합니다. – nosklo

+0

예. 호출자를 전달하는 것이 더 나은 해결책이라는 데 동의합니다. –

+1

호출자가'frame.f_code.co_argcount'의 인수를 가지고 있는지와'frame.f_code.co_varnames [0]'의 첫 번째 인수의 이름을 볼 수 있습니다. –

4

호출자는 항상 A의 인스턴스입니다. B 메서드 내에서 호출하는 것은 변경되지 않습니다. 즉, Insiode B.foo, refA의 인스턴스이므로 A에 대한 호출 인 경우 ref.foo()을 호출하면 B이 호출되지 않습니다 (최상위 레벨에서 발생할 수 있음).

A가 self에 대한 참조를 전달하여 A가 B인지 여부를 확인할 수있는 유일한 정상적인 방법입니다. 발신자 가정

class A(object): 
    def foo(self, caller=None): 
     if isinstance(caller, B): 
      print "B can't call methods in A" 
     else: 
      print "Foobar" 

class B(object): 
    def foo(self, ref): ref.foo(self) 

class C(object): 
    def foo(self, ref): ref.foo(self) 

a = A(); 
B().foo(a) # Outputs "B can't call methods in A" 
C().foo(a) # Outputs "Foobar" 
a.foo()  # Outputs "Foobar" 
+0

투명하게 보이려고. 메소드의 수가 크게 증가하면 관리하기가 어렵습니다. – blakef

+6

@blakef : 나는 이것이 왜 나쁜 생각인지에 대한 나의 질문을 편집했다. 이 호출은 최상위 레벨에서 발생할 수 있습니다. 전화가 어디서 발생했는지 탐지하려고 시도하는 것은 잘못 설계되었습니다. 대신 ** 왜 지구상에서 ** 한 클래스의 메소드가 다른 클래스의 메소드를 호출하지 못하도록하고 싶은지 공유해야합니다. – nosklo

+0

질문은 결국 학문적으로되었습니다. 당신의 솔루션이 더 나은 접근 방법이지만, 나는 호출자의 코드를 포함시키지 않고 어떻게 할 수 있는지에 관심이있다. – blakef

0

뭔가 더 나은 당신의 요구를 충족 할 수 있습니다.