[Tutor] class method problem

Steven D'Aprano steve at pearwood.info
Sun Sep 26 03:16:13 CEST 2010


On Sun, 26 Sep 2010 08:13:23 am David Hutto wrote:
> Since I had nothing else to do, but practice, this looks much better:
>
> def find(word, search):
> 	if search in word:
> 		print True
> 	else:
> 		print False


For some definition of "better".

If I called a function:

find("anti-disestablishmentarianism", "lish")

and got back an answer:

True

I'd feel ripped off and cheated. That would be like going to Google, 
typing in something into the search box, and Google comes back with:

    Yes, we found your terms on the Internet, but we won't tell you
    where. If you would like to find something else, we won't tell 
    you where that is either.

Aside from the name of the function, which is deceptive because it 
doesn't describe what the function does, the names of the arguments are 
also poor. The first argument is not necessarily a word. Nor is there 
any need for it to be -- it can be any text. The second argument is 
poorly described as "search" -- search is a verb. 

A better function signature might be:

def search(text, target):
    # Search for target in text and print whether it is found or not.

Even this is slightly misleading, because "text" doesn't need to be an 
actual string. It could be any sequence, such as a list. But this gives 
the *intention* of the function, which is to do text searches. So this 
is (in my opinion) an acceptable compromise between intention and 
generality.

Now on to the code itself. The body of the function is needlessly 
verbose. You say:

if search in word:
    print True
else:
    print False

This is so simple we can trace the entire function by hand. Say we call 
search("I like spam and eggs", "spam"):

(1) target in text? => True
(2) take the if branch
(3) print True

Now say we call find("I like spam and eggs", "cheese"):

(1) target in text? => False
(2) take the else branch
(3) print False

Can you see the common factor? The object which is printed is always 
precisely the same object generated by the `in` test. So we can 
simplify the body of the function:

def search(text, target):
    print target in text


But this is so simple, there's no point to wrapping it in a function!

Small functions that do one thing are good, up to a point, but when the 
function is so small that it is just as easy to include the body in the 
caller code, the function is pointless. It's not like "search(b, a)" is 
easier to write or remember than "print a in b" -- if anything the 
opposite is the case, because I would never remember which order to 
pass the arguments.



-- 
Steven D'Aprano


More information about the Tutor mailing list