2010-03-26 67 views
13

我正在写一个类用户插入到数据库中,而之前,我太远,我只是想确保我的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() 

这是正确的做法吗? 我应该向上声明类变量吗? 我应该在所有类变量前面使用_来使它们变为私有的吗?

感谢您的帮助。

+0

代码中没有类变量。考虑更新您的标题。 – 2010-03-26 08:02:30

+0

你使用什么教程来学习Python。这应该包括在内。既然不是,我想知道你正在使用什么教程。 – 2010-03-26 10:14:27

+0

“对象实例变量”在Python中被称为“属性” – 2010-03-26 10:19:57

回答

19

这通常是正确的,据我所知,但你可以用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() 

还有一个方便的基于装饰器的语法,文档也解释了这一点。

+0

这真的很有帮助。谢谢。 – ensnare 2010-03-26 08:17:36

+1

我注意到你的构造函数接受了一个强制的'name'参数,所以你的'User()'的例子用法会引发一个错误。我编辑我的示例默认'name'为'None'来避免这种情况,但是您可能想要提供一个没有参数的重载实现。 – bcherry 2010-03-26 08:36:37

+0

是的,谢谢! – ensnare 2010-03-26 17:14:32

3

该代码中没有类变量,只有实例属性。并使用properties而不是访问器。而且确实创造了在初始化实例的属性,最好在传递的值:

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

    ... 
+0

感谢您的回应。我不确定哪些属性,但我会阅读。用户对象有很多变量,大约50个,所以我认为这将是太多的传递给构造函数,不是吗? 我知道代码中目前没有类变量。我的意思是,我应该制作这些类变量吗? 谢谢。 – ensnare 2010-03-26 08:04:22

+0

永远不要使用类变量,当值需要随实例而变化时。 – 2010-03-26 08:06:28

7

使用单个_不会使您的属性变为私有:它是一种约定,它告诉它是内部属性,并且不应在正常情况下由外部代码访问。使用您的代码也意味着密码和名称是只读的。

我强烈建议为您的类使用初始化程序,它将初始化您的属性,即使是默认值(如None):它会使事情变得更容易,您不必检查是否存在_name和_password属性(使用hasattr)。

在您的代码上使用Pylint。

2

其他人已经指出:如果在获取/设置属性时不需要执行额外的逻辑,请避免使用setter和getter并使用简单的属性访问。 如果您确实需要额外的逻辑,请使用属性。

如果有许多参数传递给一个实例初始化考虑使用单独的对象或辞典保持所有参数:

>>> 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' 

附:在你的情况下,你不需要在课堂级别声明你的属性。 通常情况下,如果要在所有类实例中共享相同的值,请执行以下操作:

>>> 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'