Класс Objects и сравнение определенных атрибутов - PullRequest
0 голосов
/ 10 ноября 2009

У меня есть следующий код.

class person(object):

    def __init__(self, keys):
        for item in keys:
            setattr(self, item, None)

    def __str__(self):
        return str(self.__dict__)

    def __eq__(self, other) :        
        return self.__dict__ == other.__dict__

Теперь я хочу взять этот код и делать __eq__ только для определенного набора атрибутов («ключей»). Поэтому я изменил это, чтобы сделать это:

class person(object):

    def __init__(self, keys):
        self.valid_keys = keys
        for item in keys:
            setattr(self, item, None)

    def __str__(self):
        return dict([(i, getattr(self, i)) for i in self.valid_keys ])

    def __eq__(self, other) :
        assert isinstance(other, person)
        self_vals = [ getattr(self, i) for i in self.valid_keys ]
        other_vals = [ getattr(other, i) for i in self.valid_keys ]
        return self_vals == other_vals

Я прочитал следующие два удивительных поста ( здесь и здесь ), и мой основной вопрос:

Это правильный подход или есть лучший способ сделать это в python?

Очевидно, TMTOWTDI - но я бы хотел сохранить и следовать стандартному питоническому подходу. Спасибо !!

Обновление

Меня спросили, почему я не исправляю атрибуты в моем классе. Это отличный вопрос, и вот почему. Цель этого состоит в том, чтобы взять несколько записей о сотрудниках, разделенных друг от друга, и создать полную картину сотрудника. Например, я получаю свои данные из ldap, заметок лотоса, файлов unix passwd, данных bugzilla и т. Д. Каждый из них имеет уникальные атрибуты, поэтому я обобщил их в личность. Это дает мне быстрый последовательный способ сравнить старые записи с новыми записями. НТН. Спасибо

** Обновления Pt.2 **

Вот что я закончил:

class personObj(object):

    def __init__(self, keys):
        self.__dict__ = dict.fromkeys(keys)
        self.valid_keys = keys

    def __str__(self):
        return str([(i, getattr(self, i)) for i in self.valid_keys ])

    def __eq__(self, other):
        return isinstance(other, personObj) and all(getattr(self, i) == getattr(other, i) for i in self.valid_keys)

Спасибо обоим мужчинам за рецензию!

Ответы [ 2 ]

2 голосов
/ 10 ноября 2009

Есть небольшие улучшения (исправления ошибок), которые я определенно сделаю.

В частности, getattr, вызываемый с двумя аргументами, вызывает ArgumentError, если атрибут отсутствует, поэтому вы можете получить это исключение, если сравниваете два экземпляра с разными ключами. Вместо этого вы можете просто вызвать его с тремя аргументами (третий аргумент возвращается в качестве значения по умолчанию, когда атрибут отсутствует) - просто не используйте None в качестве третьего аргумента в этом случае, так как обычно это значение (используйте значение часового в качестве третьего аргумента).

__str__ не разрешено возвращать dict: он должен возвращать строку.

__eq__ между несопоставимыми объектами не должен подниматься - он должен возвращать False.

Помимо ошибок, вы можете получить очень компактное состояние объекта с помощью self.__dict__ или более элегантно с vars(self) (однако, вы не можете переназначить весь dict с последним синтаксисом). Эти знания позволят вам полностью переделать ваш класс на более высоком уровне абстракции - более компактный и быстрый:

class person(object):

    def __init__(self, keys):
        self.__dict__ = dict.fromkeys(keys)

    def __str__(self):
        return str(vars(self))

    def __eq__(self, other):
        return isinstance(other, person) and vars(self) == vars(other)
1 голос
/ 10 ноября 2009

Вы можете упростить сравнение с:

self_vals = [ getattr(self, i) for i in self.valid_keys ]
other_vals = [ getattr(other, i) for i in self.valid_keys ]
return self_vals == other_vals

до:

return all(getattr(self, i) == getattr(other, i) for i in self.valid_keys)
...