Steven D'Aprano wrote: > > What do people think about functions that accept either a file name or a > file object? > > > def handle_file(obj): > if type(obj) == str: > need_to_close = True > obj = file(obj, 'r') > else: > need_to_close = False > do_something_with(obj.read()) > if need_to_close: > data.close() > > > Good idea? Bad idea? Just a matter of personal preference?
I sometimes write functions like this myself. However, the matter of testing for file-like objects can obviously vary somewhat in terms of personal preference and correctness. Some would argue that this is a situation which would benefit from interfaces: if isinstance(obj, FileLike): # or obj.implements(FileLike), perhaps do_something_with(obj.read()) In the original example, we can intuitively see that a file-like object need only support the read and close methods, and in the case of receiving a file-like object, only the read method need exist on the object. Consequently, we can write the following: if hasattr(obj, "read"): do_something_with(obj.read()) Some would rightly say that this is ridiculous: you're testing something which will be discovered straight away. However, there can be situations where you might want to know in advance whether the object is suitable, especially if you may perform more than one kind of operation on the object and where side-effects may occur - the "let the code fail" attitude arguably doesn't hold up very well in such cases. The problem can then be framed in terms of being able to express the set of required operations and whether something like interfaces is a flexible enough means of doing so. We might have something like this: if test_for_file(obj): do_something_with(obj) # not the string but the object itself Now, we have the choice of explicitly phrasing the test ourselves... def test_for_file(obj): return hasattr(obj, "read") and hasattr(obj, "close") # and ... ...or relying on an interface mechanism to do this for us, with the possible additional overhead of declaring such interface usage when defining or adopting classes. It seems to me that there's a gulf between the use of interfaces, with the cost of introducing declarations in the code and the benefit of relatively easy verification of object "capabilities", and the current situation where one might like to try and deduce the required capabilities of an object at any given point in the code. Without interfaces, such verification is difficult but there's less overhead for the programmer; with interfaces, verification is easier but the programmer has to work harder to do most of the work. I can't really see a good compromise. Paul -- http://mail.python.org/mailman/listinfo/python-list