Then let's get rid of the with semantics too, because they add magic.
Compare:
with open("file.txt") as somefile:
for line in somefile:
print line
To the more explicit and clear:
somefile = open("file.txt")
line = somefile.readline()
while line:
print line
line = somefile.readline()
somefile.close()
But I'm still using some magic, I should be more explicit:
def explicit_readline(fd):
buff = []
char = fd.read(1)
while char != "\n" and char != "":
buff.append(char)
return "".join(buff)
somefile = open("file.txt", "rb") # just to be sure now
line = explicit_readline(somefile)
while line != "": # to be more explicit, of course
print line
line = explicit_readline(somefile)
somefile.close()
And we could go on like this to replace open with the os module file-descriptor functions, and print with sys.stdout/stderr (because more explicit, right?). But even without getting there, it should be obvious that:
* The "explicit" verison no longer behaves as the original one, because, for example, explicit_readline only handles well the NIX newline character. If I want to provide the same functionality as file.readline() I should add a lot more code.
I've reinvented the wheel for no good reason, and readability has suffered. It may also leave a lingering question in the mind of a read "why did he do that? is there some edge case that wasn't well documented anywhere and he bumped into?".
* I've seen more contrived code do a version of this "more explicit" programming style, to the point of having statements like:
def f1(number):
number = int(number)
return number & 0xff00 # or plug the number parameter in an equation, etc
* ... (not a verbatim example, but along those lines). And that code is redundant and it will fail anyway if another thing other than an int/long/float is passed. It would be certainly saner to have an assert, or simply specify in the docs that said function expects a number (which is implied in the args too).
My point was the "Explicit is better than implicit" means "be clear of your intent". And if I see someone using the attr module (which comes with the standard library), and I'm not familiar with it, I'll read into it. And for it's use case, I think it's clear enough in what it does, and how it should be used.