Reading Until EOF

Alex Martelli aleaxit at yahoo.com
Tue Oct 21 18:13:27 EDT 2003


Scott Brady Drummonds wrote:
   ...
>   #  This is enclosed in a 'try' block
>   file = open(...)
>   while object = Object(file):
>     self.list = self.list + [object]
> 
> With this implementation, the file reading stops both with an exception
> (raised by a parsing error, as an example) and when the Object constructor
> returns something that makes the while conditional fail.  However, therein
> lies the rub: I don't know how to do this in Python.
> 
> Is there a way for me to make the second implementation work?  Is there an

It's a bad idea, as others have pointed out, but, sure -- as long as you
change this into something like:
    while True:
        object = Object(file)
        if object is None: break
        self.list.append(object)
or -- perhaps a bit more Pythonically, but otherwise equivalently:
    def Objfromfile(): return Object(file)
    self.list.extend([ object for object in iter(Objfromfile, None) ])    

> "empty" operator in Python that I could overload?  Can I have a
> constructor return 'null'?

I'm not sure what an "empty operator" would be.  You can easily
make a function return None; use a factory function instead of the
bare ctor and you're all set (you'd do it that way in C++ too, and
there you'd have no alternative to that OR an exception).

You _CAN_ have Object.__new__ return what you want -- iff it
returns an instance of Object, that is then passed to Object.__init__.

Basically calling Object(xxx) is like calling a function that does:
def equivalent(xxx):
    result = Object.__new__(Object, xxx)
    if isinstance(result, Object): Object.__init__(result, xxx)
    return result
but basically, for that to be used the way you want you need to do
almost all the work in Object.__new__ rather than in __init__ --
you can afford to let the latter be called only when you're fully
satisfied you'll be able to construct an Object instance just fine.

It IS a bad idea, but, if you insist, assuming that Object just
needs a field of exactly 4 bytes it reads from the file, period;
where you now have
    def __init__(self, file):
        self.field = file.read(4)
        if len(self.field) != 4: raise EOFError
have no __init__ at all and instead a __new__:
    def __new__(cls, file):
        result = object.__new__(cls)
        result.field = file.read(4)
        if len(self.field) != 4: return None
        return result

Using such exoteric techniques to avoid normal idiomatic usage
and surprise every Python-aware reader of your code IS a bad
idea.  Be prepared to defend it craftily at the first code review!-)


Alex





More information about the Python-list mailing list