2017-01-13 11 views
1

私はあなたのほとんどがそのままであることを知っていますexecは使用しないでください。ここで'exec'はプライベートメソッドPythonでは動作しません

は働く、最小限の例です。

class A: 
    def __init__(self): 
     exec('self.a = self.funct()') 
    def funct(self): 
     return 1 
    def ret(self): 
     return self.a 
> obj = A() 
> obj.ret() 
1 

しかし、ときに私はない:その差がある理由

class A: 
    def __init__(self): 
     exec('self.a = self.__funct()') 
    def __funct(self): 
     return 1 
    def ret(self): 
     return self.a 
> obj = A() 
AttributeError: 'A' has no attribute '__funct' 

誰もが知っていますか?

+1

'__'名は** class ** privateです。それは他の言語のプライバシーモデルと同じではありません。 –

答えて

3

__name名前はプライベートです。そのような名前は、コンパイル時に別のアンダースコアとクラス名の接頭辞が付きます。目的は、名前がサブクラスで使用される名前と偶然の衝突から保護することです。これらの名前はではなく、外部の発信者にはプライベートにすることを目的としたではありません。

__*
クラスのプライベート名:Reserved classes of identifiers sectionを引用

。このカテゴリの名前は、クラス定義のコンテキスト内で使用されると、ベースクラスと派生クラスの「プライベート」属性間の名前の衝突を避けるために、変更されたフォームを使用するように書き直されます。

と​​:

プライベート名前マングル:原文どおりクラス定義で発生した識別子は、二つ以上のアンダースコア文字で始まり、、二つ以上のアンダースコアでそれを終了していませんそのクラスのプライベートな名前とみなされます。プライベート名はコードが生成される前に長い形式に変換されます。この変換では、先頭にアンダースコアが削除され、アンダースコアが1つ挿入されたクラス名が挿入されます。たとえば、Hamという名前のクラスにある識別子__spam_Ham__spamに変換されます。この変換は、識別子が使用されている構文的文脈とは無関係です。あなたのケースで何が起こる

exec()が効果的に分離にその呼び出しをコンパイルし、コンパイルを延期するということです。クラスのコンテキストがなくなったので、マングリングは起こりません。

そのため、手動での接頭辞自動を適用する必要があります。

exec('self.a = self._A__funct()') 

あなたは、Python 3を使用している場合は、現在のメソッドが定義されたクラス名にアクセスするために__class__閉鎖normally available for the super() functionを使用することができます。

あなたのクラスが広く、内部実装の詳細と衝突について誤って心配する必要はありませんサードパーティ製のコードでサブクラス化するために、あなたが実際に予定がない限り、今、あなたは二重のuを使用すべきではない
exec('self.a = self._{0.__name__}__funct()'.format(__class__)) 

名前のネストは全くありません。代わりに単一のアンダースコアの名前をつけてください。

0

Pythonのプライベートメソッドは、コードで指定されたものとは異なる識別子で "偽装"されているため、_classname__privateAttributeのようにアクセスできます。

が、これは具体的には投稿:

class A: 
    def __init__(self): 
     exec('self.a = self._A__funct()') 
    def __funct(self): 
     print("Hello") 
    def ret(self): 
     return self.a 

obj = A() 

私はそれが働いたかどうかを検出するためにそこに印刷答えを入れて、それがなかったです!

関連する問題