Setting up a main function with command line argument

Let's refine our word fetching module a little further. First, we'll perform a small refactoring and separate the word retrieval and collection on the one hand from the word printing on the other:

from urllib.request import urlopen

# This fetches the words and returns them as a list.
def fetch_words():
with urlopen('http://sixty-north.com/c/t.txt') as story:
story_words = []
for line in story:
line_words = line.decode('utf-8').split()
for word in line_words:
story_words.append(word)
return story_words


# This prints a list of words
def print_words(story_words):
for word in story_words:
print(word)


if __name__ == '__main__':
words = fetch_words()
print_words(words)

We do this because it separates two important concerns: when importing we'd rather get the words as a list, but when running directly, we'd prefer the words
to be printed.

Next, we'll extract the code from our if __name__ == '__main__' block into a function called main():

def main():
words = fetch_words()
print_words(words)
if __name__ == '__main__':
main()

By moving this code into a function we can test it from the REPL, something which isn't possible while it's in the module scope if-block.

We can now try these functions from the REPL:

>>> from words import (fetch_words, print_words)
>>> print_words(fetch_words())

We've used this opportunity to introduce a couple of new forms of the import statement. The first new form imports multiple objects from a module using a comma separated list. The parentheses are optional, but they do allow you to break this list over multiple lines if it gets long. This form is perhaps the most widely used form of the import statement.

A second new form imports everything from a module using an asterisk wildcard:

>>> from words import *

This latter form is recommended only for casual use at the REPL. It can wreak havoc in programs since what is imported is now potentially beyond your control, opening yourself up to potential namespace clashes at some future time.

Having done this, we can fetch words from the URL:

>>> fetch_words()
['It', 'was', 'the', 'best', 'of', 'times', 'it', 'was', 'the', 'worst','of', 'times', 'it', 'was', 'the', 'age', 'of', 'wisdom', 'it', 'was','the', 'age', 'of', 'foolishness', 'it', 'was', 'the', 'epoch', 'of','belief', 'it', 'was', 'the', 'epoch', 'of', 'incredulity', 'it', 'was','the', 'season', 'of', 'Light', 'it', 'was', 'the', 'season', 'of','Darkness', 'it', 'was', 'the', 'spring', 'of', 'hope', 'it', 'was', 'the','winter', 'of', 'despair', 'we', 'had', 'everything', 'before', 'us', 'we','had', 'nothing', 'before', 'us', 'we', 'were', 'all', 'going', 'direct','to', 'Heaven', 'we', 'were', 'all', 'going', 'direct', 'the', 'other','way', 'in', 'short', 'the', 'period', 'was', 'so', 'far', 'like', 'the','present', 'period', 'that', 'some', 'of', 'its', 'noisiest', 'authorities','insisted', 'on', 'its', 'being', 'received', 'for', 'good', 'or', 'for','evil', 'in', 'the', 'superlative', 'degree', 'of', 'comparison', 'only']

Since we've separated the fetching code from the printing code, we can also print any list of words:

>>> print_words(['Any', 'list', 'of', 'words'])
Any
list
of
words

Indeed, we can even run the main program:

>>> main()
It
was
the
best
of
times

Notice that the print_words() function isn't fussy about the type items in the list. It's perfectly happy to print a list of numbers:

>>> print_words([1, 7, 3])
1
7
3

So perhaps print_words() isn't the best name. In fact, the function doesn't mention lists either - it will happily print any collection that the for-loop is capable of iterating over, such as a string:

>>> print_words("Strings are iterable too")
S
t
r
i
n
g
s

a
r
e

i
t
e
r
a
b
l
e

t
o
o

So let's perform a minor refactoring and rename this function to print_items(), changing the variable names within the function to suit:

def print_items(items):
for item in items:
print(item)
We'll talk more about the dynamic typing in Python which allows this degree of flexibility in the next module.

Finally, one obvious improvement to our module would be to replace the hard-coded URL with a value we can pass in. Let's extract that value into an argument of the fetch_words() function:

def fetch_words(url):
with urlopen(url) as story:
story_words = []
for line in story:
line_words = line.decode('utf-8').split()
for word in line_words:
story_words.append(word)
return story_words
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset