2013-08-19 2 views
0

Укороченный вариант:Переходя ломтиков произвольных функций

Я только что прочитал о расширенном нарезку и узнал, что можно передать кортеж ломтиков в __getitem__:

a[::3, 1::3] 

Тем не менее, вы не можете передать ломтики до произвольных функций (поправьте меня, если я ошибаюсь), следовательно, это не получится:

f(::3, 1::3) 

как-то громоздкого е обходной путь зовут slice:

f(slice(None, None, 3), slice(1, None, 3)) 

1. Есть ли порезать литералы (постижения) как [] для списков, {} для словарей и наборов или () для генераторов и кортежей? (Возможно, <start, end, step> или что-то еще)

2. Можно ли передавать фрагменты произвольным функциям в аккуратной ноте фрагмента?


Длинная версия (TL; DR):

Если я хочу, чтобы сливаться через различные кусочки из списка, то есть найти первый элемент из этих кусочков, которые не оценить в False, это было бы неплохо, если бы я смог передать известную и очень краткую нотацию к этой функции. Теперь решение может быть следующим, но я не уверен, если это опрометчиво:

#! /usr/bin/python3.3 

class Array(list): 
    class Coalescer: 
     def __init__(self, array): 
      self.array = array 

     def __getitem__(self, slices): 
      if not isinstance(slices, tuple): 
       slices = (slices,) 
      for s in slices: 
       for e in self.array[s]: 
        if e: return e 
      return None 

    @property 
    def coalesce(self): 
     return Array.Coalescer(self) 

a = Array ([0, 0, 2, 0, 3, 4, 0, 5, 6]) 

print(a.coalesce[:]) #2 
print(a.coalesce[::3]) #None 
print(a.coalesce[1::3]) #3 
print(a.coalesce[::3, 1::3]) #3 
a [6] = 42 
print(a.coalesce[::3, 1::3]) #42 

ИМХО, это более читаемым, чем a.coalesce(slice(None, None, 3), slice(1, None, 3)) или даже coalesce(a, slice(None, None, 3), slice(1, None, 3)).

3. Является ли это жизнеспособным вариантом или плохим примером того, как не использовать __getitem__?

4. Есть ли PEP или другой документ, который дает рекомендации, когда и как перезаписывать __getitem__, и что еще более важно, когда нет и как нет?

5. Что было бы, по вашему мнению, наиболее подходящим способом реализации функции, которая объединяется по упорядоченному списку срезов?

спасибо.

+0

Возможно, вы могли бы просто использовать NumPy? Или, если вы настаиваете на сворачивании своих собственных, одолжите идею объектов вида. –

+0

@JanneKarila Спасибо, Янне. Существуют ли литералы для фрагментов или возможно передать срезы (в известной ноте среза) произвольным функциям с помощью NumPy? Возможно, вы могли бы написать ответ, объясняющий, как NumPy обращается к этим двум темам. – Hyperboreus

+0

Вы можете написать функцию 'coalesce', которая используется как' coalesce (a [:: 3]) ' –

ответ

2

Сначала я хотел бы предложить использовать NumPy или панда и создание функции, которая бы просто получить, а @JanneKarila предложил coalesce(a[::3])

Но если вы должны создать объект, который может быть нарезан и имеют функции, которые также должны реализовать ломтиками я бы следовал подходу, который сделала библиотека Pandas.

  1. У вас есть DataFrame (не заморачиваться с именами) объектом df, и вы можете сделать нарезку на него с помощью df[1:3]

  2. Но если вы хотите какую-то особая нарезки, то они реализовали еще один объект, который имеет ссылка на первую, которая также реализует срез и доступна как атрибут первого объекта df.ix[3:5].

Ваша реализация будет выглядеть примерно так:

class SpecialSlicer(object): 
    def __init__(self, obj): 
     self.obj = obj 

    def __getitem__(self, ...): 
     return sefl.obj[...] 

class Array(object): 
    def __init__(self): 
     # do your stuff 
     self.ss = SpecialSlicer(self) 

    def __gettitem__(self, ...): 
     return .... 

Итак, теперь вы можете сделать:

a = Array() 
a[3:4] 
a.ss[4:5] 

Но опять же, в этом случае, если я правильно понял проблему, я будет идти для функции, которая просто получает уже срезанный объект.

+0

Спасибо. Если я не ошибаюсь, ваш фрагмент кода делает то же самое, что и мой код в части TL, DR моего вопроса. Если Pandas сделает это, я думаю, что это эффективный вариант, а не плохой способ использования getitem. – Hyperboreus

+0

Да, это жизнеспособный вариант. Единственное различие между вашим и моим кодом заключается в том, что вы создаете объект indexer всякий раз, когда обращение к ресурсу происходит, что в данном случае, я думаю, не нужно. –