1
  1. これら2つのクラス宣言の違いは何ですか?「オブジェクト」は何をしますか?

    class className(object):
        pass 
    
    class className:
        pass 
    
  2. 次のコードを実行すると、なぜこのエラーが発生するのですか:「引数を取りません(1つ指定)」

    class Hobbs():
        def represent():
            print "Hobbs represent!"
        represent = classmethod(represent)
    
    Hobbs.represent()   
    
  3. 関数に引数を渡さなくても、「Foo.class_foo()」でエラーが発生しないのはなぜですか。

    class Foo(object):
        @staticmethod
        def static_foo():
        print "static method"
        @classmethod
        def class_foo(cls):
            print "Class method. Automatically passed the class: %s" % cls      
    Foo.static_foo()
    Foo.class_foo()
    
  4. 以下のコードを実行すると、なぜこのエラーが発生するのですか?

    class Foo(object):  
        def static_foo():
            print "static method"
            static_foo = staticmethod(static_foo)
        def class_foo(cls):
                print "Class method. Automatically passed the class: %s" % cls
        class_foo = classmethod(class_foo)  
    Foo.static_foo()
    Foo.class_foo()
    

「TypeError:バインドされていないメソッドstatic_foo()は、最初の引数としてFooインスタンスを使用して呼び出す必要があります(代わりに何も取得しません)」

4

5 に答える 5

5
  1. 新しいクラスの基本クラスとして使用objectすることは、少なくとも Python 2.2 以降の慣習であり、「New-Style Classes」と呼ばれます。詳細については、この質問を参照してください。古いスタイルのクラス (つまり、 を継承していないクラスobject) は、Python 3.0 で非推奨になるように設定されています。これらの変更の理由はやや不明瞭ですが、低レベルのクラス解決と継承パターンに関係しています。

  2. Python インスタンス メソッドは、慣例によりself、最初の引数として受け取ります。この引数は暗黙的に渡されます。そのため、メソッド定義が をとらない場合、self呼び出しようとしているメソッドが自動的に渡される引数を受け入れないと、インタープリターは文句を言います。これはクラスメソッドに対してもまったく同じように機能しますが、self通常は を取得する代わりに を取得しclsます。(単なる命名規則です。)簡単な修正:

    class Hobbs():
        def represent(cls):
            print "Hobbs represent!"
        represent = classmethod(represent)
    
    Hobbs.represent()   
    
  3. Python は、メソッドを呼び出すたびにクラス オブジェクトをメソッドに自動的に渡すため、呼び出しFoo.class_foo()によって問題が発生することはありません。class_fooこれらのメソッドはバインド メソッドと呼ばれます。つまり、これらのメソッドは通常の関数ですが、クラスまたはインスタンス オブジェクトにバインドされます。バインドされたメソッドは、バインド先のクラスまたはインスタンス オブジェクトを最初の引数として自動的に受け取ります。

  4. Python ではインデント レベルが重要です。提供されたコード サンプルを実行しようとしましたが、static_foo =と行の両方が、クラス定義の下や他のメソッド内ではなくclass_foo =、クラス定義内にある必要があります。Foo適切にインデントすると、コードは正常に実行されます。

    class Foo(object):
        def static_foo():
            print "static method"
        static_foo = staticmethod(static_foo)
        def class_foo(cls):
            print "Class method. Automatically passed the class: %s" % cls
        class_foo = classmethod(class_foo)
    Foo.static_foo()
    Foo.class_foo()
    
于 2012-09-23T01:41:43.407 に答える
1
  1. 最後の2つは同じです。空の角かっこは、それらを省略するのと同じです。1つ目は組み込みクラスから継承しobject、「新しいスタイルのクラス」になります。新旧のスタイルクラスの理由は歴史的であり、古いスタイルは下位互換性のためにのみ保持されます-基本的に、Python 2では、object他のものから継承しない場合は常にから継承することをお勧めします。あなたが学ぶであろう派手なトリックは、最終的にはそれに依存します。Python 3にアップグレードすると、これがデフォルトの動作になり、3つのクラス宣言はすべて同等になります。

  2. と同様のclassmethod最初の引数を取る必要がありますself-を呼び出すと、Pythonはその最初の引数としてHobbs.represent()渡されます。これがとHobbsの根本的な違いです。aは最初の引数を取ります(呼び出されたクラスであるため)が、そうではありません。classmethodstaticmethodclassmethodstaticmethod

  3. 2-と同じ-クラスはclassmethod通常の代わりにに渡されselfます。

  4. これはインデントの問題のようです。コードが次のようにインデントされている場合、コードは記述どおりに機能します。

    def static_foo():
        print "static method"
    static_foo = staticmethod(staticfoo)
    

しかし、そうではありません

def static_foo():
    print "static method"
    static_foo = staticmethod(staticfoo)    

行の再割り当てstatic_fooは、関数自体の一部ではなく、クラス本体に含める必要があるためです。後者の場合、その行は関数が実行されるまで実行されません(つまり、関数がエラーになるため実行されません)staticmethod。そして、メソッド自体ではなくローカル変数にを割り当てます。このタイプのエラーは、デコレータ構文を使用するのが適切な理由の1つです。

 class Hobbs:
    @staticmethod
    def static_foo():
         print "static method"

動作します。

于 2012-09-23T01:49:42.130 に答える
0

あなたの質問のほとんどは、実際にはオブジェクト指向自体に関するものではなく、Pythonによるその特定の実装に関するものです。

  1. Python 2.xは、新しい機能が追加されて、いくつかの進化を遂げました。したがって、クラスを定義する方法は2つあり、「新しいスタイルのクラス」と「古いスタイルのクラス」になります。Python3.xには「新しいスタイルクラス」しかありません。新しいスタイルのクラスの基本オブジェクトはと呼ばれobjectます。それを継承すると、新しいスタイルのクラスができます。特定のデコレータなどの追加機能のいくつかを提供します。Python 2.xにベア(継承なし)の定義がある場合は、古いスタイルのクラスがあります。これは、下位互換性のために存在します。Python 3.xでは、新しいスタイルのクラスも取得します(したがって、からの継承objectはオプションです)。

  2. represent()「クラスメソッド」を作成しました。したがって、呼び出されたときに、クラスオブジェクトを暗黙の最初の引数として取得します。ただし、これらは新しいスタイルのクラスでのみ機能します。古いスタイルのクラスで使用しようとしました。したがって、機能しません。

  3. Pythonは、クラスメソッドの引数ゼロとしてクラスオブジェクトを自動的に挿入します。これが正しいパターンであり、機能します。

  4. インデントが間違っているためか、メソッドはどういうわけかクラスメソッドになりませんでした。

于 2012-09-23T01:47:43.587 に答える
0
  1. class ClassName(OtherClass): ClassNameがOtherClassから継承することを意味します。継承は大きなテーマですが、基本的には、ClassNameが少なくともOtherClassと同じ関数とフィールドを持っていることを意味します。

    Pythonでは、すべてがオブジェクトであるため、すべてのクラスは暗黙的または明示的にオブジェクトから継承します。これは言われています

    class ClassName():宣言は古い構文であるため、避ける必要があります。

    class ClassName:クラスと同等ですClassName(object):

  2. クラスメソッドは静的メソッドではありません。インスタンスではなくパラメータとしてクラスが渡されることを除けば、他のインスタンスメソッドと同じです。

    クラスメソッドの宣言が間違っています。clsパラメーターが必要です。

  3. 一方、静的メソッドは、コンテキスト外で呼び出されるメソッドです。つまり、どのインスタンスとも関係がありません。これは、セマンティックな理由で単にクラスに入れられる独立した関数と考えることができます。

    これが、自己パラメータを必要とせず、自己パラメータが渡されない理由です。

  4. インデントエラーがあります。エラーの原因になっている可能性があります。

于 2012-09-23T01:48:05.263 に答える
0

すべてのクラス関数は、最初の引数として自分自身を取る必要があります

class  A:
   def my_func(self):
        print "In my func"

静的メソッドは、名前空間内の関数にすぎないクラスです(Pythonではめったに使用されません)。

クラスメソッドは、インスタンスではなくクラス自体で呼び出す必要があるクラス名前空間の関数です。

于 2012-09-23T01:19:28.707 に答える