我可以指定另一个类的instance-method作为我的方法的变量吗?

时间:2011-04-27 11:53:10

标签: python refactoring instance-methods

我还是相对较新的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

但是我在每个write方法中都有一个大的冗余代码块:

    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。会喜欢额外的解释或指导。感谢。

2 个答案:

答案 0 :(得分: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)

答案 1 :(得分: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