2

我对 python 还是比较陌生,1-2 年的单独学习,并且正在尝试改进我的代码结构,所以我正在重构我编写的一些旧程序。在一个程序中,我定义了几种写入文件的方法。第一个使用“写”来转储一个巨大的 http 响应。第二个使用“writelines”转储各种派生列表,例如链接列表、表单或其他提取数据。

我最初考虑了文件的命名:

    @property
    def baseFilename(self):
        unacceptable = re.compile(r'\W+')
        fname = re.sub(unacceptable,'-',self.myUrl)
        t = datetime.datetime.now()
        dstring = "%s%s%s%s%s%s" % (t.year, t.month, t.day, t.hour, t.minute, t.second)
        fullname = fname + '_' + dstring + '.html'
        return fullname

但是我在每个写入方法中都有大量冗余代码块:

    def writeFile(self, someHtml, writeMethod=write, prefix="RESPONSE_"):
        '''The calling functions will supply only the data to be written and 
           static prefixes, e.g. "full_" for the entire http-response.
        '''

       fullpath = self.myDump + prefix + self.baseFilename
       with open(fullpath, 'w') as h:
           h.write(someHtml)
           h.close()
       print "saved %s" % fullpath
       return fullpath

    def writeList(self, someList, prefix="mechList_"):
        '''Like write file but for one of the many lists outputted.  
           How do I refactor this, since redundant?
        '''

        fullpath = self.myDump + prefix + self.baseFilename
        with open(fullpath, 'w') as h:
            h.writelines(someList)
            h.close()
        print "saved %s" % fullpath
        return fullpath

我希望能够为每个指定要使用的写入方法的函数添加一个变量,例如(writeMethod=writelines)。我考虑只传入一个字符串并使用其中一个黑魔法函数——我猜是 exec() ——但这不可能是正确的,因为似乎没有人使用过这些函数。这整个例子可能比较傻,因为我可以解决它,但我决定知道如何传递这些实例方法(这是正确的术语吗?)。这与绑定和解除绑定有关吗?我需要一个好的答案是传递'write','writelines'等所需的语法。可能很简单:writeMethod = insert_your_syntax_here。不过希望得到更多的解释或指导。谢谢。

4

2 回答 2

2

您可以从对象中获取“绑定方法”,然后可以将其作为函数调用,而无需引用该对象。

f = obj.method
f(args)
# is equivalent to
obj.method(args)

但是,这对您没有用,因为您创建了只想在方法中使用的对象 - 您不能将它作为绑定方法传递给那里。您可以考虑创建fullpath,尽管这只会为您节省一半的冗余。一种我认为过分的选择是传递一个回调,该回调返回用于写入的函数。

另一种选择是装饰器将所有公共部分分解出来并将其余部分推入回调,即装饰函数:

def uses_file(prefix_default):
    def decorator(f):
        @functools.wraps(f)
        def decorated(self, data, prefix=prefix_default):
            fullpath = obj.myDump + prefix + obj.baseFilename
            with open(fullpath, 'w') as h:
                f(h, data, prefix)
            print "saved", % fullpath
            return fullpath
        return decorated
    return decorator

# ...

@uses_file(default_prefix="RESPONE_")
def writeFile(self, someHtml, prefix):
   '''...'''
   h.write(someHtml)

@uses_file(default_prefix="mechList_")
def writeList(self, someList, prefix):
    '''...'''
    h.writelines(someList)
于 2011-04-27T12:17:58.567 回答
1

有不同的方法可以做到这一点,例如使用 lambdas:

def writeFile(self, someHtml, writeMethod=lambda f, data: f.write(data), 
              prefix="RESPONSE_"):
    '''The calling functions will supply only the data to be written and 
       static prefixes, e.g. "full_" for the entire http-response.
    '''

   fullpath = self.myDump + prefix + self.baseFilename
   with open(fullpath, 'w') as h:
       writeMethod(h, someHtml)
       h.close()
   print "saved %s" % fullpath
   return fullpath
于 2011-04-27T12:17:56.350 回答