2016-11-08 9 views
0

필자는 머리말을 디스크립터 개념으로 바꾸려고 노력하고 있으며 최근에는 성공하지 못했습니다. 이 article의 설명자를 어떻게 도왔으며 동시에 나 또한 혼란 스러웠습니다. 나는 m.x가 나는 기사"descriptors howto"기사에서의 설명자 예제 이해

세부 사항에 다음과 같은 성명에 의해 혼동하고 있기 때문에 내가이 고민하고있는 이유는 생각 def __get__(self, obj, objtype):

class RevealAccess(object): 
    def __init__(self, initval=None, name='var'): 
     self.val = initval 
     self.name = name 

    def __get__(self, obj, objtype): 
     print('Retrieving', self.name) 
     return self.val 

    def __set__(self, obj, val): 
     print('Updating', self.name) 
     self.val = val 

>>> class MyClass(object): 
...  x = RevealAccess(10, 'var "x"') 
...  y = 5 
... 
>>> m = MyClass() 
>>> m.x 
Retrieving var "x" 
10 

를 호출하는 이유는 여기에 이 예를 고민하고있다 호출은 obj가 객체인지 또는 클래스인지에 따라 달라집니다. 물체의 경우 기계류는 b.xtype(b).__dict__['x'].__get__(b, type(b))으로 변환하는 object.__getattribute__() 에 있습니다. 구현은 인스턴스 변수, 우선 순위가 아닌 데이터 기술자를 통해 인스턴스 변수를 통해 데이터 기술자 우선 순위를 부여하는 우선 순위 체인을 통해 작동하고,

를 제공하는 경우 어떻게 저자 확실하지 않다 __getattr__()에 가장 낮은 우선 순위를 할당 여기 개체 또는 클래스를 의미합니다. 객체는 클래스의 인스턴스를 의미합니까? 나는 우리가 instance.var 파이썬 내부적으로 instance.__dict__["var"]을 수행 할 때 그것을 찾지 못하면 class.__dict__["var"]을 수행한다는 것을 이해합니다. 나는 그 개념을 잃어 버렸습니다. 누구나이 예제가 어떻게 작동하는지 조금 설명 할 수 있을까요? def __get__(self, obj, objtype):의 정의는 m.x과 어떻게 관련이 있습니까? 아무도이 문제를 해결할 수 있다면 매우 감사 할 것입니다.

+0

매개 변수 이름'def __get __ (self, instance, owner)'를 사용하면 명확해질 수 있습니다. 'RevealAccess'는 기술자 클래스이고 MyClass는 소유자 클래스입니다. 클래스는 객체이므로,'owner'는 클래스 객체'MyClass'가됩니다. – cdarke

답변

2

예, 개체 작성자는 클래스가 아닌 인스턴스를 의미합니다. 이 구별은 디스크립터가 어디에 있는지에 따라 다르다. 기술자는 클래스에 정의되어 있으므로 클래스에서 해당 설명자 에 직접 액세스하면 해당 클래스의 인스턴스에서 해당 설명자에 액세스 할 때와 다른 경로가 이어집니다.

예에서 m은 인스턴스입니다. 이 인스턴스 자체에는 m ('x' in m.__dict__False)의 속성이 없습니다. 파이썬은 또한 해당 속성을 해결하기 위해 type(m)을보고 type(m)MyClass입니다. 'x' in MyClass.__dict__True이고 MyClass.__dict__['x'].__get__이 있으므로 파이썬은 해당 객체가 설명자임을 알게됩니다. 거기에 더 m.__dict__['x'] 없지만, 때문에

그래서, 그 방법은 type(m).__dict__['x'].__get__(m, type(m))로 이어지는 인수로 mtype(m)로 호출하는 type(m).__dict__['x'].__get__있다. 'x' in MyClass.__dict__ 사실이지만 MyClass.__dict__['x'].__get__하지이 존재 한 경우

(그래서 객체가 하지 기술자 객체입니다), 다음 MyClass.__dict__['x'] 직접 반환 된 것이다.

인스턴스 x 속성을 추가하려고하면 상황이 더욱 흥미로워집니다. 이 경우 MyClass.__dict__['x'].__set__ 또는 MyClass.__dict__['x'].__delete__이 존재하면 설명자를 데이터 설명자로 만드는 것이 중요합니다. 데이터 디스크립터는 동점의 경우 항상 승리합니다.따라서 MyClass.__dict__['x'].__get__중 하나 이상이MyClass.__dict__['x'].__set__ 또는 중 하나 이상인 경우 m.__dict__['x']도 존재하면 더 이상 중요하지 않습니다. 파이썬은 심지어 그것을 찾지 않을 것입니다.

그러나 클래스의 설명자 개체에 __set__ 또는 __delete__ 메서드가없는 경우 m.__dict__['x']이 반환되고 반환됩니다. 이 경우 디스크립터는 데이터가 아닌 일반 디스크립터이며 인스턴스 속성이 없어집니다.

마지막으로, 'x' in type(m).__dict__이 거짓 (클래스에 개체가없는 경우) 인 경우 m.__dict__['m']이 반환됩니다. 설명자 프로토콜은 클래스에있는 객체에만 적용되며 인스턴스의 속성에는 적용되지 않습니다.

+0

굉장 !! 이 문제를 해결해 주셔서 감사합니다. –

+0

x가 클래스 변수가 아닌 'MyClass'의 인스턴스 변수 인 경우 어떻게 되었을까요? (즉, m ('x'가 m .__ dict__이 True이면) '). –

+0

@JamesFranco : * 추가적으로'MyClass.x'가 있습니까? –

1

개체는 클래스의 인스턴스를 의미합니까?

예.

정의 def __get__(self, obj, objtype):m.x으로 어떻게 호출됩니까? 때문에 당신이 인용 한 문서를 말한다 단지 무엇을

:

객체의 경우는 기계 type(b).__dict__['x'].__get__(b, type(b))b.x 변환 object.__getattribute__()입니다.

object.__getattribute__m.x 뭔가를 할 때 발생하는 구현 메커니즘입니다. 그래서, 명시 적으로 :

m.x 
type(m).__dict__['x'].__get__(m, type(m)) 
MyClass.__dict__['x'].__get__(m, MyClass) 
RevealAccess(10, 'var "x"').__get__(m, MyClass) 

그래서 마지막 줄은 RevealAccess 클래스의 __get__ 메소드를 호출합니다.