создание классов Python с произвольно подставленным именем атрибута - PullRequest
0 голосов
/ 11 февраля 2011

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

Я определил класс с атрибутом «спам»:

def SpamClass(object):
    def __init__(self, arg):
        self.spam = arg
    def __str__(self):
        return self.spam

Я хочу создать класс (sub / sibling?), Который имеет точно такую ​​же функциональность, но с атрибутом с именем «eggs» вместо «spam»:

def EggsClass(object):
    def __init__(self, arg):
        self.eggs = arg
    def __str__(self):
        return self.eggs

В целом, как сделатьСоздать функционально идентичные классы с произвольными именами атрибутов?Когда у класса сложное поведение, дублировать код кажется глупым.

Обновление : Я согласен, что это пахнет плохим дизайном.Чтобы уточнить, я не пытаюсь решить конкретную проблему таким глупым образом.Я просто хочу знать, как произвольно назвать (не магическое) содержимое объекта __dict__ при сохранении функциональности.Рассмотрим что-то вроде keys() метода для dict -подобных объектов.Люди создают различные классы с keys() методами, которые ведут себя в соответствии с соглашением, и соглашение об именах - это хорошо.Но название произвольно.Как я могу создать класс с spam() методом, который точно заменяет keys() без ручной замены / keys / spam / в источнике?

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

На самом деле, я могу придумать вероятный вариант использования.Предположим, вам нужен класс mixin, который присваивает специальный атрибут, и некоторые тесно связанные методы, которые манипулируют этим атрибутом или зависят от него.Пользователь может захотеть по-разному называть этот специальный атрибут для разных классов (для сопоставления имен в реальной проблемной области или во избежание конфликтов имен) при повторном использовании базового поведения.

Ответы [ 4 ]

4 голосов
/ 11 февраля 2011

Вот способ получить эффект, который, я думаю, вам нужен.

Определите универсальный класс с именем универсального атрибута.Затем в каждом подклассе следуйте совету в http://docs.python.org/reference/datamodel.html#customizing-attribute-access, чтобы внешний вид атрибута выглядел так, как будто бы он называется так, как вы хотите.

В вашем описании того, что вы делаете, есть кодчуствую "мне", я бы посоветовал внимательно изучить ваш дизайн, чтобы понять, действительно ли это то, что вы хотите сделать.Но вы можете заставить его работать с моим предложением.

0 голосов
/ 11 февраля 2011

Чтобы создать атрибуты во время выполнения, просто добавьте их в self.__dict__['foo'] = 'I'm foo' в коде класса.

0 голосов
/ 11 февраля 2011

Рассматривали ли вы не слишком усложняете вещи и просто создали один класс?(поскольку они в любом случае идентичны)

class FoodClass(object):
    def __init__(self, foodname, arg):
        self.attrs = {foodname: arg}
        self.foodname = foodname

    def __str__(self):
        return self.attrs[foodname]

Если вам нужны хорошие конструкторы, просто создайте их отдельно:

def make_eggs(arg):
    return FoodClass('eggs', arg)

def make_spam(arg):
    return FoodClass('spam', arg)
0 голосов
/ 11 февраля 2011

Вы также можете создать суперкласс со всеми общими вещами, а затем подклассы с определенными атрибутами.

Или даже:

def SuperClass(object):
    specific_attribute = 'unset'

    def __init__(self, arg):
        setattr(self, specific_attribute, arg)

    def __str__(self):
        return getattr(self, specific_attribute)


def EggClass(SuperClass):
    specific_attribute = 'eggs'
...