11

クラスが初期化された後、クラスの一部の属性に対するそれ以上の割り当てを禁止したいと考えています。例えば; Person インスタンス 'p' が初期化された後は、誰も明示的に 'ssn' (社会保障番号) プロパティに値を割り当てることはできません。_ setattr __ init _メソッド内で値を割り当てている間に呼び出されているため、これは私が望むものではありません。今後の割り当てのみを制限したいと思います。どうすればそれを達成できますか?

class Person(object):
    def __init__(self, name, ssn):
        self.name = name
        self._ssn = ssn

    def __setattr__(self, name, value):
        if name == '_ssn':
            raise AttributeError('Denied.')
        else:
            object.__setattr__(self, name, value)

>> p = Person('Ozgur', '1234')
>> AttributeError: Denied.
4

4 に答える 4

15

通常の方法は、アンダースコアで始まる「プライベート」属性と、パブリック アクセス用の読み取り専用プロパティを使用することです。

import operator

class Person(object):
    def __init__(self, name, ssn):
        self.name = name
        self._ssn = ssn
    ssn = property(operator.attrgetter("_ssn"))

これは属性を変更することを実際に妨げるものではありませんが、属性が非公開であるという _ssn主要なドキュメントに注意してください。_

于 2012-06-07T09:24:53.903 に答える
5

まだ変更できることを指摘するだけ_ssnです。

オブジェクトには特別な属性があり__dict__ます。これは、オブジェクトのすべてのインスタンス属性を対応する値にマップするディクショナリです。__dict__オブジェクトの属性を変更することで、インスタンスの属性を直接追加/更新/削除できます。

_snn次のように変更できます。

p = Person('Ozgur', '1234')

p.__dict__.get('_ssn') # returns '1234'

p.__dict__['_ssn'] = '4321'

p.__dict__.get('_ssn') # returns '4321'

ご覧のとおり、 の値を変更することができました_ssn。設計上、すべてのケースで Python の属性アクセスを回避する簡単な方法はありません。

property()をデコレータとして使用して属性アクセスを制限する、より一般的な方法を示します。

class Person(object):
    def __init__(self, name, ssn):
        self.name = name
        self._ssn = ssn

    @property
    def ssn(self):
        return self._ssn

    @ssn.setter
    def ssn(self, value):
        raise AttributeError('Denied')


>> p = Person('Ozgur', '1234')
>> p.ssn
>> '1234'
>> p.ssn = '4321'
>> AttributeError: Denied

お役に立てれば!

于 2018-08-15T06:59:45.293 に答える
2

コンストラクターでインスタンス ディクショナリに直接割り当てることにより、setattrをバイパスできます。もちろん、このトリックは、_ssn を読み取り専用にするために使用する他のフープを偽装するためにいつでも使用できます (最初の書き込み後)。

 class Person(object): 
    def __init__(self, name, ssn):    
        self.name = name
        self.__dict__['_ssn'] = ssn 

    def __setattr__(self, name, value):
        if name == '_ssn':
            raise AttributeError('Denied.')
        else:
            object.__setattr__(self, name, value)
于 2015-08-16T00:33:32.300 に答える