3

我有一个子类,它将图形功能添加到实现算法的超类中。因此,除了一些额外的初始化函数外,这个子类只需要在执行完超类中的每个算法计算函数后刷新图形即可。

课程:

class graph(algorithms):
  ... #initialization and refresh decorators

  @refreshgraph
  def algorithm1(self, *args, **kwargs):
    return algorithms.algorithm1(self, *args, **kwargs)

  @refreshgraph
  def algorithm2(self, *args, **kwargs):
    return algorithms.algorithm2(self, *args, **kwargs)

  ... #and so on

是否有一种 Python 的方式来自动装饰超类中定义的所有非私有方法,这样如果我在那里添加一个新算法,我就不需要在我的子类中明确提及它?我还希望能够明确排除一些超类的方法。

4

2 回答 2

3

默认情况下,子类总是从父类获取所有方法。如果您希望模拟其他语言用于隐私的行为(例如 C# 中的“私有”或“受保护”修饰符),您有两种选择:

1)Python约定(这只是一个约定)是名称中带有单个前导下划线的方法不是为从定义类外部访问而设计的。

2) 带有前导下划线的名称在字节码中被破坏,因此它们对以自己名称命名的其他代码不可见。ParentClass.__private 在 ParentClass 中可见,但只能从 ParentClass 外部作为 ParentClass._ParentClass__private 访问。(这里有很好的解释)。Python 中没有什么是真正私有的;)

要覆盖继承的方法,只需在派生类中定义相同的名称。要在派生类中调用父类方法,您可以像在示例中那样执行此操作,也可以使用super

def algorithm2(self, *args, **kwargs):
  super(graph, self).algorithm2(self, *args, **kwargs)
  # do other derived stuff here....
  self.refresh()
于 2013-09-12T01:47:14.633 回答
0

这很难看,但我认为它可以满足您的要求,但没有继承:

class DoAfter(object):
    def __init__(self, obj, func):
        self.obj = obj
        self.func = func

    def __getattribute__(self, attr, *a, **kw):      
        obj = object.__getattribute__(self, 'obj')

        if attr in dir(obj):
            x = getattr(obj, attr)

            if callable(x):
                def b(*a, **kw):
                    retval = x(*a, **kw)
                    self.func()
                    return retval
                return b
            else:
                return x

        else:
            return object.__getattribute__(self, attr)

像这样使用它:

>>> class A(object):
...     def __init__(self):
...         self.a = 1
... 
...     def boo(self, c):
...         self.a += c
...         return self.a
>>> def do_something():
...     print 'a'
>>> a = A()
>>> print a.boo(1)
2
>>> print a.boo(2)
4
>>> b = DoAfter(a, do_something)
>>> print b.boo(1)
a
5
>>> print b.boo(2)
a
7

A每次A.boo调用时递增一个计数器。aDoAfter 包装了 A,因此可以调用实例中的任何方法,就好像它是b. 请注意,每个方法都以这种方式包装,因此do_something()每当访问方法时都会调用它。

这几乎没有经过测试,不推荐,而且可能是个坏主意。但是,我认为它可以满足您的要求。

编辑:通过继承来做到这一点:

class graph(algorithms):
    def refreshgraph(self):
        print 'refreshgraph'

    def __getattribute__(self, attr):
        if attr in dir(algorithms):
            x = algorithms.__getattribute__(self, attr)

            if callable(x):
                def wrapped(*a, **kw):
                    retval = x(*a, **kw)
                    self.refreshgraph()
                    return retval
                return wrapped
            else:
                return x

        else:
            return object.__getattribute__(self, attr)
于 2013-09-12T02:34:11.617 回答