2017-10-19 17 views
4

모든 기본 사용자 정의 __slots__ 속성의 목록을 반환해야하는 기본 클래스에 __dir__ 사용자 정의가 있습니다. 이것은 일반적으로 작동하지만 리턴하기 전에 결과에 sort을 수행하는 것처럼 보입니다. 그렇게하도록 프로그램하지는 않았지만 (나는 할당 된 것과 동일한 순서로 속성을 필요로합니다).사용자 정의 __dir __()은 알파벳순으로 정렬 된 속성 목록을 반환합니다.

예 :

class A: 
    __slots__ = ['b', 'a'] 

    def __dir__(self): 
     slot_attrs = [] 
     for parent_class in reversed(type(self).__mro__[:-1]): 
      for attr in parent_class.__slots__: 
       slot_attrs.append(attr) 
     for attr in self.__slots__: 
      slot_attrs.append(attr) 
     return slot_attrs 


class B(A): 
    __slots__ = ['c', 'd'] 
    pass 


class C(B): 
    __slots__ = [] 
    pass 


class D: 
    __slots__ = ['b', 'a'] 

    def slots(self): 
     slot_attrs = [] 
     for parent_class in reversed(type(self).__mro__[:-1]): 
      for attr in parent_class.__slots__: 
       slot_attrs.append(attr) 
     for attr in self.__slots__: 
      slot_attrs.append(attr) 
     return slot_attrs 


class E(D): 
    __slots__ = ['c', 'd'] 
    pass 


class F(E): 
    pass 

slots()__dir__()의 출력 IMO 동일이어야한다.

대신, 이런 일이 발생 : dir()를 사용하는 경우

>>>c = C() 
>>>f = F() 

>>>print(dir(c)) 
['a', 'b', 'c', 'd'] 
>>>print(f.slots()) 
['b', 'a', 'c', 'd', 'c', 'd', 'c', 'd'] 

내가의 종류, 그것은 순으로 출력을 정렬하는 것을 이해할 수있다 -이 documented in the docs입니다. 그러나 버그메서드를 정의 했음에도 불구하고 출력을 정렬하는 버그 또는 적어도 예기치 않은 동작으로 보입니다.

두 번째 출력은 단순히 게임에서 완전히 벗어납니다. dir은 코드가 동일하지만 slots()을 호출하면 중복 값을 반환하기 때문에 중복 출력을 피하기 위해 일종의 필터 (아마도 set)를 사용합니다.

나는 그게 어째서 그 일을하는지 이해하지 못한다. B) 도대체 어쨌든 dir은하고있다.

여기에 포인터가 있습니까?

편집 : - 그러므로 그 클래스가 두 번 포함되어
두 번째 경우는 __mro__ solved-이다는 호출 측의 클래스뿐만 아니라 그것을 상속하는 모든 클래스가 포함되어 있습니다. 즉 :

>>>F.__mro__ 
(<class '__main__.F'>, <class '__main__.E'>, <class '__main__.D'>, <class 'object'>) 

편집 2 : 음모가 두껍게
.

>>Couldn't __dir__ also be allowed to return a tuple? 
no, because tuples are not sortable, and i don't want to 
over complicate the c-side code of PyObject_Dir. 
having __dir__ returning only a list is equivalent to 
__repr__ returning only strings. 

__dir__이 구현되기 전에에서, C 소스 코드에서 발생하는 일 것으로 보인다 : 코멘트에 언급 된 문제는이 문제의 근원에 작은 조금 더 많은 빛을 흘렸다.

편집 3 :
나는 issue on python's bug tracker을 열었습니다. 합의가 무엇인지 보자. 그러나, 나는 이것이 전혀 없으면 backburner에 놓이게 될 것이라고 기대한다. 왜냐하면 dir()은 주로 afle과 같은 검사를 위해 설계된 afaik이기 때문이다.

+0

모든 고유하지 않은 요소는 제거됩니다. 'dir'은 커스텀 메소드를 호출 할 뿐이지 만, 문서를 편집 할 수 있도록 사후 처리합니다. –

+0

사실, 이드는 그들을 지우지 못합니다 - 방금 테스트 해봤습니다.나는'F'에서'__slots__'을 두 번 추가했습니다. – nlsdfnbch

+0

여전히 예기치 않은 동작으로 보입니다. 'dir()'이'__dir __()'을 호출하면, 내가 말한 것처럼 그것을 할 수 있기를 기대하며, 그 위에 무언가를 숨기지 않습니다. – nlsdfnbch

답변

1

issue opened on the Python bug tracker에 따라 경찰 : 당신이 파이썬에서 같은 이름의 메소드에 액세스 할 수 없기 때문에

https://docs.python.org/3/library/functions.html#dir also states that "The resulting list is sorted alphabetically." The section has an example where __dir__ returns an unsorted list but dir() returns a sorted list: 

      class Shape: 

...  def __dir__(self): 
...   return ['area', 'perimeter', 'location'] 

      s = Shape() 
      dir(s) 

['area', 'location', 'perimeter'] 

Since the primary purpose of dir() is convenient use for humans, sorting makes perfectly sense. If you need tight control over order of values, you should make your object iterable instead or provide another method. 

Several dunder methods perform some sort of post-processing or post-check: 

      class Example: 

...  def __bool__(self): return 2 
... 

      bool(Example()) 

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: __bool__ should return bool, returned int 

      class MyInt(int): 

...  pass 
... 

      type(MyInt(1)) 

<class '__main__.MyInt'> 

      class Example: 

...  def __int__(self): 
...   return MyInt(1) 
... 

      int(Example()) 

1 

      type(int(Example())) 

<class 'int'>