4

Pythonのスーパー関数に問題があります。次の2つのクラスがあるとします。

class A(object):
     x=5
     def p(self):
             print 'A'
     def f(self):
             self.p()
             self.x+=1

class B(A):
    def p(self):
             print 'B'
    def f(self):
             super(B, self).f()
             self.x*=2

b = B()
b.f()

その場合、bxは12に等しくなりますが、関数は「A」ではなく「B」を出力します。必要なのはBpの代わりにApを実行することですが、どうすればそれを達成できますか?

御時間ありがとうございます :)


編集:わかりました、私の悪い例のために、あなたは私の実際の状況についてのいくつかの詳細を見逃したと思います。実際のコードに取り掛かりましょう。私はこれらの2つのクラス(Djangoモデル)を持っています:

class Comment(Insert, models.Model):

    content = models.TextField()
    sender = models.ForeignKey('logic.User')
    sent_on = models.DateTimeField(auto_now_add=True)

    def __insert__(self):
        self.__notify__()

    def __notify__(self):
        receivers = self.retrieve_users()
        notif_type = self.__notificationtype__()
        for user in receivers:
            Notification.objects.create(
                object_id=self.id,
                receiver=user,
                sender_id=self.sender_id,
                type=notif_type
            )

    def __unicode__(self):
        return self.content

    class Meta:
        abstract = True


class UserComment(Comment):

    is_reply = models.BooleanField()
    reply_to = models.ForeignKey('self', blank=True,
                                null=True, related_name='replies')
    receiver = models.ForeignKey('User', related_name='comments')

    def __insert__(self):
        super(UserComment, self).__insert__()
        self.__notify__()

    def __notification__(self, notification):
        if self.is_reply:
            return '%s has replied your comment' % self.sender
        return super(UserComment, self).__notification__(notification)

    def __notify__(self):
        # Notification objects "should" be created by Comment's __notify__
        Update.objects.create(
            object_id=self.id,
            target=self.receiver,
            type=self.__updatetype__(),
        )

    @classmethod
    @cache(prop_name='_notificationtype')
    def __notificationtype__(cls):
        return NotificationType.objects.get(name='USER_COMMENT')

    @classmethod
    @cache(prop_name='_updatetype')
    def __updatetype__(cls):
        return UpdateType.objects.get(name='USER_COMMENT')

    def retrieve_users(self):
        return [self.receiver]  # retrieve_users MUST return an iterable

問題は、両方のモデルのメソッドにあります__insert__。は、オブジェクトがDBに最初に記録されたときに呼び出されるメソッドであり、主に通知目的で使用します。次に、これが私がやりたいことです:__notify____insert__

  1. UserCommentオブジェクトを作成し、保存します
  2. UserCommentインスタンスを呼び出す__insert__
  3. コメントを呼び出す、コメント__insert__を呼び出す必要があります__notify__
  4. __notify__からUserCommentインスタンスを呼び出す__insert__

これは多かれ少なかれ簡単な方法で可能ですか、それともコードをリファクタリングする必要がありますか?
すべての回答に改めて感謝します。

4

3 に答える 3

5

あなたはあなたが実行したいと言うだけですA.p()

class B(A):
    def p(self):
        print 'B'
    def super_p(self):
        return A.p(self) # prints 'A'

それが確実に実行されるようにしたい場合A.p()は、のメソッドから明示的に呼び出すのが最善の策Bです。Rajeshが言ったように、この状況を回避する最善の方法は、基本クラスで呼び出す予定のメソッドをオーバーライドしないことです。

スーパークラスがサブクラスについて何も知る方法はありません。たとえば、サブクラスBをインスタンス化し、それがメソッドを継承してメソッドx()をオーバーライドするp()場合、を呼び出すと、Aの(オーバーライドされた)定義ではなく、 Bの定義x()が呼び出されます。これはまさに期待すべきことです。ハイブリッドクラスを作成し、メソッドの1つをオーバーライドしました。p()

于 2012-08-15T23:28:20.613 に答える
1

これはインスタンスをself参照し、bはBのインスタンスであるため、self.p()はAではなくを参照することに注意してください。したがって、クラスBからmethod p() in class Bメソッドを削除するか、Bから次のように明示的に呼び出します。p()A's p()

class B(A):
    def p(self):
             super(B, self).p()
             print 'B'
    def f(self):
             super(B, self).f()
             self.x*=2

または、Aのpa staticmethodを作成し、クラスAのf()から、を使用して呼び出しA.p()ます。特に、そのメソッドからクラスにアクセスする必要がない場合は、pを「メソッド」ではなく「関数」にします

class A(object):
    x=5
    @staticmethod
    def p():
        print 'A'
    def f(self):
        A.p()
        self.x+=1

このBを使用すると、出力は次のようになります。

>>> b = B()
>>> b.f()
A
>>> b.x
12
>>> b.p()
A
B

Bがb.p()呼び出しでのみ印刷され、そうであったときは印刷されなかったことに注意してくださいb.f()

于 2012-08-16T01:07:06.870 に答える
0

コード内のイベントの進行を監視します。

self.x = 5

self.x = 6

self.x = 12

あなたのコードを考えると、それが出力として12を取得する唯一の方法です。ただし、BではなくクラスAから実行すると、次の動作が発生します。

self.x = 5

self.x = 6

あなたはその振る舞いを望んでいるように私には思えます。唯一の違いは行にありself.x += 2ます。

これは、メソッドを別の何かにオーバーロードした後、子クラスがそのスーパーのメソッドを正確に動作するようにしたかった(または期待した)理由についてのより興味深い質問につながります!A関数を実行しますが、関数x+1B実行します(x+1)*2が、これは明らかに異なります。メソッドのオーバーロードの基本的な目的は、親クラスとは異なる動作を示すことです。

于 2012-08-15T23:47:01.083 に答える