Why is Python not supporting full derivation of built-in file class?

Pierre Rouleau prouleau at impathnetworks.com
Sat Apr 23 17:30:52 EDT 2005


Greetings,

I'm wondering why the >> operator does not use the write() method of a 
class derived from the built-in file class as in DerivedFile below.

In the following example:

- StringFile is just a file-like string accumulation class that can be 
used in place of a real file to accumulate strings that would otherwise 
be printed.  Works fine, can accumulate strings with the >> operator, 
but is not a true file.

- DelegatedFile is a new-style class, a true file class, which provides 
all the features of a real file through delegation.  It also works fine 
and can accumulate string with the >> operator.

- DerivedFile is a new-style class that is derived from file.  It 
behaves like a true file, but the >> operator does not call its write() 
method.  Why is that?

Is this related to the fact that on object from that class is seen as a 
file (as shown at the end of the code session below)?

Is this intended or is it a flaw in the language that is waiting to be 
fixed?


 >>> import sys
 >>> sys.ps2=' ... '; sys.ps1=' >>> '
  >>> def hello(stream=None):
  ...     if stream is None:
  ...         stream = sys.stdout
  ...     print >> stream, "Bonjour!"
  ...

  >>> # Using a duck-typing to define a class
  ... # that behaves like a file for writing only.
  ... class StringFile:
  ...     "A file-like object to accumulate strings"
  ...     # print >> aStringFile works
  ...     def __init__(self):
  ...         self.strings = []
  ...     def write(self, text):
  ...         self.strings.append(text)
  ...     def writelines(self, lines):
  ...         self.strings.extend(lines)
  ...

  >>> # Using delegation to file to create a class that
  ... # extends the built-in file object.
  ... class DelegatedFile(object):
  ...     "A file-like object to accumulate strings"
  ...     # print >> aStringFile works
  ...     def __init__(self, *args):
  ...         self.strings = []
  ...         self._file = file(*args)
  ...     def __getattr__(self, name) :
  ...         return getattr(self._file, name)
  ...     def write(self, text):
  ...         self.strings.append(text)
  ...         self._file.write(text)
  ...     def writelines(self, lines):
  ...         self.strings.extend(lines)
  ...         self._file.writelines(lines)
  ...

  >>> # Using derivation from file to create a class
  ... # that extends file. But has a flaw in the use of the >> operator!
  ... class DerivedFile(file):
  ...     "A file object that accumulated written strings"
  ...     # print >> a DerivedFile doe NOT work!
  ...     def __init__(self, *args):
  ...         self.strings = []
  ...         file.__init__(self, *args)
  ...     def write(self, text):
  ...         self.strings.append(text)
  ...         file.write(self, text)
  ...         # super(DerivedFile, self).write(text)
  ...     def writelines(self, lines):
  ...         self.strings.extend(lines)
  ...         file.writelines(self, lines)
  ...         # super(DerivedFile, self).writelines(lines)
  ...

  >>> hello()
Bonjour!
  >>>

  >>> sf = StringFile()
  >>> hello(sf)
  >>> sf.strings
['Bonjour!', '\n']
  >>>

  >>> dg = DelegatedFile("temp.txt","w")
  >>> hello(dg)
  >>> dg.close()
  >>> dg.strings
['Bonjour!', '\n']
  >>> for line in file("temp.txt"): print line
  ...

Bonjour!

  >>> df = DerivedFile("temp2.txt","w")
  >>> hello(df)
  >>> df.close()
  >>> df.strings
[]
  >>> for line in file("temp2.txt"): print line
  ...

Bonjour!

  >>>
  >>> sf
<__main__.StringFile instance at 0x008D86C0>
  >>> dg
<__main__.DelegatedFile object at 0x008D50B0>
  >>> df
<closed file 'temp2.txt', mode 'w' at 0x0087FA28>
  >>>

--

Pierre Rouleau



More information about the Python-list mailing list