Управление геттером и сеттером для класса питона - PullRequest
5 голосов
/ 07 августа 2009

Рассмотрим следующий класс:

class Token:
    def __init__(self):
        self.d_dict = {}

    def __setattr__(self, s_name, value):
        self.d_dict[s_name] = value

    def __getattr__(self, s_name):
        if s_name in self.d_dict.keys():
            return self.d_dict[s_name]
        else:
            raise AttributeError('No attribute {0} found !'.format(s_name))

В моем коде токен имеет некоторую другую функцию (например, get_all (), которая возвращает d_dict, has (s_name), которая сообщает мне, имеет ли мой токен определенный атрибут).

В любом случае, я думаю, что это мой недостаток в моем плане, так как он не работает: когда я создаю новый экземпляр, python пытается вызвать __setattr__('d_dict', '{}').

Как мне добиться подобного поведения (возможно, более питоническим способом?) Без необходимости писать что-то вроде Token.set (имя, значение) и получать (имя) каждый, который я хочу установить или получить атрибут для токена .

Критики по поводу недостатков дизайна и / или глупости приветствуются:)

Спасибо!

Ответы [ 6 ]

3 голосов
/ 07 августа 2009

Специальный корпус __dict__ работает следующим образом:

def __init__(self):
    self.__dict__['d_dict'] = {}

Для этого не нужно использовать класс нового стиля.

3 голосов
/ 07 августа 2009

Вам нужен особый случай d_dict.

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

В этом случае вы можете использовать свойства.

class C(object):
    def __init__(self):
        self._x = None

    @property
    def x(self):
        """I'm the 'x' property."""
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

    @x.deleter
    def x(self):
        del self._x
2 голосов
/ 07 августа 2009

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

>>> class  Foo(object):
...     def __new__(cls, *args):
...             my_cls = super(Foo, cls).__new__(cls, *args)
...             my_cls.d_dict = {}
...             return my_cls

>>> f = Foo()
>>> id(f.d_dict)
3077948796L
>>> d = Foo()
>>> id(d.d_dict)
3078142804L

Слово с объяснением, почему я считаю это хаком: вызов __new__ возвращает новый экземпляр класса , поэтому d_dict , инициализированный там, имеет вид static , но он инициализируется новым экземпляром словаря каждый раз, когда класс " создал ", поэтому все работает так, как вам нужно.

1 голос
/ 07 августа 2009

Стоит помнить, что __getattr__ вызывается, только если атрибут не существует в объекте, тогда как __setattr__ всегда вызывается.

1 голос
/ 07 августа 2009

Решение, не очень питонное, но работает. Как указал Леннарт Регебро, вы должны использовать специальный случай для d_dict.

class Token(object):

    def __init__(self):
        super(Token,self).__setattr__('d_dict', {})

    def __getattr__(self,name):
        return self.a[name]

    def __setattr__(self,name,value):
        self.a[name] = value

Вам нужно использовать новые классы стилей.

0 голосов
/ 10 августа 2009

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

# This is a class that serves as a dictionary but also has user-defined methods
class mydict(dict): pass

# This is a class that allows setting x.attr = value or getting x.attr:
class mysetget: pass

# This is a class that allows setting x.attr = value or getting x.attr:
class mygetsethas: 
    def has(self, key):
        return key in self.__dict__

x = mygetsethas()
x.a = 5
print(x.has('a'), x.a)

Я думаю, что последний урок ближе всего к тому, что вы имели в виду, и мне также нравится играть с синтаксисом и получать от этого массу удовольствия, но, к сожалению, это не очень хорошая вещь. Причины, по которым не рекомендуется использовать атрибуты объекта для повторной реализации словаря: вы не можете использовать x.3, вы конфликтуете с x.has(), вы должны помещать кавычки в has('a') и многие другие.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...