2016-11-23 1 views
2

파이썬 슬라이스 객체에 일부 메타 데이터를 포함하고 슬라이스의 각 요소 색인을 나타내는 변수를 추가하고 싶습니다. 메타 데이터는 조각이 검색중인 각 요소에 레이블을 지정하는 데 사용됩니다. 사용할 수있는 다른 레이블이 붙은 데이터 구조가 있다는 것을 알고 있습니다 만, 프로젝트 조각에는 numpy 배열에 대한 일종의 첨자로 미리 정의되어 있으며 여러 위치에서 다시 사용됩니다. 그래서, 나에게 이것은 이것을 통합하는 방법을 찾는 것이 합리적입니다.파이썬 슬라이스 객체 또는 하위 클래스를 모방 할 수 있습니까?

하위 분류는 slice으로 생각했지만 명확하게 연결된 질문의 대답으로 명확하게 설명 된 subclassed이 될 수 없습니다. 그 이후로 어떤 것이 바뀌 었습니까?

sub = Subscript(0, 5, labels=['s0', 's1', 's2', 's3', 's4']) 

list(range(10))[sub] # [0, 1, 2, 3, 4] 

range(10)[sub.s0] # 0 

없이 할 수있는 방법이있다 :

class Subscript: 
    def __init__(self, start, stop, step=None, labels=None): 
     self.labels = labels 
     self.slc = slice(start, stop, step) 

     for i, l in zip(range(start, stop, step), labels): 
      setattr(self, l, i) 

과 같이 사용할 수 있습니다 : 내가하고 싶은 무엇

처럼 보이는 클래스를 만드는 것입니다 슬라이스를 반환하는 방법을 __call__ 추가해야합니까? 어레이와리스트가 sub에서 __getitem__까지 걸리므로 어떻게해야할지 모르겠다. 나는이 정보를 slice으로 원숭이 패치 할 수 있을지는 모르지만 이런 종류의 일이 수업에서 할 수 있는지 궁금해하고 있습니다.

현재, 내가 좋아하는 별도 슬라이스와 슬라이스 요소를 정의하고있다 :

sub = slice(0, 5) 

s0, s1, s2, s3, s4 = range(5) 

그러나이 방법은 더 힘들어 키 첨자 요소의 조합이 경우에 사전인가로 다차원 배열의 출력을 처리 할 수 ​​있습니다 1 sub 이상이고 값은 1d 배열입니다.

+1

속성을 동적으로 설정하는 데'exec'을 사용하지 마십시오. setattr이 훨씬 더 적합합니다. 또한'__init__'에는'self'가 없습니다. – vaultah

+0

고마워! 그 중 하나를 잊어 버렸습니다 – pbreach

답변

1

아니요, slice 개체는 여전히 하위 클래스로 분류 될 수 없습니다. 그들은 유형과 마찬가지로 적절한 Py_TPFLAGS_BASETYPE이 거기에 or 에드 것

Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 

객체가 기본 클래스의 역할을 할 수 있도록하려면 : 파이썬 (3.7) 지점의 기본에 PySlice_Type에 정의 된이 기반 on the flags를 말하는거야 정의 된. 로 예를 들어 lists 촬영, 자신의 플래그가 정의되어 있습니다 :

Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | 
    Py_TPFLAGS_BASETYPE | Py_TPFLAGS_LIST_SUBCLASS,   /* tp_flags */ 

나머지를 무시 Py_TPFLAGS_BASETYPE이는 기본 클래스 역할을 할 수있는 | '편이다.

문서의 어딘가에서 언급 한 내용을 찾을 수 없다는 판단에 따라 현재 실현되지 못하는 구현 세부 사항을 말하고 싶습니다. 내가 당신을 믿는 유일한 길은 일 수도 있고 일 수도 있습니다. C으로 떨어 뜨리고 거기서 수업을하는 것입니다. 나는 단지 (목록 동일한 기능을 수행 할 수있다) 이러한 유형의 개체에 조각을 전달하려고 노력했기 때문에 numpy.ndarray 서브 클래스되어 일을 결국, 다음 그래서 __getitem__을 재 구현 무엇

+0

고마워요. 내가 생각했던 것보다 더 까다 롭다. 원숭이 패치 '슬라이스'조차도 이런 이유로 할 수있는 것처럼 보이지 않습니다. 방금 대신'AttributeError'를 얻습니다. – pbreach

+1

예. 올바르게 기억한다면,'list .__ getitem__' (그리고 다른 컨테이너도 비슷하게 행동해야합니다.)'slice' 타입을 전달 된 인자 또는'int' 값으로 명시 적으로 검사합니다. 적절한'int'를 리턴하는'__index__' 메소드). 당신이 할 수있는 최선의 방법은 실제로'slice's처럼 행동하는 커스텀 객체를 허용하는 새로운'list' 하위 타입을 생성하는 것입니다 (composition에 의해 아마?). –

+0

'list' 대신에'numpy.ndarray'를 서브 클래 싱하여 제외하고 제안한 것을 기본적으로 수행하고 여기에 게시했습니다. 나를 위해 일한다! – pbreach

1

하는 Subscript 목적은 다음에 전달되는 경우 슬라이스는 먼저 부모 메서드로 전달되기 전에 추출됩니다.

처럼 보이는 :

import numpy as np 

class SubArray(np.ndarray): 
    def __new__(cls, input_array, subs=None): 
     obj = np.asarray(input_array).view(cls) 
     obj.subs = subs 
     return obj 

    def __getitem__(self, *args): 
     args = tuple([a.slc if isinstance(a, SubRange) else a for a in args]) 
     return super().__getitem__(*args) 

    def __array_finalize__(self, obj): 
     if obj is None: 
      return 
     self.subs = getattr(obj, 'subs', None) 


class Subscript: 
    def __init__(self, labels, bounds=None): 
     name, elements = labels 

     if bounds: 
      start, stop = bounds 
     else: 
      start, stop = 0, len(elements) 

     self.size = stop - start 
     self.slc = slice(start, stop) 
     self.labels = labels 
     self.name = name 
     self.elements = elements 

     for l, i in zip(labels, range(start, stop)): 
      setattr(self, l, i) 

그리고 다음과 같이 사용할 수 있습니다

sub = Subscript(('sub', ['s0', 's1', 's2', 's3', 's4'])) 

SubArray(np.arange(10), subs=sub)[sub] # SubArray([0, 1, 2, 3, 4]) 

SubArray(np.arange(10), subs=sub)[sub.s0] # 0 

이 내가 피하는 된 접근 방식에 훨씬 더 가까이 (즉 xarray 같은 것을 사용),하지만 결과는 여전히 기본적으로 numpy 배열 및 나를 위해 작동합니다.

관련 문제