如何在python的子类中检测方法重载?

2024-09-29 04:24:10 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个班是许多其他班的超级班。我想知道(在我的超级类的init中)子类是否重写了一个特定的方法。

我试着用类方法来实现这一点,但结果是错误的:

class Super:
   def __init__(self):
      if self.method == Super.method:
         print 'same'
      else:
         print 'different'

   @classmethod
   def method(cls):
      pass

class Sub1(Super):
   def method(self):
      print 'hi'

class Sub2(Super):
   pass

Super() # should be same
Sub1() # should be different
Sub2() # should be same

>>> same
>>> different
>>> different

超级类有没有办法知道一个子类是否重写了一个方法?


Tags: 方法selfinitdefpassbe子类method
3条回答

作为对答案https://stackoverflow.com/a/9437273/1258307的回复,由于我还没有足够的点数来评论它,除非您将im_func替换为__func__,否则它在python 3.4下无法工作(而且很可能是更高版本),因为函数不再具有__func__属性,而只具有绑定方法。

编辑:这是原始问题的解决方案(它适用于2.7和3.4,我假设所有其他版本介于两者之间):

    class Super:
        def __init__(self):
            if self.method.__code__ is Super.method.__code__:
                print('same')
            else:
                print('different')

        @classmethod
        def method(cls):
            pass

    class Sub1(Super):
        def method(self):
            print('hi')

    class Sub2(Super):
        pass

    Super() # should be same
    Sub1() # should be different
    Sub2() # should be same

结果如下:

same
different
same

你可以用你自己的装潢师。但这是一个技巧,只适用于控制实现的类。

def override(method):
  method.is_overridden = True
  return method

class Super:
   def __init__(self):
      if hasattr(self.method, 'is_overridden'):
         print 'different'
      else:
         print 'same'
   @classmethod
   def method(cls):
      pass

class Sub1(Super):
   @override
   def method(self):
      print 'hi'

class Sub2(Super):
   pass

Super() # should be same
Sub1() # should be different
Sub2() # should be same

>>> same
>>> different
>>> same

通过比较实例字典的公共子集和基类本身,这样做似乎是最简单和足够的,例如:

def detect_overridden(cls, obj):
  common = cls.__dict__.keys() & obj.__class__.__dict__.keys()
  diff = [m for m in common if cls.__dict__[m] != obj.__class__.__dict__[m]]
  print(diff)

def f1(self):
  pass

class Foo:
  def __init__(self):
    detect_overridden(Foo, self)
  def method1(self):
    print("Hello foo")
  method2=f1

class Bar(Foo):
  def method1(self):
    print("Hello bar")
  method2=f1 # This is pointless but not an override
#  def method2(self):
#    pass

b=Bar()
f=Foo()

运行并给出:

['method1']
[]

相关问题 更多 >