2013-10-28 2 views
0

У меня есть скрипт Python, который управляет list воображаемых машин, которые должны пройти выше линий данного изображения.Цепь над iterable

У меня есть класс Control, который отслеживает все экземпляры Machine и обновляет положение и поворот экземпляра. Из-за некоторых недостатков изображения некоторые случаи могут и будут потеряны, так что им нужно будет пересчитать их «вручную».

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

Это то, что у меня есть:

class Control: 
    def __init__(self, instances): 
     self.machine_instances = instances 
     ... 

    def get(self, elem = 0, end = None, step = 1): 
     return machine_instances[elem : end : step] 

    ... 


class Machine: 
    def __init__(self, x_position): 
     ... 

    def position_recalc(self): 
     ... 

    ... 

Это, как он должен быть использован:

ml = [Machine(int(sys.argv[i])) for i in range(1, sys.argc)] 
c = Control(ml) 

... 

c.get(2, 4).position_recalc() 

OBS: Метод Control.get() может иметь возвращаемое значение и тип изменился.

+1

Что вы хотите сказать? '' Get (2, 4) 'должен возвращать машины по индексам 2 и 4? – BrenBarn

+0

Просто выполните: 'для машины в c.get (2, 4): machine.position_recalc()'. Вы можете написать функцию, которая делает это для вашего: 'def recalc_all (control, * args): для машины в control.gets (* args): machine.position_recalc()'. – Bakuriu

+0

Не могу это сделать с помощью '__getattr__'? –

ответ

1

Похоже, что вам нужно, чтобы вернуть что-то вроде list с методом position_recalc

class ListWithReCalc(list): 
    def position_recalc(self): 
     ... 

class Control: 
    def __init__(self, instances): 
     self.machine_instances = instances 
     ... 

    def get(self, elem = 0, end = None, step = 1): 
     return ListWithReCalc(machine_instances[elem : end : step]) 

В противном случае вы можете использовать композицию,

class ThingWithReCalc(object): 
    def __init__(self, items): 
     self.items = items() 

    def position_recalc(self): 
     for i in self.items(): 
      i.position_recalc() 

class Control: 
    def __init__(self, instances): 
     self.machine_instances = instances 
     ... 

    def get(self, elem = 0, end = None, step = 1): 
     return ListWithReCalc(machine_instances[elem : end : step]) 
+0

Не могу ли я добавить этот метод к встроенному 'list'? –

+2

@RodrigoSiqueira, нет, это не Рубин.Вот почему модуль называется [forbiddenfruit] (http://clarete.github.io/forbiddenfruit/). Серьезно, вы хотите, чтобы _ALL_ из ваших объектов списка имел этот метод ??? –

+0

Хорошая точка. Не думал об этом. –

1

Вы можете создать класс SelectedMachines:

class SelectedMachines: 
    def __init__(self, selected): 
     self.selected_machines = selected 
    def position_recalc(self): 
     for machine in self.selected_machines: 
      machine.someFunction() 

Итак, вы можете вернуть SelectedMach Ines объекта в Control.get():

class Control: 
    def __init__(self, instances): 
     self.machine_instances = instances 
     ... 

    def get(self, elem = 0, end = None, step = 1): 
     return SelectedMachines(machine_instances[elem : end : step]) 

... 

someFunction() Где это метод, который применяется пересчитывает положение одной конкретной машины.

+0

Да, это нормальный очевидный путь, но вопрос настаивает на конкретном соглашении. –

+0

@gnibbler Отредактировано так, чтобы оно соответствовало требованиям OP. – Christian

0

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

class Control(object): 
    def __init__(self, instances): 
     self.focus = None 
     self.instances = instances 

    def get(self, start=None, end=None, slice=None): 
     self.focus = (start, end, slice) 
     return self 

    def position_recalc(self): 
     if self.focus == None: 
      self.focus = (None, None, None) 
     for i in self.instances.__getitem__(slice(*self.focus)): 
      i.position_recalc() 
     self.focus = None 

c.get(2,4).position_recalc() 

c.get(2,4) возвращает тот же элемент, но задает контекст для него, и возвращает же объекта пользователя, что необходимо так position_recalc имеет объект работа над. вероятно, существует общий шаблон для этого (делегитор?), это необычная форма для него, но все тот же общий шаблон.

Смежные вопросы