2011-09-22 2 views
6

프로그래머가 던져 버릴 수도있는 장애물에도 불구하고 Python 인스턴스를 절대적으로 검사 할 방법이 있는지 궁금합니다. 의도하지 않은 참조 루프 및 열린 리소스와 같은 문제를 디버깅하는 데 도움이 될 수 있기 때문입니다. 파일.클래스에 __dict__ 변수가 있으면 obj .__ dict__를 검사 할 수 있습니까?

더 간단한 예제는 프로그래머가 자신의 클래스 뒤에 keys()을 숨겨둔 경우 dict 서브 클래스의 키를 어떻게 볼 수 있습니까? 그 주위에 방법은 수동으로 대신 상속 메소드의 서브 클래스의 버전을 불러올 수 있습니다의 dictkeys() 메소드를 호출하는 것입니다 : 내가 상관없이, 인스턴스의 __dict__ 볼 수있는 방법,

# Simple example of getting to the real info 
# about an instance 

class KeyHidingDict(dict): 
    def keys(self): 
     return [] # there are no keys here! 

khd = KeyHidingDict(a=1, b=2, c=3) 
khd.keys()  # drat, returns [] 
dict.keys(khd) # aha! returns ['a', 'b', 'c'] 

이제 내 실제 질문은 무엇 프로그래머가 나 한테 숨길 수 있었을거야? 그들이 __dict__ 클래스 변수를 설정하면 그 클래스에서 상속 물건의 실제 __dict__ 그림자 같다 :

# My actual question 

class DunderDictHider(object): 
    __dict__ = {'fake': 'dict'} 

ddh = DunderDictHider() 
ddh.a = 1 
ddh.b = 2 
print ddh.a  # prints out 1 
print ddh.__dict__ # drat, prints {'fake': 'dict'} 

당신이 볼 실제 속성을 설정하고 점점 방해 할 수 __dict__에 대한이 거짓 값은하지 않습니다 그러나 ab을 숨기고 fake을 개체의 인스턴스 변수로 표시하여 오디 쉬 코드 dir()을 오도 할 수 있습니다.

내 목표는 클래스 인스턴스 집합이 너무 많은 메모리를 차지하거나 많은 파일을 열어 놓은 이유에 대해 궁금해 할 때 클래스 인스턴스를 "내 정보"로 볼 수있게 해주는 도구를 작성하는 것입니다. 위의 상황이 극도로 고안되었지만 주위를 둘러싼 방법을 찾으면 도구의 모든 작업 시간이 "보고있는 수업에 이상이없는 한 위대한 작품"이라고하는 대신 항상 작업 할 수 있습니다.

나는 포위 하듯이 같은으로 __dict__을 잡을 수있을 것이라고 생각했다 :

dict_descr = object.__dict__['__dict__'] 
print dict_descr(ddh, DunderDictHider) 

그러나 object에는 __dict__ 설명자가 없음이 밝혀졌습니다. 대신, subtype_dict() C 함수는 프로그래머가 생성하는 object의 각 하위 클래스에 개별적으로 첨부 된 것처럼 보입니다. 디스크립터를 이름을 지정하거나 가져올 수있는 중심적인 방법이 없으므로 클래스를 숨기는 객체에 수동으로 적용 할 수 있습니다.

의견이 있으십니까? :)

+0

추가 생각해 주셔서 감사합니다. 따라서 상속 계층 구조'object' →'A' →'B'에서 객체 B가 인스턴스의'__dict__' 속성을 숨기는 경우에 한 가지 방법이 있습니다. 그러나 오해의 소지가있는'__dict__' 클래스 속성을 정의하는 클래스 'A'라면 당신의 생각이 도움이되지 않는다는 점을 고치고 있습니까? –

답변

0

이 하나가이 항목의 여룹 대답을 기반으로합니다 : 당신은 당신이 메타 클래스와 무엇을 찾고 있는지 달성 할 수 What is a metaclass in Python?

.

먼저 당신은 메타 클래스를 만들어야합니다

def test_metaclass(name, bases, dict): 
    print 'The Class Name is', name 
    print 'The Class Bases are', bases 
    print 'The dict has', len(dict), 'elems, the keys are', dict.keys() 

    return dict 

물론 인쇄 necessery 수 없습니다.

The Class Name is DunderDictHider 
The Class Bases are (<type 'object'>,) 
The dict has 3 elems, the keys are ['__dict__', '__module__', '__metaclass__'] 
{'__dict__': {'fake': 'dict'}, '__module__': '__main__', '__metaclass__': <function test_metaclass at 0x1001df758>} 

때마다 : 이제 repr(DunderDictHider)

출력 (print repr(DunderDictHider) 라인) 모든 초기화 elems에 베풀어 액세스 할 수

class DunderDictHider(object): 
    __metaclass__ = test_metaclass 
    __dict__ = {'fake': 'dict'} 

:

은 그럼 새 DunderDictHider을 소개하자 시도해 볼 수 있습니다

if '__dict__' in repr(DunderDictHider) 

이 클래스가 __dict__을 숨기려고하는지 여부를 알 수 있습니다. repr 출력은 문자열이라는 것을 기억하십시오. 그것은 더 잘할 수 있지만 그 자체가 아이디어입니다. 내가 행복 해요 확실하지 않다

+0

기능이라면 메타 클래스라고 부르는 것이 적절하지 않다고 말합니다. 확실히 유효하지만 클래스 *는 아닙니다. –

+0

약간 혼란 스러울 수도 있습니다. 제 질문은 다른 프로그래머가 작성한 임의의 클래스에서 상속 받고 내성을 어렵게 만드는 기술을 피할 수는 없다는 (a) 객체 인스턴스의 상태를 검사하는 것입니다. 하지만 : (a) 답변에 객체 인스턴스가 없습니다. (b) 프로그래머가 작성한 클래스를 제어하지 않으면 어떻게 메타 클래스를 제어 할 수 있습니까? –

1

이 얼마나 간단 :

>>> class DunderDictHider(object): 
...  __dict__ = {'fake': 'dict'} 
... 
>>> ddh = DunderDictHider() 
>>> ddh.a = 1 
>>> ddh.b = 2 
>>> 
>>> print ddh.a 
1 
>>> print ddh.__dict__ 
{'fake': 'dict'} 

문제는 클래스가 바람을 피우고 있다는 것입니다? 고쳐!

>>> class DictUnhider(object): 
...  pass 
... 
>>> ddh.__class__ = DictUnhider 
>>> print ddh.a 
1 
>>> print ddh.__dict__ 
{'a': 1, 'b': 2} 

그리고 거기에 있습니다. 클래스가 슬롯을 정의하는 경우에는 완전히 실패합니다.

>>> class DoesntHaveDict(object): 
...  __slots__ = ['a', 'b'] 
... 
>>> dhd = DoesntHaveDict() 
>>> dhd.a = 1 
>>> dhd.b = 2 
>>> 
>>> print dhd.a 
1 
>>> dhd.__class__ = DictUnhider 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: __class__ assignment: 'DoesntHaveDict' object layout differs from 'DictUnhider' 
>>> 
+0

'__slots__'는 여전히 같은 이름의 정상적인 기본 슬롯으로 작동하는'__dict__ '을 정의 할 수 있습니다. 또한 클래스에 실제 슬롯 설정이 없더라도'__slots__' var를 숨길 수 있습니다. – SingleNegationElimination

+0

전체적인 요점은 객체를 변경하지 않고 객체를 검사하는 것이었기 때문에 클래스를 조정할 생각을 이미 버렸습니다. 객체를 검사 할 때 동시에 객체를 사용할 수있는 다른 스레드가없는 경우에도 마찬가지입니다 ,이 솔루션은 전체 객체 그룹의 '__class__'을 전환해야하지만 리소스와 열린 파일을 사용할 수 있어야합니다. 그러나 나는이 가능성을 실제로 무시해야하는지에 대해 더 생각할 것이다. 흠. –

관련 문제