Переключение операторов для композиции объектов в Python
У меня возникают проблемы при разработке шаблона переключателя (Python), который хорошо работает с композицией объектов. Более конкретно, я хочу создать функцию, которая получает "entity_id" в качестве аргумента (+ другие соответствующие аргументы), создает объект и соответствующие компоненты для него (возможно, используя дополнительные аргументы). Вот игрушечный пример
class Entity:
def __init__(self,name,animal=None,item=None):
self.name = name
class Animal: # Animal component
def __init__(self,legs):
self.legs = legs
class Item: # Item component
def __init__(self,quantity):
self.quantity = quantity
Я хотел бы иметь что-то вроде:
def place_entity(entity_id,quantity=1):
switch (entity_id):
case 'emu':
animal_component = Animal(2)
ent = Entity('Emu', animal_component)
break
case 'apple':
item_component = Item(quantity)
ent = Entity('Apple(s)', item_component )
break
return(ent)
Было бы легко произвести вышесказанное, используя цикл for и операторы if, но есть ли лучший способ? Это должно быть легко
- добавлять новые типы объектов (бананы, гвозди, акулы и т. д.),
- добавить новые компоненты (например, съедобный, который сообщает, является ли сущность вопроса съедобной и сколько калорий в нем содержится),
без необходимости менять код в слишком многих местах. Обратите внимание, что компонентам иногда требуются дополнительные аргументы (которые приведены во входных данных функции).
Я видел замену операторов switch на словари, но моя реализация (ниже) оказалась ужасной. Добавление другого компонента требует добавления кода для каждой функции сущности!
Также я не знаю, как элегантно передать аргументы компонентам. Дополнительные аргументы не работают в этой реализации. То есть, если бы я хотел создать сущность (группу) яблок (скажем, количество =5), мне пришлось бы модифицировать каждый тип функции сущности, чтобы принимать аргумент количества (даже если он не использует ее), или изменить количество после создания сущности (это не разумно, поскольку, если использовать операторы if, то можно также использовать операторы loop+if).
def create_entity(entity_id,quantity=None):
def emu():
animal_component = Animal(2)
entity_data = {'name':'Emu','animal_component':animal_component,
'item_component':None}
return(entity_data)
def apple(quantity=1):
item_component = Item(quantity)
entity_data = {'name':'Apple(s)','animal_component':None,
'item_component':item_component}
return(entity_data)
entity_dict = {'emu':emu,'apple':apple}
entity_data = entity_dict[entity_id]()
ent = Entity(entity_data['name'], animal=entity_data['animal_component'],
item=entity_data['item_component'])
return(ent)
1 ответ
Вы можете имитировать оператор switch, используя это определение функции:
def switch(v): yield lambda *c: v in c
Использование будет очень близко к тому, что вы ищете:
for case in switch (entity_id):
if case('emu'):
animal_component = Animal(2)
ent = Entity('Emu', animal_component)
break
if case('apple'):
item_component = Item(quantity)
ent = Entity('Apple(s)', item_component )
break