2017-11-01 8 views
0

プロパティがdeletedのクラスがあります。ユーザーはob.delete()メソッドを使用する必要があります。彼が直接ob.deleted = Trueをやろうとすると、エラーが発生するはずです。属性を設定するときにスローエラーが発生する

class A(ORMBaseClass): 
    deleted = False 

    def delete(self): 
     self.deleted = True 


a = A() 
a.delete() # works 
print(a.delete) # works 
a.deleted = True # must throw exception 
Exception: you cannot directly set deleted 

私は__setattr__を過負荷でそれを試してみましたが、それは同様にob.delete()影響します。クラスは、ORMモデルであり、彼はsession.query(A).filter(A._deleted == True)a.deleted=TrueのUXの矛盾に直面しているようob._deletedプライベート属性を持つ

プロパティとob.deletedプロパティは適していません。

私はPythonがこれを行うための完全な安全な方法を持っていないことを知っています。私はただ停止し、因果関係を設定したユーザーに通知したいだけです。このような

+0

どのようなpythonを使用しますか? Arch Linux/x86-64のpython-3.6で問題を確認できません – user3159253

+0

2.7/OsX –

+0

@ user3159253と同じです。Ashish、ひどく書いてしまいましたが、既存のエラーはありません。私は混乱する言葉を修正した。 – aitchnyu

答えて

2

何か作業をする必要があります:

class A(object): 
    def __init__(self): 
     self._deleted = False 

    @property 
    def deleted(self): 
     return self._deleted 

    @deleted.setter 
    def deleted(self, value): 
     raise Exception("Can't directly set deleted") 

    def delete(self): 
     self._deleted = True 

あなたはプロパティのgetおよびsetメソッドを指定し、セッターが直接呼び出された場合に例外を発生させます。これはPython 2.7と3.xで動作します。

2

あなたはこれを行うことができます:

def __setattr__(self, name, value): 
    if name == 'deleted': 
     raise AttributeError("you cannot directly set deleted") 
    object.__setattr__(self, name, value) 

その後、deleteに、あなたが直接object.__setattr__(self, 'deleted', True)を呼び出すことによって、その周りに行かなければなりません。

しかし、実際にはそれを行うべきではないでしょう。メンバー変数を「プライベート」にしたい場合は、その名前をアンダースコアで始めるだけです(例: _deleted。それでも書込み可能ですが、「変数は非公開で、それに触れないでください」という意味での規約です。

+0

プライベートに2つのアンダースコアを使用します。 2つのアンダースコアは大会以上のもので、pythonが名前のマングリングを使用するよう強制します。クラスの中では、属性は '__deleted'になりますが、' __deleted'クラスの外には存在しません。これは '_CLASS__attribute'と呼ばれます。あなたの属性が混乱しないように、継承されたクラスを必要とするときは特に良いことです。 –

+0

@LoïcFaure-Lacroix実際、プライベート変数に2つのアンダースコアを使用することはお勧めできません。 '_'も' __'も、本当にプライベートなものではありません。どちらも絶対にアクセス可能なままです。後者は、より多くの入力が必要です。ダブルアンダースコアは、継承を含むいくつかの状況で便利です。シンプルな「プライバシー」のために、Pythonでは慣習に頼らざるを得ません。したがって、単一のアンダースコアを使用した単純なソリューションは、私がほとんどいつでも好むものです。 – zvone

0

これまでの解決策をいくつかご紹介します。

あなたはメンバーが変数のプライベートを作るために2つのアンダースコアを使用している、プライベートメンバー(名前の符号化)のためのPythonの力学

class A(ORMBaseClass): 
    __deleted = False 

    def delete(self): 
     self.__deleted = True 

    @property 
    def deleted(self): 
     return self.__deleted 

最初の通知を利用することができます。 2つのアンダースコアを使用することは、提案された1つのアンダースコアのようなコンベンション以上のものです。これは、pythonが属性上で名前のマングリングを使用するようにします。この場合、この属性にアクセスする唯一の方法は、obj._A__deletedです。まだ書き込み可能ですが、1つのアンダースコアを使用するよりもはるかに優れています。

今、あなたはTrue__deletedを設定する簡単な方法と値を返すプロパティを持っています。ここでは何も複雑ではありません。

なぜ名前のマングリングが重要なのですか?あなたがこれを行うにあればここで

obj = B() 
obj.deleted 

あなたがFalseを推測した場合は、その後、あなたは正しい:

class B(A): 
    __deleted = True 

    @property 
    def deleted2(self): 
     return self.__deleted 

はの戻り値がどうなるかと思います!クラスBは、クラスA _A__deletedの間に_B__deletedという名前の属性を定義します。あなたが見ることができるように、名前のマングリングは、サブクラスが誤って上位クラスの属性にアクセスするのを防ぎます。そして、クラス外のどこからでも__deletedにアクセスしようとすると、その属性は未定義となります。

理論的には、あなたが本当にプライベートであることを望むなら、毎回ランダムな名前でそのようなものを構築することができますクラスが構築される時間。

関連する問題