Python 当我没有';我不想复制父类中的每个方法

Python 当我没有';我不想复制父类中的每个方法,python,dynamic,methods,Python,Dynamic,Methods,如果这个问题已经在某个地方得到了回答,我深表歉意,但如果已经得到了回答,我无法找到答案 我希望以这样的方式创建父类的子类:在每次调用相应的父类方法之前都会有延迟(例如,time.sleep())。我希望这样做,我不需要复制子类中的每个父类方法。事实上,我希望有一个泛型方法,可以与几乎任何父类一起工作——这样我甚至不需要知道所有的父类方法 在实例化子类时将指定延迟 例如: class Parent(): .... def method1(self): ....

如果这个问题已经在某个地方得到了回答,我深表歉意,但如果已经得到了回答,我无法找到答案

我希望以这样的方式创建父类的子类:在每次调用相应的父类方法之前都会有延迟(例如,
time.sleep()
)。我希望这样做,我不需要复制子类中的每个父类方法。事实上,我希望有一个泛型方法,可以与几乎任何父类一起工作——这样我甚至不需要知道所有的父类方法

在实例化子类时将指定延迟

例如:

class Parent():
    ....
    def method1(self):
        ....
    def method2(self):
        ....


class Child(Parent):
    def __init__(self, delay)
        self.delay = delay
        ....

child = Child(1)

调用
child.method1()
会导致在调用
Parent.method1()
之前延迟1秒。

实际上,这里的设计涉及策略对象

最好的方法是修复父类以包含对“延迟对象”的调用。默认延迟对象不执行任何操作

这违反了功能集所希望的“这样我甚至不需要知道所有父类方法”

方法查找没有与
\uuuuuu getattribute\uuuu
相对应的方便的
\uuuuuu getmethod\uuuuuuuu
;这种差距使得很难利用Python的内部进行方法调用

class Parent( object ):
    delay= ZeroDelay()
    def method1(self):
        self.delay()
        ....
    def method2(self):
        self.delay()
        ...

class ZeroDelay( object ):
    def __call__( self ):
        pass

class ShortDelay( ZeroDelay ):
    def __init__( self, duration=1.0 )
        self.duration= duration
    def __call__( self ):
        time.sleep( self.duration )

class Child( Parent ):
    delay= ShortDelay( 1 )

编辑:当然,您也可以装饰每个方法

def delayed( delayer ):
    def wrap( a_method ):
        def do_delay( *args, **kw ):
            delayer()
            return a_method( *args, **kw )
        return do_delay
    return wrap


class Parent( object ):
    delay= ZeroDelay()
    @delayed( self.delay )
    def method1(self):
        self.delay()
        ....
    @delayed( self.delay )
    def method2(self):
        self.delay()
        ...

你可以通过使用这种方法来实现你想要的

更新:根据delnan的评论更新


更新2:根据delnan的第二条评论更新。Lott解决方案是一个很好的解决方案。如果您需要更大的粒度(即仅延迟某些方法,而不是所有方法),您可以使用decorator:

from time import sleep

def delayed(func):
    '''This is the decorator'''
    def wrapped(*args, **kwargs):
        sleep(2)
        func(*args, **kwargs)
    return wrapped

class Example(object):

    @delayed
    def method(self, str):
        print str

e = Example()
print "Brace! I'm delaying!"
e.method("I'm done!")
其思想是在要删除的方法的定义之前添加
@delayed


编辑:更精细:设置任意延迟:

from time import sleep

def set_delay(seconds):
    def delayed(func):
        '''This is the decorator'''
        def wrapped(*args, **kwargs):
            sleep(seconds)
            func(*args, **kwargs)
        return wrapped
    return delayed

class Example(object):

    @set_delay(1)
    def method(self, str):
        print str

    @set_delay(2)
    def method_2(self, str):
        print str

e = Example()
print "Brace! I'm delaying!"
e.method("I'm done!")
e.method_2("I'm also done!")

我认为前面给出的答案并没有真正解决您延迟父类中所有方法的具体需求,也不一定要去修饰它们。您说过您不想在子类中复制父类方法,只是为了延迟它们。这个答案使用了与S.Lott相同的延迟包装器,但也使用了元类(http://www.voidspace.org.uk/python/articles/metaclasses.shtml)


MetaClassFactory将每个函数包装在延迟装饰器中。如果要确保某些内置函数(如init函数)没有延迟,可以在MetaClassFactory中检查该名称并忽略它。

这会延迟属性访问,而不是方法调用。即使您将其限制为方法访问,它仍然不能像绑定方法那样工作(
f=obj.method;对于xs中的x:f(xs)
)。我修复了我的
子类实现,以便只在方法调用时睡眠。我不明白你的边界方法是什么意思。。。你能详细解释一下吗?我不知道你的更新是如何修复的。如果检索到的值是真实的,它将休眠,如果不可调用,它将崩溃。关于绑定方法:考虑我的第一个注释中给出的例子,<代码> f= Obj.To方法;对于x-in-xs:f(xs)
。它在循环之前休眠一次,尽管该方法被调用了
len(xs)
次。@delnan要么我误解了你的意思,要么你错了。当我做
f=obj.method时;对于范围(3)中的i:f()
则程序休眠3次。。。(我解决了呼叫问题)对不起,我错了。我只是浏览了一下你的更新代码。我不知道你当时已经解决了这个问题。推迟某些方法可能是明智的。例如,不以下划线开头的“public”方法。否则,可能会出现大量嵌套延迟。比如说,方法a经常调用平凡的方法b,比如
len
。我不会采用“延迟所有方法”的方法,但我会给出一个要修饰的方法的明确列表。然而,我真的很喜欢这种元类方法,因为你不必为你想要延迟的每个方法编写高度冗余的代码。我想将其增强为类似于
\uuu元类\uuuu=Delayed(“abc”、“def”、“ghi”)
@Anonymouse的东西-这是用于包装多个装饰器的吗?是的,您可以让MetaClassFactory接受*args而不是单个函数,然后循环并将它们包装在
if类型(属性)下==FunctionType:
我想知道装饰器解决方案是否满足了
这样做的要求,即我不需要复制子类中的每个父类方法
?@gecco-当然不需要。如我所述,S.Lott的解决方案是好的,如果OP希望获得更高的粒度,我的解决方案是另一种选择。:)哦,我的错。。。不知怎的,我错过了你指定的:-p我已经对S.Lott的帖子投了更高的票,但我想知道为什么我的不是更好的解决方案?!我认为第一个
delayed
decorator中缺少一个返回,它应该是
returnfunc(*args,**kwargs)
可以编辑父类来实现此行为吗?您提到了缺少一个方便的
\uuu getMethod\uuu
。你能解释一下为什么
\uuuu getattribute\uuuu
不合适吗?我想这是有原因的,因为我的答案是没有被提升;-)
from time import sleep

def set_delay(seconds):
    def delayed(func):
        '''This is the decorator'''
        def wrapped(*args, **kwargs):
            sleep(seconds)
            func(*args, **kwargs)
        return wrapped
    return delayed

class Example(object):

    @set_delay(1)
    def method(self, str):
        print str

    @set_delay(2)
    def method_2(self, str):
        print str

e = Example()
print "Brace! I'm delaying!"
e.method("I'm done!")
e.method_2("I'm also done!")
#!/usr/bin/env python

from types import FunctionType
import time


def MetaClassFactory(function):
    class MetaClass(type):
        def __new__(meta, classname, bases, classDict):
            newClassDict = {}
            for attributeName, attribute in classDict.items():
                if type(attribute) == FunctionType:
                    attribute = function(attribute)

                newClassDict[attributeName] = attribute
            return type.__new__(meta, classname, bases, newClassDict)
    return MetaClass


def delayed(func):
    def wrapped(*args, **kwargs):
        time.sleep(2)
        func(*args, **kwargs)
    return wrapped

Delayed = MetaClassFactory(delayed)

class MyClass(object):
    __metaclass__ = Delayed 

    def a(self):
        print 'foo'

    def b(self):
        print 'bar'