ホームページ  >  記事  >  バックエンド開発  >  Pythonのマジックメソッドを詳しく解説

Pythonのマジックメソッドを詳しく解説

高洛峰
高洛峰オリジナル
2016-10-20 09:22:141308ブラウズ

準備

クラスが新しい型であることを確認するには、モジュールの先頭に _metaclass_=type を置く必要があります。

class NewType(Object):
  mor_code_here
class OldType:
  mor_code_here


これら 2 つのクラスのうち、NewType が新しいクラスで、OldType が古いクラスに属します。_metaclass_=type を前に追加すると、両方のクラスが新しいクラスに属します。

Constructor

Constructor は、オブジェクトが作成されるとすぐに呼び出されます。 Python コンストラクターの作成は非常に簡単で、init メソッドを単純な init メソッドからマジック バージョンの _init_ メソッドに変換するだけです。

class FooBar:
    def __init__(self):
        self.somevar = 42
          
>>> f =FooBar()
>>> f.somevar
42


一般メソッドをオーバーライドする

すべてのクラスは 1 つ以上のスーパークラス (親クラス) を持つことができ、スーパークラスから動作メソッドを継承します。

class A:
    def hello(self):
        print 'hello . I am A.'
class B(A):
  pass
>>> a = A()
>>> b = B()
>>> a.hello()
hello . I am A.


クラスBにはhelloメソッドがなく、クラスBはクラスAを継承しているため、クラスAのhelloメソッドが呼び出されます。

サブクラスに機能を追加する最も基本的な方法は、メソッドを追加することです。ただし、一部のスーパークラス メソッドをオーバーライドして、継承された動作をカスタマイズすることもできます。以下の通り:

class A:
    def hello(self):
        print 'hello . I am A.'
class B(A):
    def hello(self):
        print 'hello . I am  B'
>>> b = B()
>>> b.hello()
hello . I am  B


特殊メソッドとコンストラクターメソッド

オーバーライドは、特にコンストラクターにとって、継承メカニズムの重要な部分です。次の例を見てください:

class Bird:
    def __init__(self):
        self.hungry = True
    def eat(self):
        if self.hungry:
            print 'Aaaah...'
            self.hungry = False
        else:
            print 'No, thanks!'
>>> b = Bird()
>>> b.eat()
Aaaah...
>>> b.eat()
No, thanks!


このクラスは、鳥が一度食べた後は、もうお腹が空かなくなることを定義しています。

次に、SongBird クラスを使用して Bird クラスを継承し、それに歌うメソッドを追加します。

class Bird:
    def __init__(self):
        self.hungry = True
    def eat(self):
        if self.hungry:
            print 'Aaaah...'
            self.hungry = False
        else:
            print 'No, thanks!'
              
class SongBird(Bird):
         def __init__(self):
                 self.sound = 'Squawk!'
         def sing(self):
                 print self.sound
>>> s = SongBird()
>>> s.sing()
Squawk!
>>> s.eat()
Traceback (most recent call last):
  File "<pyshell#26>", line 1, in <module>
    s.eat()
  File "C:/Python27/bird", line 6, in eat
    if self.hungry:
AttributeError: &#39;SongBird&#39; object has no attribute &#39;hungry&#39;


この例外はエラーを明確に示しています: SongBird にはハングリー機能がありません。その理由は次のとおりです。SongBird ではコンストラクターが書き直されますが、新しいコンストラクターにはハングリーなプロパティの初期化に関するコードが含まれていません。目的の効果を実現するには、SongBird のコンストラクターはそのスーパークラス Bird のコンストラクターを呼び出して、基本的な初期化を確実にする必要があります。

実装する 2 つのメソッド:

1. アンバインド スーパークラス コンストラクター

class Bird:
    def __init__(self):
        self.hungry = True
    def eat(self):
        if self.hungry:
            print &#39;Aaaah...&#39;
            self.hungry = False
        else:
            print &#39;No, thanks!&#39;
              
class SongBird(Bird):
         def __init__(self):
                 Bird.__init__(self)
                 self.sound = &#39;Squawk!&#39;
         def sing(self):
                 print self.sound
>>> s = SongBird()
>>> s.sing()
Squawk!
>>> s.eat()
Aaaah...
>>> s.eat()
No, thanks!

を呼び出します。 コード Bird.__init__(self) の行を SongBird クラスに追加します。 インスタンスでメソッドを呼び出すと、メソッドの self パラメータが自動的にインスタンスにバインドされます (これをバインド メソッドと呼びます)。ただし、クラス メソッドを直接呼び出すと、インスタンスはバインドされません。これにより、必要な自己パラメータを自由に提供できるようになります (このようなメソッドは非バインド メソッドと呼ばれます)。

現在のインスタンスを unbound メソッドの self パラメーターとして提供することで、SongBird はそのスーパークラス コンストラクターのすべての実装を使用できます。これは、hungry 属性を設定できることを意味します。

2. スーパー関数を使う

__metaclass__ = type  #表明为新式类
class Bird:
    def __init__(self):
        self.hungry = True
    def eat(self):
        if self.hungry:
            print &#39;Aaaah...&#39;
            self.hungry = False
        else:
            print &#39;No, thanks!&#39;
              
class SongBird(Bird):
         def __init__(self):
                 super(SongBird,self).__init__()
                 self.sound = &#39;Squawk!&#39;
         def sing(self):
                 print self.sound
>>> s.sing()
Squawk!
>>> s.eat()
Aaaah...
>>> s.eat()
No, thanks!

スーパー関数は新しいスタイルのクラスでのみ使用できます。現在のクラスとオブジェクトは、スーパー関数のパラメーターとして使用できます。関数によって返されたオブジェクトを呼び出すメソッドは、現在のクラスではなくスーパー クラスのメソッドを呼び出します。そうすれば、SongBird のコンストラクターで Bird を使用する代わりに、 super(SongBird, self) を直接使用できます。

Property

アクセサーは、getHeight や setHeight などの名前を使用して、いくつかのプロパティを取得または再バインドできる単純なメソッドです。特定の機能にアクセスしたときに何らかのアクションを実行する必要がある場合、このように状態変数をカプセル化することが重要です。以下のとおりです:

class Rectangle:
    def __init__(self):
        self.width = 0
        self.height = 0
    def setSize(self,size):
        self.width , self.height = size
    def getSize(self):
        return self.width , self.height
>>> r = Rectangle()
>>> r.width = 10
>>> r.height = 5
>>> r.getSize()
(10, 5)
>>> r.setSize((150,100))
>>> r.width
150

上記の例では、getSize メソッドと setSize メソッドは、size と呼ばれる架空のプロパティのアクセサー メソッドです。ここで、size は幅と高さで構成されるタプルです。

プロパティ関数

プロパティ関数は、前のセクションですでに Rectangle のようなクラスを作成している場合は、次のコード行を追加するだけです。新しいバージョンの Retangle では、 property 関数は、アクセサー関数がパラメーターとして使用されるプロパティを作成し (最初に値を取得し、次に値を割り当てます)、そのプロパティには size という名前が付けられます。これにより、実装方法を気にする必要がなくなり、幅、高さ、サイズを同じ方法で処理できるようになります。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。