5

このシナリオでは、ネストされたクラスに、外部クラスのリストにアイテムを追加するように依頼する必要があります。これは、Imがやろうとしていることに似た擬似コードです。どうすればそれを機能させることができますか?

class Outer(object):
  outerlist = []
  class Inner(object):
    def __call__(self, arg1):
      outerlist.append(arg1)

if __name__ == "__main__":
  f = Outer()
  f.Inner("apple")
  f.Inner("orange")

  print f.outerlist()

これは私が見たいものです- apple, orange

詳細:
OS X、Python 2.7

4

5 に答える 5

4

これにより、望ましい結果が得られます。

__new__(行 A)の使用に注意してください。これは、構築作業を適切に行う代わりに、Inner がリストを追加するだけであることを意味します。また、包含クラスのクラス プロパティにアクセスするには、外側のクラスの名前を使用します (行 B)。

最後に C 行を見てください。リストは関数ではありません。元のコードに余分な括弧がいくつかありました。

class Outer(object):
    outerlist = []
    class Inner(object):
        def __new__(self, arg1):                #A
            Outer.outerlist.append(arg1)        #B

f = Outer()
f.Inner("apple")
f.Inner("orange")
print f.outerlist                               #C
于 2012-12-10T09:33:49.030 に答える
3

完全なグローバル名を持つ外部クラスにのみアクセスできます。

class Outer(object):
    outerlist = []
    class Inner(object):
        def __call__(self, arg1):
            Outer.outerlist.append(arg1)

Python では、通常、どのような場合でもクラスをネストする必要はありません。関数でクラスを定義する (スコープ変数を使用する) ことが理にかなっているユースケースがありますが、ネストされたクラスが必要になることはめったにありません。

于 2012-12-10T09:25:51.790 に答える
2

外側のクラスのインスタンスをパラメーターとして内側のクラスのメソッドに渡してみませんか? その方法で、外部クラス インスタンスのメンバーにアクセスできます。

  class Outer(object):
    outerlist = []
    class Inner(object):
      def __init__(self, outer_self):
        self.outer = outer_self
      def __call__(self, arg1):
        self.outer.outerlist.append(arg1)

 if __name__ == "__main__":
   f = Outer()
   i = f.Inner(f)
   i("apple")
   i("orange")

   print f.outerlist
于 2016-09-01T17:43:13.927 に答える
1

私があなたのデザインを理解したので、あなたはすべて間違ったことをしている。

まず、アウターはクラスです。__call__エドにはなりません。17行目は、空のOuterオブジェクトを作成し、それに対して何もしません。Outerオブジェクトを「呼び出す」場合は、__init__メソッドを定義できます。または、Sheenaが提案するように__new__、初期化されたオブジェクトは実際には必要ないため、を定義して初期化をインターセプトできます。

正直なところ、まだどのように機能するかを理解していない人は__call__、まだこのようなトリッキーなものを構築しようとすべきではないと思います。しかし、あなたが主張するなら、読み続けてください。

この種のものをインスタンスではなくクラスに収集することは、非常に奇妙で、おそらく悪い設計です。クラス変数は事実上グローバルであり、それに伴うすべてのものがあることに注意してください。繰り返し使用しようとするとOuter、または複数のスレッド/イベントハンドラー/グリーンレットなどから使用しようとすると、使用は互いに踏みにじられてしまいます。今は問題にならないだろうと思っていても、将来的には問題になる可能性があります。

インスタンスを作成し、Outerそのメンバーをデコレータとして使用できます。例えば:

from outer_library import Outer

outer = Outer()

@outer.get("/")
…

しかし、それがはるかに優れているかどうかはわかりません。ここでの設計全体には、通常の関数を定義し、最後に関数を呼び出すだけのように見えますが、モジュールレベルでアクションを実行することが含まれているようです。あなたが自分自身を混乱させることができたという事実は、これがデザインをどれほど混乱させているかの証拠であるはずです。

ただし、それを実行したい場合は、Outer.__init__メソッド内でクラスを定義し、それらをインスタンスメンバーに割り当てることをお勧めします。クラスはファーストクラスの値であり、他の値と同じように変数に割り当てることができます。次に、それらのクラスの__init__(または__new__)メソッドを使用して必要な作業を実行し、クラスに関数をシミュレートさせます。

これは、紛らわしいまたは誤解を招くように見える場合があります。ただし、実行しようとしていることの全体的なポイントは、メソッドのように見える方法でクラスを使用することであるため、問題には一種の混乱が内在していることを忘れないでください。ただし、必要に応じて、デコレータを関数として(この場合は)の通常のインスタンスメソッドとして記述できますOuter。この部分ではなく、問題の別の部分を難しくするだけです。

このようなものを設計するためのより通常の方法はOuter、人々がサブクラス化またはインスタンスを作成できる完全に通常のクラスを作成し、ハンドラーメソッドまたは関数をURLにアタッチするための明示的な非ファンシーな方法を提供することです。次に、それが機能したら、デコレータを使用してハンドラの登録を簡素化する方法を設計します。

于 2012-12-10T10:05:17.223 に答える