Правильный способ установки переменных экземпляра объекта
Я пишу класс, чтобы вставлять пользователей в базу данных, и прежде чем я заберусь слишком далеко, я просто хочу убедиться, что мой подход OO чист:
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()
Это правильный подход?
Должен ли я объявлять переменные класса вверх?
Должен ли я использовать _ перед всеми переменными класса, чтобы сделать их частными?
Спасибо за помощь.
Ответы
Ответ 1
Как правило, правильно, AFAIK, но вы можете очистить его с помощью свойств.
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()
Там также удобный синтаксис, основанный на декорете, документы также объясняют это.
Ответ 2
с использованием единственного _ не делает ваши атрибуты закрытыми: это соглашение, указывающее, что это внутренний атрибут и не должно при нормальных обстоятельствах быть доступным внешним кодом. С вашим кодом это также означает, что пароль и имя только для чтения.
Я настоятельно рекомендую использовать инициализатор для вашего класса, который инициализирует ваши атрибуты, даже если это значение по умолчанию, такое как None: это упростит ваш метод фиксации, когда вам не нужно будет проверять наличие _name и _password (с hasattr).
Используйте Pylint для вашего кода.
Ответ 3
В этом коде нет переменных класса, только атрибуты экземпляра. И используйте свойства вместо аксессуаров. И создайте атрибуты экземпляра в инициализаторе, предпочтительно из значений, переданных в:
class User(object):
def __init__(self, name, password='!!'):
self.name = name
self.password = password
...
Ответ 4
Другие уже указали на это: избегайте использования сеттеров и геттеров и используйте простой доступ к атрибутам, если вам не нужно выполнять дополнительную логику при получении/настройке вашего атрибута.
Если вам нужна эта дополнительная логика, используйте свойства.
Если у вас есть много параметров для перехода к инициализатору экземпляра, рассмотрите возможность использования отдельного объекта или словаря, содержащего все параметры:
>>> 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'
P.S. В вашем случае вам не нужно объявлять свои атрибуты на уровне класса.
Обычно это делается, если вы хотите использовать одно и то же значение во всех экземплярах класса:
>>> 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'