Правильный способ установить переменные экземпляра объекта - PullRequest
16 голосов
/ 26 марта 2010

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

class User(object):

    def setName(self,name):

        #Do sanity checks on name
        self._name = name

    def setPassword(self,password):

        #Check password length > 6 characters
        #Encrypt to md5
        self._password = password

    def commit(self):

        #Commit to database

>>u = User()
>>u.setName('Jason Martinez')
>>u.setPassword('linebreak')
>>u.commit()

Это правильный подход? Должен ли я объявить переменные класса сверху? Должен ли я использовать _ перед всеми переменными класса, чтобы сделать их закрытыми?

Спасибо за помощь.

Ответы [ 4 ]

21 голосов
/ 26 марта 2010

Это, как правило, правильно, AFAIK, но вы можете очистить его с помощью properties .

class User(object):

    def _setName(self, name=None):
        self._name = name

    def _getName(self):
        return self._name

    def _setPassword(self, password):
        self._password = password

    def _getPassword(self):
        return self._password

    def commit(self):
        pass

    name = property(_getName, _setName)
    password = property(_getPassword, _setPassword)

>>u = User()
>>u.name = 'Jason Martinez'
>>u.password = 'linebreak'
>>u.commit()

Существует также удобный синтаксис на основе декоратора, документы также объясняют это.

7 голосов
/ 26 марта 2010

использование одиночного _ не делает ваши атрибуты приватными: это соглашение, согласно которому он является внутренним атрибутом и не должен быть доступен при нормальных обстоятельствах внешним кодом. С вашим кодом это также означает, что пароль и имя только для чтения.

Я настоятельно рекомендую использовать инициализатор для вашего класса, который инициализирует ваши атрибуты, даже если для значения по умолчанию, такого как None: это облегчит ваш метод фиксации, где вам не придется проверять наличие Атрибуты _name и _password (с hasattr).

Используйте Pylint в своем коде.

3 голосов
/ 26 марта 2010

В этом коде нет переменных класса, только атрибуты экземпляра. И используйте properties вместо аксессоров. И создайте атрибуты экземпляра в инициализаторе, предпочтительно из значений, переданных в:

class User(object):
  def __init__(self, name, password='!!'):
    self.name = name
    self.password = password

  ...
2 голосов
/ 26 марта 2010

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

Если у вас много параметров для передачи инициализатору экземпляра, рассмотрите возможность использования отдельного объекта или словаря, содержащего все параметры:

>>> class User(object):
...     def __init__(self, params):
...         self.__dict__.update(params)
... 

>>> params = {
...     'username': 'john',
...     'password': 'linebreak',
...     }
>>> user = User(params)
>>> user.username
'john'
>>> user.password
'linebreak'

PS В вашемЕсли вам не нужно объявлять свои атрибуты на уровне класса.Обычно это делается, если вы хотите использовать одно и то же значение для всех экземпляров класса:

>>> class User(object):
...     type = 'superuser'
... 
>>> user = User()
>>> user2 = User()
>>> 
>>> user.type
'superuser'
>>> user2.type
'superuser'
>>> 
>>> user2.type = 'instance superuser'
>>> 
>>> user.type
'superuser'
>>> user2.type
'instance superuser'
>>> User.type
'superuser'
...