【问题标题】:Proper way to set object instance variables设置对象实例变量的正确方法
【发布时间】:2010-03-26 07:52:32
【问题描述】:

我正在编写一个将用户插入数据库的类,在我深入之前,我只想确保我的 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()

这是正确的方法吗? 我应该在顶部声明类变量吗? 我应该在所有类变量前面使用 _ 来将它们设为私有吗?

感谢您的帮助。

【问题讨论】:

  • 代码中没有类变量。考虑更新您的标题。
  • 你用什么教程来学习 Python。这应该被覆盖。既然不是,我想知道你用的是什么教程。
  • “对象实例变量”在 Python 中被称为“属性”

标签: python oop pylons


【解决方案1】:

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

我强烈建议为你的类使用一个初始化器来初始化你的属性,即使是一个默认值,比如 None :它会让你在提交方法中更容易,你不必检查是否存在_name 和 _password 属性(带有 hasattr)。

在您的代码中使用 Pylint。

【讨论】:

    【解决方案2】:

    这通常是正确的,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()
    

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

    【讨论】:

    • 这真的很有帮助。谢谢。
    • 我注意到你的构造函数接受了一个强制的name 参数,所以你使用User() 的例子会抛出一个错误。我编辑了我的示例以将 name 默认为 None 以避免这种情况,但您可能希望提供一个完全没有参数的重载实现。
    【解决方案3】:

    该代码中没有类变量,只有实例属性。并使用 properties 代替访问器。并在初始化程序中创建实例属性,最好是从传入的值:

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

    【讨论】:

    • 感谢您的回复。我不确定什么是属性,但我会阅读。 User 对象有很多变量,大约 50 个,所以我认为传递给构造函数的变量太多了,不是吗?我知道代码中目前没有类变量。我的意思是,我应该制作这些类变量吗?谢谢。
    • 当值需要因实例而异时,永远不要使用类变量。
    【解决方案4】:

    其他人已经指出:如果您在获取/设置属性时不需要执行额外的逻辑,请避免使用 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'
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-18
      • 2014-02-25
      • 1970-01-01
      • 2011-10-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多