Какой самый питонный способ упорядочить вызовы методов объектов без - PullRequest
1 голос
/ 02 марта 2012

Когда вы предоставляете разработчику объект "robs_numbers", разработчик может вызывать различные фильтры в любом порядке, например, например. obj.filter1 (). filter2 (). filtern () ..

Однако, как правило, чем больше чисел я отфильтрую раньше, тем быстрее будет фильтрация.

Я хочу, чтобы разработчик мог вызывать методы filter () в любом порядке, в котором они хотят . Затем разработчик возвращает объект robs_numbers (или, возможно, итеративный ..). Однако я хочу, чтобы мои методы (фильтры) действительно работали в порядке, заданном priority ().

технически приоритет () должен принимать парный фильтр: [args], чтобы я мог использовать любой фильтр. priority () вернет значение приоритета

Вот пример кода, хотя вы можете полностью изменить объект, если он более питонический:

from random import randint
data = [randint(0,100) for i in range(100)]

class robs_numbers():
    def __init__(self,numbers,_min,_max):
        self.numbers = iter(numbers)
        self._min = _min #approx
        self._max = _max #approx

    def bigger(self,x):
        print "priority = ", self.priority(x)
        return robs_numbers([i for i in self.numbers if i>x],x,self._max)

    def smaller(self,x):
        print "priority = ", self.priority(x)
        return robs_numbers([i for i in self.numbers if i<x],self._min,x)

    def order(self,backwards=False):
        print "priority = ", self.priority()
        self.numbers = iter(sorted(self.numbers,reverse=backwards))
        return self

    # ...
    # More filter methods
    # ...

    def priority(self,x=None):
        #works out the order methods should be called to increase efficiency
        if x is None:
            return 99999
        else:
            return abs(x-(self._max-self._min)/2)

и пример двух допустимых применений, однако я хочу, чтобы они оба были быстрыми, сейчас эффективен только один:

def get():
    return robs_numbers(data,0,100)

rf = get().bigger(80).smaller(90).order() #faster in this order
print list(rf.numbers), rf._min, rf._max

#priority =  30
#priority =  80
#priority =  99999
#[81, 81, 82, 83, 85, 86, 87, 87, 89] 80 90


rf = get().order().smaller(90).bigger(80) #slower in this order
print list(rf.numbers), rf._min, rf._max
#priority =  99999
#priority =  40
#priority =  35
#[81, 81, 82, 83, 85, 86, 87, 87, 89] 80 90

1 Ответ

1 голос
/ 02 марта 2012

Вам придется создать какой-то лениво оцененный набор запросов и выполнять все фильтры только тогда, когда разработчик вызывает list() или что-то еще, что требует от вас экспорта данных в другой объект. Django имеет хороший пример этого в своих наборах запросов, , которые ленивы .

Итак, вы можете написать что-нибудь с эффектом

class RobsNumbers(object):
    def __init__(self, numbers, min, max):
        self._numbers = numbers
        self._min = min
        self._max = max
        self._filters = []

    def bigger(self, x):
        new_obj = RobsNumbers(self._numbers, x, self._max)
        new_obj._filters = self._filters + [GreaterThanFilter(x)]
        return new_obj

    # Other filter methods simply add a filter to the _filters list of the object

    def __iter__(self):
        # Here is the complicated optimization logic to reorder and execute the filters
        pass

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...