Использование унифицированных переменных в Python - PullRequest
4 голосов
/ 10 августа 2011

Справочная информация: у меня есть класс, моделирующий микросхему с регистрами, микросхема имеет набор регистров, один из которых - предел высокой температуры для встроенного датчика температуры.

У меня есть следующее:

class foo():
  def __init__(self):
    # does not set self._hiTemp!
    ...
  def setHiTemp(self, t):
    self._hiTemp = t
  def getHiTemp(self):
    return self._hiTemp
  def checkHiTemp(self):
    return self._temp > self._hiTemp

Причина, по которой я не объявляю self._hiTemp в __init__, заключается в том, что пользователь может не заботиться о возможностях чипа, воспринимающих температуру. Пользователь может использовать микросхему по-разному, и бессмысленно придавать этой переменной бессмысленное значение. Однако, если пользователь пытается использовать self._hiTemp без предварительной установки его, ошибку при использовании необъявленных переменных гораздо легче отладить / отследить, чем какую-то непонятную ошибку, такую ​​как сравнение чисел и None (или в некоторых случаях вообще никаких ошибок).

Все идет нормально, пока я не запустил pylint, и, конечно, я получаю W0201: атрибут, определенный вне init почти везде. Мне просто интересно, не одобряется ли этот стиль кодирования, и если да, то что такое «Pythonic way».

Спасибо

Ответы [ 5 ]

11 голосов
/ 10 августа 2011

Я бы сделал это, установив значение None или другое значение часового, которое не встречается «в природе».Затем для операций, которые требуют его установки, используйте assert для быстрого сбоя в случае, если вызывающая сторона пытается использовать ваш объект ненадлежащим образом.

def __init__(self):
    self._hiTemp = None

def checkHiTemp(self):
    assert self._hiTemp is not None, 'Why you no set _hiTemp before checking it?'
    return self._temp > self._hiTemp
6 голосов
/ 10 августа 2011

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

class Foo(object):
    def __init__(self, hiTemp=None):
        self._hiTemp = hiTemp

    @property
    def hiTemp(self):
        if self._hiTemp is None:
            raise AttributeError("You have not initialized hiTemp")
        return self._hiTemp

    @hiTemp.setter
    def hiTemp(self, value):
        self._hiTemp = value

    def checkHiTemp(self):
        return self._temp > self._hiTemp

foo=Foo()
foo.hiTemp = 50
print foo.hiTemp # Prints 50

foo=Foo(hiTemp=20)
print foo.hiTemp # Prints 20

foo=Foo()
print foo.hiTemp # Raises exception
1 голос
/ 10 августа 2011

Если вы хотите, чтобы определенный атрибут объекта был установлен с помощью метода, то всегда может быть причина, по которой он будет доступен в инициализаторе.Вы можете просто использовать self._hiTemp=None. Вы уже объявляете его частным, ведя _, поэтому пользователи поймут, что на это не следует полагаться.

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

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

def __init__(self):
    self._hiTemp = None

def setHiTemp(self, t):
    self._hiTemp = t

def getHitemp(self):
    if self._hiTemp is None:
        raise Exception('You need to setHiTemp() before using it.')
    else:
        return self._hiTemp

def checkHiTemp(self):
    if self._hiTemp is None:
        raise Exception('You need to setHiTemp() before using it.')
    else:
        return self._temp > self._hiTemp
0 голосов
/ 10 августа 2011

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

...