45

Javaでは、匿名の内部クラスを使用して新しいクラスをインラインで定義できます。これは、クラスの単一のメソッドのみを書き直す必要がある場合に役立ちます。

単一のメソッドのみをオーバーライドするサブクラスを作成するとしOptionParserます(たとえばexit())。Javaでは、次のように記述できます。

new OptionParser () {

    public void exit() {
        // body of the method
    }
};

このコードは、メソッドOptionParserのみを拡張およびオーバーライドする匿名クラスを作成します。exit()

Pythonにも同様のイディオムがありますか?このような状況で使用されるイディオムはどれですか?

4

11 に答える 11

50

組み込み関数を使用type(name, bases, dict)して、その場でクラスを作成できます。例えば:

op = type("MyOptionParser", (OptionParser,object), {"foo": lambda self: "foo" })
op().foo()

OptionParserは新しいスタイルのクラスではないためobject、基本クラスのリストに明示的に含める必要があります。

于 2010-10-12T13:53:02.040 に答える
17

Javaは、主にクロージャまたは単にコードブロックを模倣するために匿名クラスを使用します。Pythonではメソッドを簡単に渡すことができるため、匿名の内部クラスのように不格好な構造は必要ありません。

def printStuff():
   print "hello"

def doit(what):
   what()

doit(printStuff) 

編集:私はこれがこの特別な場合に必要なものではないことを知っています。この問題に対する最も一般的なPythonソリューションについて、Javaの匿名内部クラスによって最も一般的に説明しました。

于 2008-12-10T23:35:43.170 に答える
14

これは、次の 3 つの方法で実行できます。

  1. 適切なサブクラス (もちろん)
  2. オブジェクトを引数として呼び出すカスタム メソッド
  3. (おそらく必要なもの) -- オブジェクトに新しいメソッドを追加する (または既存のメソッドを置き換える)。

オプション 3 の例 (「新しい」モジュールの使用を削除するように編集 -- 非推奨であり、知りませんでした):

import types
class someclass(object):
    val = "Value"
    def some_method(self):
        print self.val

def some_method_upper(self):
    print self.val.upper()

obj = someclass()
obj.some_method()

obj.some_method = types.MethodType(some_method_upper, obj)
obj.some_method()
于 2008-12-11T00:01:54.643 に答える
12

クラスはファースト クラス オブジェクトなので、必要に応じてメソッドで作成できます。例えば

from optparse import OptionParser
def make_custom_op(i):
  class MyOP(OptionParser):
    def exit(self):
      print 'custom exit called', i
  return MyOP

custom_op_class = make_custom_op(3)
custom_op = custom_op_class()

custom_op.exit()          # prints 'custom exit called 3'
dir(custom_op)            # shows all the regular attributes of an OptionParser

しかし、実際には、通常のレベルでクラスを定義しないのはなぜでしょうか? カスタマイズする必要がある場合は、カスタマイズを引数として に入れます__init__

(編集:コードの入力エラーを修正)

于 2008-12-11T00:05:13.610 に答える
6

Python はこれを直接サポートしていません (匿名クラス) が、簡潔な構文のため、実際には必要ありません。

class MyOptionParser(OptionParser):
    def exit(self, status=0, msg=None):
        # body of method

p = MyOptionParser()

唯一の欠点は、名前空間に MyOptionParser を追加することですが、John Fouhy が指摘したように、複数回実行する場合は関数内に非表示にできます。

于 2008-12-11T15:06:37.393 に答える
5

Python には、おそらく問題を解決するためのより良い方法があります。あなたがやりたいことのより具体的な詳細を提供できれば、それは役に立ちます。

たとえば、コードの特定のポイントで呼び出されるメソッドを変更する必要がある場合は、関数をパラメーターとして渡すことでこれを行うことができます (関数は Python のファースト クラス オブジェクトであり、関数などに渡すことができます)。無名関数を作成することもできlambdaます (ただし、それらは単一の式に制限されています)。

また、Python は非常に動的であるため、作成後にオブジェクトのメソッドを変更できますが、object.method1 = alternative_impl1実際にはもう少し複雑ですが、gnud の回答を参照してください。

于 2008-12-10T23:54:47.560 に答える
2

Python では、ラムダ ステートメントを使用して宣言された無名関数があります。私はそれらがあまり好きではありません。あまり読みにくく、機能が限られています。

ただし、あなたが話していることは、まったく異なるアプローチで python に実装される可能性があります。

class a(object):
  def meth_a(self):
    print "a"

def meth_b(obj):
  print "b"

b = a()
b.__class__.meth_a = meth_b
于 2008-12-10T23:49:53.593 に答える
0

ひねくれたので_、派生クラス名に使い捨ての名前を使用できます。

class _(OptionParser):

    def exit(self):
        pass  # your override impl
于 2021-01-25T23:24:20.687 に答える
0

クラスはいつでも変数で非表示にできます。

 class var(...):
     pass
 var = var()

それ以外の

 var = new ...() {};
于 2011-05-30T10:28:57.763 に答える