2013-08-14 2 views
0

В последнее время я занимаюсь разведением ООП.Передача экземпляров в качестве дополнительных аргументов другому классу

У меня есть два класса: один для события и один для вычисления некоторого набора атрибутов этого события.

class Event(object): 
    def __init__(self,name,info): 
     self.name = name 
     self.category = info.category 
     self.classification = info.classification 

    @property 
    def attributes(self): 
     return dict((k,v) for k,v in self.__dict__.items()) 

class class1(object): 
    def __init__(self,some_number): 
     self.number = some_number 

    @property 
    def category(self): 
     #stuff 
     return category 

    @property 
    def classification(self): 
     #stuff 
     return classification 

Прямо сейчас я могу сделать что-то вроде

e = Event('myevent', class1(42)) 
e.attributes 
{'category': 1, 
'classification': None, 
'name': 'myevent'} 

Но я хочу, чтобы иметь возможность давать Event() экземпляры любого числа/комбинации будущего class2, class3 и т.д.; и поэтому я хочу Event()init() метод, чтобы изящно обрабатывать их так, чтобы e.attributes вернул все соответствующие атрибуты. Предоставление Event.__init__ a * param для распаковки, похоже, не обходит необходимость знать имена атрибутов, которые ему нужно назначить себе. В конечном итоге то, что я хочу сделать, - это создать это событие, а затем создать/обновить его различные наборы атрибутов по мере необходимости, используя эту парадигму. Является ли это возможным?

+2

Во-первых, почему 'dict ((k, v) для k, v в себе .__ dict __. Items())' просто для копирования dict? Во-вторых, почему вы притворяетесь диктарем над диктором в первую очередь? Возможно, вам нужно [лучше объяснить, что вы на самом деле пытаетесь выполнить, а не просто показывать свое частичное решение] (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). – abarnert

+0

Я пытаюсь понять ваш вопрос, но это очень неясно. Я подозреваю, что есть хороший шанс, что, если бы вы объяснили это лучше, вы могли бы сами ответить самим ответом? –

+0

Я нахожусь над моей головой, поэтому я вполне могу быть виновным в проблеме xy, но я попытаюсь уточнить. У Miku почти есть то, что я хочу, за исключением того, что я являюсь после аддитивного процесса: я хочу обновить «e.attributes» после двух приведенных им вызовов, чтобы его значения были «{« i_am_totally_different »:« да, действительно », 'name': 'myevent', 'category': 'category value', 'class': 'class value', 'number': 42} '. И чтобы ответить на вопрос Майка, это потому, что у меня может не быть всей информации, необходимой для всех классов, когда я сначала создаю 'e', но я не хочу использовать атрибуты обновления по частям. – verbsintransit

ответ

1

Я думаю, есть no totally clean way to get only user defined attributes объекта python, который вам нужен в вашем примере, чтобы сделать Event полностью не осведомленным о структуре info. И если дизайн реализуется только с помощью хаков, он может быть не самым надежным - даже если он выглядит OOD-ish.


Ниже приведен пример класса событий, что не знает реальных атрибутов info объекта, переданного в:

class Event(object): 
    # instead of accepting attributes, just deal with a single object 'info' 
    def __init__(self, name, info): 
     self.name = name 
     self.info = info 

    @property 
    def attributes(self): 
     # attributes will consist of 
     # A) Event's name - fixed 
     # B) info objects hopefully 'public' attributes, which we need 
     # to lookup at runtime 
     attrs = {'name': self.name} 
     for attr in [name for name in dir(self.info) 
        if not name.startswith('_')]: 
      attrs[attr] = getattr(self.info, attr) 
     return attrs 

Class1 и Class2 действительно не имеют много:

class Class1(object): 
    def __init__(self, some_number): 
     # some initial attribute 
     self.number = some_number 

    @property 
    def category(self): 
     # stuff 
     return 'category value' 

    @property 
    def classification(self): 
     # stuff 
     return 'classification value' 

class Class2(object): 
    @property 
    def i_am_totally_different(self): 
     return 'yes, indeed' 

Теперь вы можете передать любой класс в Event, но я не уверен, если это был действительно ваш вопрос:

e = Event('myevent', Class1(42)) 
print(e.attributes) 
# {'category': 'category value', 'name': 'myevent', 
# 'classification': 'classification value', 'number': 42} 

e = Event('myevent', Class2()) 
print(e.attributes) 
# {'i_am_totally_different': 'yes, indeed', 'name': 'myevent'} 
0

Вы говорите: «У меня есть два класса: один для события и один для вычисления некоторого набора атрибутов этого события». У вас есть веская причина для этого? Если у вас есть класс событий, почему бы не использовать эти рассчитанные атрибуты как свойства события?

+0

Пожалуйста, посмотрите мой комментарий в моем исходном вопросе. – verbsintransit

+0

@verbsintransit ответил - я подозреваю, что вы пытаетесь найти комплексное решение * очень * для очень простой проблемы. Если вы дадите более подробную информацию о фактической проблеме, которую пытаетесь решить, мы можем исследовать лучший способ ее решения, чем использовать все это самоанализ. В Python существуют огромные и сложные приложения, которые не используют ни одну из этих хакерских внутренних логик. –

0

Альтернативным подходом к этому было бы не сбрасывание всего содержимого class2, class3 и т. Д., Не зная, каковы они. Вы можете попросить, чтобы класс публиковал его «общедоступные» атрибуты каким-то образом, например, с помощью метода get_attributes. С кодированием удобства точки зрения это меньше работы, если class2, class3 и так далее наследовать от общего предка, но это совершенно нормально для «доступа утка» им:

class Event(object): 
    def __init__(self, name, info): 
     self.Name = name 
     self.Info = info 

    @property 
    def attributes(): 
     result = { k: getattr(info, k) for k in info.get_attributes() } 
     return result 

class Class1(object): 
    def __init__ (name, classification, other) 
     self.Name = name 
     self.Other = other 
     self.Classification = classification 

    def get_attributes(self): 
     return ("Name", "Classification") # in this case not "Other"... 

class Class2(object): 
    def __init__(self, privateName, orivateData, publicName): 
     self.Name = privateName 
     self.Data = privateData 
     self.Public = publicName 

    def get_attributes(self): 
     return ("Public",) 

Это «выбрать в» альтернативе @ идея Мика - это, вероятно, более безопасная ставка, если вы не уверены, что ваш единственный создающий код на обоих концах события> информация отношения. Приятным трюком было бы предоставление декоратора для адаптации существующих классов с помощью метода get_attributes.

Ясность намерения в сторону, это тоже немного защита от работы в чудаком класса с тысячами строк текста в одном из своих полей :)

Редактировать В ответ на @ наблюдение Майк: это будет быть чище, если get_attributes просто вернул словарь из информационных объектов, что было бы более чистой развязкой без бремени отражения. Я оставляю код как есть или обсуждение не имеет смысла, но правильным способом было бы называть «get_attributes» на дочернем, если он существует, и возвращать значение по умолчанию, если оно не было. Мой плохой :)

+0

Как имя и данные приватны в Class2? Кроме того, вам не нужно передавать класс в Event? Эти проблемы в стороне, такой дизайн очень хакен - должно быть лучшее решение того, чего принципиально хочет достичь OP. –

+0

конфиденциальность - чисто условная - это просто указание, что они не публикуются в системе событий. Я хочу сказать, что то, что хочет OP, настолько велико, что его вероятность может вызвать больше проблем, чем решает. Идеальная развязка не очень полезна, если единственный способ ее достичь - это подробное размышление над внутренностями неизвестных классов. – theodox

+0

В Python стандартным способом указания конфиденциальности является лидирующий двойной знак подчеркивания, например self .__ Name в случае вашего примера. –

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