【问题标题】:Retain file pointer after function call, using the decorator pattern函数调用后保留文件指针,使用装饰器模式
【发布时间】:2014-11-29 16:20:58
【问题描述】:

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

这是我的代码,包括一些虚拟测试。问题是装饰器不适用于实例方法,即使我将argskwargs 传递给它。我不知道如何设计代码……

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())

更新: 只是为了澄清基本思想:

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

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

【问题讨论】:

    标签: python methods decorator


    【解决方案1】:

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

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

    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
    

    【讨论】:

    • 不要忘记包装函数的返回值。
    • @RSamuelKlatchko 啊,非常感谢!我刚刚为此添加了更多单元测试。
    猜你喜欢
    • 2020-06-08
    • 2011-08-25
    • 1970-01-01
    • 1970-01-01
    • 2013-05-07
    • 1970-01-01
    • 1970-01-01
    • 2010-09-13
    • 2017-05-25
    相关资源
    最近更新 更多