[Tutor] feedback on simple python code

Peter Otten __peter__ at web.de
Tue Feb 28 03:32:54 EST 2017


Ryan Smith wrote:

> Hi all,
> 
> New python student here. I have been using O¹reilly¹s "Python Beyond the
> Basics: Object Oriented Programming video series". In one of the
> assignments we are to write a simple inheritance hierarchy of three
> classes that write to text files. I have actually written the code for the
> assignment and it runs as well as meets the requirements of the
> assignment. I am posting to get feedback on how I can improve this and
> making it more pythonic and concise.
> 
> Please keep in mind that I am simply ³simulating" writing to a log file
> and a tabbed delimited file, so I¹m not necessarily looking for which
> modules I could have to create actual log files or writing to actual csv
> files. The output of the code should be two text files with text written
> to them that have been passed to the instance of each respective object.
> 
> #!/usr/bin/env python
> 
> import abc
> import datetime
> 
> class WriteFile(object):
>     __metaclass__ = abc.ABCMeta
>     
>     
>     @abc.abstractmethod
>     def write(self,text):

You might run a tool like https://pypi.python.org/pypi/pycodestyle over your 
code to ensure it follows common standards.

>         """Write to file"""
>         return
>     
> 
> class LogFile(WriteFile):
>     def __init__(self,fh):
>     self.fh = fh
>         
> 
>     def write(self, text):
>     date = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
>     entry = "{0} {1}{2}".format(date, text, '\n')
>     with open(self.fh, 'a') as f:
>     f.write(entry)
> 
> class DelimWrite(WriteFile):
>     def __init__(self, fh, delim):
>     self.fh = fh
>     self.delim = delim
>         
> 
>     def write(self, text):
>     with open(self.fh, 'a') as f:
>         entry = ""
>         for item in text:
>             if self.delim in item:
> entry += ' "{0}"{1} '.format(item,self.delim)

What will happen if text contains double quotes?

> else:
>                 entry += item+self.delim

Have a look at the str.join() method. Example:

>>> ",".join(["foo", "bar", "baz"])
'foo,bar,baz'

>         f.write(entry.strip(self.delim) + '\n')

I will mention another "principle", DRY (don't repeat yourself), i. e. do 
not write the same code twice.

When I look at your code I see that both DelimWrite and LogFile open a file. 
If you want modify your code to accept file objects like sys.stdout you have 
to make changes in both subclasses. To avoid that you might put the file-
writing part into a separate method:

class WriteFile(object):
    def __init__(self, file):
        self.file = file

    def write_record(self, record):
        with open(self.file, "a") as f:
            f.write(self.format_record(record))

    def format_record(self, record):
        return record


class LogFile(WriteFile):
    def format_record(self, record):
        date = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        return "{0} {1}\n".format(date, record)


class DelimWrite(WriteFile):
    quote = '"'
    def __init__(self, file, delimiter):
        super(DelimWrite, self).__init__(file)
        self.delimiter = delimiter

    def escaped(self, value):
        value = str(value)
        if self.delimiter in value:
            quote = self.quote
            value = '"{}"'.format(value.replace(quote, quote + quote))
        return value

    def format_record(self, record):
        escaped_rows = (self.escaped(value) for value in record)
        return self.delimiter.join(escaped_rows) + "\n"




More information about the Tutor mailing list