Python 使用decorator模式在函数调用后保留文件指针

Python 使用decorator模式在函数调用后保留文件指针,python,methods,decorator,Python,Methods,Decorator,我需要一个装饰或任何其他整洁的设计模式的功能是处理文件。主要目的是在函数作用于文件后,将文件指针保持在原来的位置 这是我的代码,包括一些虚拟测试。问题是,即使我将args和kwargs传递给decorator,decorator也不能处理实例方法。我不知道如何设计代码 import unittest from cStringIO import StringIO def remain_file_pointer(file_obj): def wrap(f): def wr

我需要一个装饰或任何其他整洁的设计模式的功能是处理文件。主要目的是在函数作用于文件后,将文件指针保持在原来的位置

这是我的代码,包括一些虚拟测试。问题是,即使我将args和kwargs传递给decorator,decorator也不能处理实例方法。我不知道如何设计代码

import unittest
from cStringIO import StringIO


def remain_file_pointer(file_obj):
    def wrap(f):
        def wrapped_f(*args, **kwargs):
            old_position = file_obj.tell()
            f(*args, **kwargs)
            file_obj.seek(old_position, 0)
        return wrapped_f
    return wrap


class TestRemainFilepointer(unittest.TestCase):

    def test_remains_filepointer(self):
        dummy_file = StringIO('abcdefg')

        @remain_file_pointer(dummy_file)
        def seek_into_file(dummy_file):
            dummy_file.seek(1, 0)

        self.assertEqual(0, dummy_file.tell())
        seek_into_file(dummy_file)
        self.assertEqual(0, dummy_file.tell())

    def test_remains_filepointer_in_class_method(self):

        class FileSeekerClass(object):
            def __init__(self):
                self.dummy_file = StringIO('abcdefg')

            @remain_file_pointer(self.dummy_file)
            def seek_into_file(self):
                self.dummy_file.seek(1, 0)

        fileseeker = FileSeekerClass()
        self.assertEqual(0, fileseeker.dummy_file.tell())
        fileseeker.seek_into_file()
        self.assertEqual(0, fileseeker.dummy_file.tell())
更新: 我只是想澄清一下基本想法:

decorator应该接受一个参数,它是一个文件处理程序,并在实际函数操作文件之前存储位置。之后,指针应设置到旧位置。这应该适用于独立函数和方法


我下面的答案通过假设函数中的最后一个参数是文件处理程序来解决问题。

我不会将此标记为最终答案,因为我非常确定有更好的设计

我提出了一个解决方案,假设数据操作函数的最后一个参数是文件处理程序,并通过args[-1]访问它:


不要忘记包装函数的返回值。@RSamuelKlatchko啊,非常感谢!我刚刚为此添加了更多的单元测试。
def remain_file_pointer(f):
    """Remain the file pointer position after calling the decorated function

    This decorator assumes that the last argument is the file handler.

    """
    def wrapper(*args, **kwargs):
        file_obj = args[-1]
        old_position = file_obj.tell()
        return_value = f(*args, **kwargs)
        file_obj.seek(old_position, 0)
        return return_value
    return wrapper