2016-12-23 2 views
0

__setattr__親を無視:Pythonの:次のコードを持つ

class Parent(): 
    def __init__(self): 
     pass 

    def __setattr__(self, name, value): 
     raise RuntimeError() 


class Child(Parent): 
    def __init__(self): 
     super().__init__() 
     self.y = 2 


if __name__ == '__main__': 
    print(Child().y) 

を、次の条件/仮定:新しい設定するときChildを行い、その__setattr__実装に何かが例外を発生させない

  • クラスParentクラス属性。
  • クラスParentソースコードを変更することはできません(猿のパッチが当てられている可能性がありますが、外部の依存関係です)。

これを修正する方法はありますか? yを設定する前に、Parent__setattr__の実装を「ゴミ箱」にすることはできますか? Childにこのメソッドを実装して、期待どおりに動作させることはできますか?これは完全ので、これをやってParent__setattr__は、Parentで様々な不変量を壊すかもしれないバイパスされていることを

object.__setattr__(self, 'y', 2) 

注:

+1

あなたは '' Child'クラスの__setattr__'をオーバーロードすることができます。 –

+0

@hiroprotagonist:ええ、私は 'object .__ setattr__'を試しましたが、これはうまくいきませんでした。今私はそれと 'super(Parent、self).__ setattr__'の違いを知っています。 :-) – Peque

+0

私は実際に私が答えとして投稿したものを意味しました。 'object'では' __setattr__'を呼び出さず、 'self'だけで呼び出します。これは、MROチェーンで定義されている可能性のあるすべての '__setattrs__'をバイパスします。 –

答えて

2

MROで__setattr__メソッドを検索することで、この方法を回避することができます。過去Parentを見てsuper()を教える:あなたは正常にないsuper()における電流から別のクラスを使用する必要があります

class Child(Parent): 
    def __init__(self): 
     super().__init__() 
     self.y = 2 

    def __setattr__(self, name, value): 
     # skip Parent.__setattr__ 
     super(Parent, self).__setattr__(name, value) 

注意。これは適切な例外ですが、これを行う理由を説明するために、プロダクションコードにコメントを入れてください。

あなたすぎobject.__setattr__(self, name, value)を使用することができますが、Parentobjectからではなく、また__setattr__を実装し、いくつかの他のクラスから直接継承している場合のみ。 を使用すると、継承ツリーにの次の__setattr__の実装が見つかります。

デモ:

>>> class Parent(): 
...  def __init__(self): 
...   pass 
...  def __setattr__(self, name, value): 
...   raise RuntimeError() 
... 
>>> class Child(Parent): 
...  def __init__(self): 
...   super().__init__() 
...   self.y = 2 
...  def __setattr__(self, name, value): 
...   # skip Parent.__setattr__ 
...   super(Parent, self).__setattr__(name, value) 
... 
>>> Child().y 
2 
+0

あなたは常により完全な答えを出すことができます。ありがとう! alsways新しい 'トリック'を学ぶ。 –

+0

私は 'object .__ setattr__'を試しましたが、何とか失敗していました。何とかあなたは実際の解決策と私の悪い質問(笑)に良い答えが付属しています。 – Peque

+0

最新の回答とアドバイスをいただき、ありがとうございます。 @ Bakuriuが 'object .__ setattr__'とあなたのアプローチとの間に実際の違いがあることを説明するコメントを追加したいかもしれません。それをより完全にするために、そしてあなたが時間を持っているならば。 ;-) – Peque

1

あなたはベース__setattr__を呼び出すことができます。

+0

それ以上: 'object'と' Parent'の間に複数のクラスがあり、あなたができることを潜在的に保存したい場合に 'super(Parent、self).__ setattr__'をこのように使います'object'はすべての実装をスキップします。 – Bakuriu

+0

私は 'オブジェクトで試しました。__setattr__'を尋ねる前に、何とか失敗していました。申し訳ありません、悪い質問と正しい答えをありがとうございます。 :-) – Peque

+0

@Bakuriu良い点ですが、 'super(Parent、self)...'は 'Child'と' Parent'の間にあるmixins内の '__setattr__'実装もスキップします。とにかく、それが何をしているのかを慎重に理解することなく、 'Parent .__ setattr__'をスキップすることはできません。その理解の一部は、あなたが呼びたい '__setattr__'を見つけ出し、それを呼び出すことです。この種の魔法をするとき、私は可能な限り明示的にするのが最善だと思っています。 – user4815162342

0

はあなたがParentに1を無視することができますChild__setattr__メソッドを追加:

class Child(Parent): 
    ... 
    def __setattr__(self, name, value): 
     # do whatever you want; 
関連する問題