web-dev-qa-db-ja.com

オブジェクトインスタンス変数を設定する適切な方法

私はユーザーをデータベースに挿入するクラスを書いていますが、深く入り込む前に、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()

これは正しいアプローチですか?クラス変数を一番上に宣言する必要がありますか?すべてのクラス変数の前に_を使用して、それらをプライベートにする必要がありますか?

助けてくれてありがとう。

16
ensnare

一般的には正しいですが、 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()

便利なデコレータベースの構文もあり、ドキュメントでもそれについて説明されています。

21
bcherry

単一の_を使用しても、属性は非公開になりません。これは、内部属性であり、通常の状況では外部コードからアクセスしてはならないことを示す規則です。あなたのコードでは、パスワードと名前が読み取り専用であることも意味します。

Noneなどのデフォルト値であっても、属性を初期化するクラスのイニシャライザーを使用することを強くお勧めします。これにより、_nameと_passwordの存在を確認する必要がないcommitメソッドが簡単になります。属性(hasattrを使用)。

コードでPylintを使用します。

7
gurney alex

そのコードにはクラス変数はなく、インスタンス属性のみが含まれています。そして、アクセサの代わりに properties を使用します。そして、できれば渡された値から、イニシャライザでインスタンス属性を作成します。

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

  ...

他の人はすでに指摘しています:属性を取得/設定するときに追加のロジックを実行する必要がない場合は、セッターとゲッターの使用を避け、単純な属性アクセスを使用してください。追加のロジックが必要な場合は、プロパティを使用してください。

インスタンス初期化子に渡すパラメーターが多数ある場合は、すべてのパラメーターを保持する個別のオブジェクトまたはディクショナリを使用することを検討してください。

>>> 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'
2
Ruslan Spivak