I don't understand why "reader" is a bad name. One of the links says:

> Reader/Writer – The main problem I have with these types of objects is that it only describes a small portion of the interaction that an object can have. A PhotoWriter is not an object, rather a Photo as an object has functionality binded to it so that it can be read or written.

I don't get that though.

Here's an example reader for the /etc/passwd file on my system. The reader iterates over PasswordEntry records, and the reader exposes a "Location" interface to get access to reader state, like the line number, which isn't logically part of the PasswordEntry. The reader also implements the context-manager and iterator APIs:

from collections import namedtuple

PasswordEntry = namedtuple("PasswordEntry",
"name password uid gid gecos home_dir shell")
class Location(object):
def __init__(self, filename, lineno=0, recno=0):
self.filename, self.lineno, self.recno = filename, lineno, recno

class PasswordReader(object):
def __init__(self, infile, reader_iter, location):
self._infile = infile
self._reader_iter = reader_iter
self.location = location
def __iter__(self):
return self._reader_iter
def __next__(self): # Python 3
return next(self._reader_iter)
def next(self): # Python 2
return next(self._reader_iter)
def close(self):
self._infile.close()
def __enter__(self):
return self
def __exit__(self, *args):
self.close()

def _read_password_entries(infile, location):
recno = 0
for lineno, line in enumerate(infile, 1):
location.lineno = lineno
if line.startswith("#"):
continue
fields = line.rstrip().split(":")
location.recno = recno = recno + 1
yield PasswordEntry(*fields)

def read_password_entries(filename):
infile = open(filename)
location = Location(filename)
reader_iter = _read_password_entries(infile, location)
return PasswordReader(infile, _read_password_entries(infile, location), location)

# Example code using the API
with read_password_entries("/etc/passwd") as reader:
for entry in reader:
if entry.shell != "/usr/bin/false":
print("Entry %r (record #%d, line %d) uses shell %r" % (
entry.name, reader.location.recno, reader.location.lineno, entry.shell))

## output for my system
# Entry 'root' (record #2, line 12) uses shell '/bin/sh'
# Entry '_uucp' (record #4, line 14) uses shell '/usr/sbin/uucico'

What's a better name than "PasswordReader"? (Other than PasswordEntryReader; I mean something which doesn't end in "-er".)

I don't understand the objection "it only describes a small portion of the interaction that an object can have". This is a reader, no? It reads entries, and that's pretty much all the interaction it has.

> They are not classes, and the objects they instantiate are not objects. Instead, they are collections of procedures pretending to be classes.

I also didn't understand this. How is the PasswordReader "pretending to be a class". It is a class, and methods like the context manager methods have to be implemented through a class, and not a "collection of procedures."

(Of course, C++ as "C with classes" is an example of OO programming as data structures plus a collection of procedures, where the language makes it easier to tie the two together. But that can't be the objection as then all C++ OO code is "pretending to be a class", making this an argument from extreme purism rather than one with more practical implications.)