Python 时间是对象的一种方法

Python 时间是对象的一种方法,python,Python,我有以下情况: 我想为多个对象的方法计时: class Foo(): def method(self): pass class Bar(): def method(self, x): print(x) 更具体地说,我希望有一个列表,该列表在每次调用该方法时附加执行时间 因此,基本上,我希望有一个函数time\u method,这样下面的代码将打印x对象执行方法method的3次时间 x = Foo() y = time_method(x, 'method') for i

我有以下情况: 我想为多个对象的方法计时:

class Foo():
  def method(self):
    pass
class Bar():
  def method(self, x):
    print(x)
更具体地说,我希望有一个列表,该列表在每次调用该方法时附加执行时间

因此,基本上,我希望有一个函数
time\u method
,这样下面的代码将打印x对象执行方法
method
的3次时间

x = Foo()
y = time_method(x, 'method')
for i in range(3):
  y.method()
print(y.get_time())

因此,基本上,
y
在任何地方都需要像
x
一样操作,除非调用了
y.method()
,在这种情况下,它还将记录执行时间。然后可以通过特定于y的
get\u time
方法访问执行时间列表。这个
time\u方法
函数应该适用于任何对象。

我认为它应该适用于:

import inspect

class time_method:
    def __init__(self,timedClass,method):
        self.timedClass = timedClass
        self.methodName = method
        self.measuredTimes = []
        self.all_methods = inspect.getmembers(timedClass, predicate=inspect.ismethod)
        self.set_all_methods();
        setattr(self, method, self.timeMethod)

    def timeMethod(self,*args,**kwargs):
        start = time.time()
        res=getattr(self.timedClass, self.methodName)(*args,**kwargs)
        end = time.time()
        self.measuredTimes.append(end-start)
        return res

    def get_time(self):
        return self.measuredTimes

    def set_all_methods(self):
        for method in self.all_methods:
            setattr(self, *method)

    def __getitem__(self,*args,**kwargs):
        return self.timeMethod(*args,**kwargs)

    def __repr__(self,*args,**kwargs):
        return self.timeMethod(*args,**kwargs)
所有应该工作的特殊功能都必须按照上面所示的模式实现。 当然,当初始化
time\u方法时,必须说:

y = time_method(x, '__getitem__')
然后您可以通过以下方式调用:

y[something]

我认为这应该奏效:

import inspect

class time_method:
    def __init__(self,timedClass,method):
        self.timedClass = timedClass
        self.methodName = method
        self.measuredTimes = []
        self.all_methods = inspect.getmembers(timedClass, predicate=inspect.ismethod)
        self.set_all_methods();
        setattr(self, method, self.timeMethod)

    def timeMethod(self,*args,**kwargs):
        start = time.time()
        res=getattr(self.timedClass, self.methodName)(*args,**kwargs)
        end = time.time()
        self.measuredTimes.append(end-start)
        return res

    def get_time(self):
        return self.measuredTimes

    def set_all_methods(self):
        for method in self.all_methods:
            setattr(self, *method)

    def __getitem__(self,*args,**kwargs):
        return self.timeMethod(*args,**kwargs)

    def __repr__(self,*args,**kwargs):
        return self.timeMethod(*args,**kwargs)
所有应该工作的特殊功能都必须按照上面所示的模式实现。 当然,当初始化
time\u方法时,必须说:

y = time_method(x, '__getitem__')
然后您可以通过以下方式调用:

y[something]

经过一些尝试和错误后,这似乎起到了作用:

import types
import time

def time_method(x, method):
    setattr(x, f'time_of_{method}', [])
    if method not in get_object_methods(x):
        print(f'Object {x} doesn\'t have method {method}')
    else:
        old_method = getattr(x, method)
        def new_method(self, *args, **kwargs):
            start = time.time()
            res = old_method(*args, **kwargs) 
            end = time.time()
            getattr(x, f'time_of_{method}').append(end-start)
            return res
        setattr(x, method, types.MethodType(new_method, x))
    return x
唯一的“问题”是它在适当的地方修改了x,但在我的用例中它不应该是一个问题

注意:这不适用于绑定到类的方法,如
\uuu getitem\uu

注2:对于多处理,事情会变得更加棘手,事实上,如果您的对象被发送到多线程,
f'time\u of_{method}
属性不会被共享,基本上也不会更新。解决方案是使用
Manager

import multiprocessing
manager = multiprocessing.Manager()

并在初始化时将
[]
替换为
manager.list()

经过一些尝试和错误后,这似乎起到了作用:

import types
import time

def time_method(x, method):
    setattr(x, f'time_of_{method}', [])
    if method not in get_object_methods(x):
        print(f'Object {x} doesn\'t have method {method}')
    else:
        old_method = getattr(x, method)
        def new_method(self, *args, **kwargs):
            start = time.time()
            res = old_method(*args, **kwargs) 
            end = time.time()
            getattr(x, f'time_of_{method}').append(end-start)
            return res
        setattr(x, method, types.MethodType(new_method, x))
    return x
唯一的“问题”是它在适当的地方修改了x,但在我的用例中它不应该是一个问题

注意:这不适用于绑定到类的方法,如
\uuu getitem\uu

注2:对于多处理,事情会变得更加棘手,事实上,如果您的对象被发送到多线程,
f'time\u of_{method}
属性不会被共享,基本上也不会更新。解决方案是使用
Manager

import multiprocessing
manager = multiprocessing.Manager()

在初始化时用
manager.list()
替换
[]

可能的重复我不确定我是否完全理解您想要做什么,但您应该检查模块。@mkrieger1可能的重复是的,但他希望有一个继承方法的类,但也记录执行时间。我不认为这是重复的,因为问题在于结构,而不是时间本身。那么具体的问题应该在问题中更加明确。可能的重复我不确定我是否完全理解你想要做什么,但是你应该检查一下这个模块,@mkrieger1可能是重复的。是的,但是他想要一个继承了一个方法的类,但同时也记录了一个执行时间。我不认为它是重复的,因为问题在于结构,而不是时间本身。那么具体问题应该在问题中更清楚。啊,我以为你应该使用类,我确实认为它有点优雅,实际上与OP中指定的工作方式完全相同。然而,有趣的解决方案。因此,您想调用
y[4]
?因为
y.\uuu getitem\uuuu4)
确实有效。当然,我们的想法是将x传递到外部代码来计时一些事情,在这些外部代码中,
\uuu getitem\uuuuu
从来没有直接使用过,而是由
[]
在类级别调用。遗憾的是,除了实现所有的特殊方法之外,我不认为有其他解决方法,你希望被使用的。我编辑了我的代码,所以现在您可以调用
y[4]
,并为
\uuuu repr\uuuu
添加了另一个示例,以表明所有特殊方法的实现方式都是相同的。当然,我想在库中对深度学习模型培训的不同步骤计时。基本上,我有一张清单,上面列出了我想做的事情。这些很容易识别。(例如,我想对数据集的访问计时,所以我想对数据集对象的
\uu getitem\uuu
方法计时),所以我想对所有对象/方法使用这个方法,我想计时,在库中调用fit并获取时间。啊,我以为你应该使用类,我确实认为它有点优雅,实际上与OP中指定的工作方式完全相同。然而,有趣的解决方案。因此,您想调用
y[4]
?因为
y.\uuu getitem\uuuu4)
确实有效。当然,我们的想法是将x传递到外部代码来计时一些事情,在这些外部代码中,
\uuu getitem\uuuuu
从来没有直接使用过,而是由
[]
在类级别调用。遗憾的是,除了实现所有的特殊方法之外,我不认为有其他解决方法,你希望被使用的。我编辑了我的代码,所以现在您可以调用
y[4]
,并为
\uuuu repr\uuuu
添加了另一个示例,以表明所有特殊方法的实现方式都是相同的。当然,我想在库中对深度学习模型培训的不同步骤计时。基本上,我有一张清单,上面列出了我想做的事情。这些很容易识别。(例如,我希望对数据集的访问进行计时,因此我希望对数据集对象的
\uuu getitem\uuu
方法进行计时),因此我希望对所有要计时的对象/方法使用此方法,在库中调用fit并获取时间。