I’m still relatively new to python, 1-2 years of solo-learning, and am trying to improve my code structure so I’m refactoring some old programs I wrote. In one program, I defined a couple of methods for writing files. The first uses, “write” to dump a huge http-response. The second uses “writelines” to dump various derived lists, e.g. lists of links, or forms, or other extracted data.
I’d originally factored out the naming of the file:
@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
But I have a large redundant block of code in each write method:
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
I’d like to be able to add a variable to each function that specifies the write method to use, e.g. (writeMethod=writelines). I considered just passing in a string and using one of the black-magic functions– exec() I guess– but that can’t possibly be right since no one ever seems to use those functions. This whole example may be relatively silly, since I could just work around it, but I decided I’d benefit from knowing how to pass these sorts of instance-methods (is that the right term?). Is this related to binding and unbinding? All I need for a good answer is the syntax required to pass ‘write,’ ‘writelines’ etc. Could be simple as: writeMethod = insert_your_syntax_here. Would love additional explanation or guidance though. Thanks.
You can get a “bound method” from an object, which is then callable as a function without having a reference to the object.
However, that’s not useful for you, as you create the object you want to use only in the method – you can’t pass it in there as bound method. You can factor out the creation of
fullpath, although this only saves you half of the redundancy. One option, which I’d consider overkill, would be passing a callback which return the function to use for writing.Another option would be a decorator to factor out all the common parts and push the rest into a callback, the decorated function:
# …