#python #scoring
#питон #подсчет очков #python #оценка
Вопрос:
нужно руководство по простому способу сделать это. у меня есть несколько активов, каждый с несколькими точками данных. Я хочу присвоить значение каждому активу на основе решений по каждой из этих точек данных. В качестве примера, каждый актив, являющийся домом, и точки данных, включая количество окон, гаражных ворот, сломанный забор и т.д., Каждый дом будет иметь оценку.
Есть ли рекомендуемый способ кодирования этого, помимо сотен операторов if и добавления / вычитания из оценки?
Пример того, как я планирую это сделать
def score_house(house):
# score house
score = 0
if (house.windows > 2): score = 10
if (house.garage): score = 10
if (house.fence == 'broken'): score = 80
return score
Комментарии:
1. Вы ищете существенные изменения?
2. Больше просто нужно убедиться, что является наиболее эффективным и питоническим.
Ответ №1:
Я думаю, вы также можете использовать шаблон «цепочка ответственности» здесь:
Шаблон позволяет нескольким объектам обрабатывать запрос без привязки класса отправителя к конкретным классам получателей. Цепочка может быть составлена динамически во время выполнения с помощью любого обработчика, который следует стандартному интерфейсу обработчика.
Что хорошо в использовании этого шаблона, так это то, что вы можете определять и расширять различные оценки в отдельных модулях и динамически комбинировать их во время выполнения на основе проблемных условий. Вот как вы можете это сделать. Сначала определите родительский класс score:
from functools import reduce
class BaseScorer(object):
def __init__(self):
self._next_scorer = None
def set_next(self, scorer):
self._next_scorer = scorer
return scorer
def _call_next(self, house, score):
if self._next_scorer is None:
return score
return self._next_scorer.score(house, score)
def score(self, house, score=0):
raise NotImplementedError
@staticmethod
def chain(scorers):
reduce(lambda x, y: x.set_next(y), scorers)
return scorers[0]
Затем определите различные классы оценщиков, например:
class WindowScorer(BaseScorer):
def score(self, house, score=0):
if house.windows > 2:
score = score 10
return self._call_next(house, score)
class GarageScorer(BaseScorer):
def score(self, house, score=0):
if house.garage:
score = score 10
return self._call_next(house, score)
class FenceScorer(BaseScorer):
def score(self, house, score=0):
if house.fence == 'broken':
score = score - 5
return self._call_next(house, score)
И вот как это можно использовать:
scorer = BaseScorer.chain([
WindowScorer(),
GarageScorer(),
FenceScorer()
])
house = House(windows=4, garage=True, fence='nice')
score = scorer.score(house)
Комментарии:
1. Учитывая, что существует два уникальных вычисления для каждого атрибута (сравнение, оценка), это самый чистый метод.
Ответ №2:
Я думаю, что ваш метод хорош, и не стоит пытаться сделать что-то еще. Возможно, вы захотите упорядочить его, определив функцию следующим образом:
def add_score(x, score):
score = x
return score
И dictionary
тому подобное:
sdict = {windows: 10, garage: 10, broken_fence: 10}
Чтобы вы могли вызывать свою функцию следующим образом:
def score_house(house):
# score house
score = 0
if (house.windows > 2): add_score(sdict[windows])
if (house.garage): add_score(sdict[garage])
if (house.fence == 'broken'): add_score(sdict[broken_fence])
return score
И легко иметь возможность изменять оценку с одной dictionary
.
Вы также можете (и теперь, когда думаете об этом, вероятно, должны) использовать Enums
:
from enum import Enum
class Scoring(Enum):
WINDOWS = 10
...
def score_house(house):
# score house
score = 0
if (house.windows > 2): add_score(Scoring.WINDOWS)
...
Комментарии:
1. Мне нравится простота. Спасибо