2017-06-07 12 views
3

私が行ったPythonスクリプトのオブジェクトからフィールドにアクセスする際に問題があります。基本的には、コードのこの小さな作品に沸く:フィールドのデフォルト値

from enum import Enum 

class AbstractFoo: 
    def __init__(self, foo='works', bar='nope'): 
     self.foo = foo 
     self.bar = bar 

class Foo(Enum): 
    test = AbstractFoo('bla', 'tada') 

だから、Pythonのコンソールに私が私の列挙型の要素にアクセスしようとすると:

Foo.test.foo 

私はそれが私を印刷することを期待します " bla 'はコンストラクタに渡す値です(少なくとも、私が割り当てたデフォルト値である' works 'を出力する必要があります)。

私は何を実際に取得すると、あなたはおそらく今私はPythonとPythonで特に概念オブジェクトにかなり新たなんだということで伝えることができ

AttributeError: 'Foo' object has no attribute 'foo' 

です(私は主に、いくつかのmissconceptionsにつながる可能性があるJavaでコードを書きますPythonでオブジェクトの動作についての私の部分から)。私も考え出し何

は私が行うことができるということです。

Foo.test.foo = 'whatever' 

と、このようにfooに値を割り当てます。

Foo.test.noField = 'shouldn't even exist' 

、それは私は全く理解していないこれだけのように正常に動作します。しかし、これをやると、私も、私もようなコンストラクタで指定されていないフィールドに値を割り当てることができます。

私は、オブジェクトがどのようにしてPythonで動作するか、および/またはPythonでクラスの列挙型を実現する方法について、本当に嬉しく思っています。

編集:明らかに、コードはEnumから継承を削除した場合、私が望むように動作します。

+0

enumが必要ですか?コードは 'Enum'から' Foo'を継承しないと期待通りに動作します – sommerjj

+0

それはありますか?大いに感謝する!しかし、enumの問題は何ですか? – Desperate

+0

私がenumを使用しないときは、これはFooクラスに属する静的フィールド(Javaの用語集を使用しています)のようになりました。私がしようとしていることは重要ではありませんが、なぜ私のコードが動作するのかを理解することを好む(: – Desperate

答えて

3

これは、文字通りtestが何かであり、それはもはやそれではないと言っているので、かなり混乱する可能性があります。これは、Enumがそのメンバーのすべてをとり、それらをクラスのインスタンスに「変換」する特別な種類のクラスであるためです。したがって、testのタイプはAbstractFooではなく、代わりにFooです。しかし、あなたがvalueプロパティで列挙インスタンスに割り当てられた元の値取り戻すことができます。@jdehesaが指摘したように

from enum import Enum 

class AbstractFoo: 
    def __init__(self, foo='works', bar='nope'): 
     self.foo = foo 
     self.bar = bar 

class Foo(Enum): 
    test = AbstractFoo('bla', 'tada') 

print(Foo.test.value.foo) 

>>> bla 
+0

!説明のおかげでたくさんありました!コメントする最初の人は私が本当にエナムを必要としていないと指摘しました。私がまだ理解していない唯一のことは、あなたが実際にPythonでEnumをいつ使うのでしょうか?基本的にクラスのインスタンスに型の列挙型を与え、.value経由でフィールドにアクセスするように強制することです。列挙型の継承をそのまま残して幸せにならないのはなぜですか? – Desperate

+0

@Desperate 'Enum'は本当に便利です(Pythonのほとんどのもののように8Dのようです)。それは直接的なクラスインスタンスの作成を許さず(ちょっと)、値の比較をより安全にします(ちょっと)。また、既存の値を反復処理することもできます。しかし、switch/case完全性チェック(最初にswitch文が必要)やそれに類するものは何もないので、利点は限られています。 – jdehesa

1

を、Enumメンバーは、親Enumクラスのインスタンスです。あなたはまた、いくつかの他のクラスのインスタンスであることを彼らが必要な場合は、単にだけでなく、それを継承する:あなたは、もはや直接AbstractFooを呼び出す必要が

class Foo(AbstractFoo, Enum): 
    test = 'bla', 'tada' 

注意を。

関連する問題