Automate the Boring Stuff with Python

Home > Other > Automate the Boring Stuff with Python > Page 12
Automate the Boring Stuff with Python Page 12

by Al Sweigart


  While the hash character (#) marks the beginning of a comment for the rest of the line, a multiline string is often used for comments that span multiple lines. The following is perfectly valid Python code:

  """This is a test Python program. Written by Al Sweigart [email protected] This program was designed for Python 3, not Python 2. """ def spam(): """This is a multiline comment to help explain what the spam() function does.""" print('Hello!')

  Indexing and Slicing Strings

  Strings use indexes and slices the same way lists do. You can think of the string 'Hello world!' as a list and each character in the string as an item with a corresponding index.

  ' H e l l o w o r l d ! ' 0 1 2 3 4 5 6 7 8 9 10 11

  The space and exclamation point are included in the character count, so 'Hello world!' is 12 characters long, from H at index 0 to ! at index 11.

  Enter the following into the interactive shell:

  >>> spam = 'Hello world!' >>> spam[0] 'H' >>> spam[4] 'o' >>> spam[-1] '!' >>> spam[0:5] 'Hello' >>> spam[:5] 'Hello' >>> spam[6:] 'world!'

  If you specify an index, you’ll get the character at that position in the string. If you specify a range from one index to another, the starting index is included and the ending index is not. That’s why, if spam is 'Hello world!', spam[0:5] is 'Hello'. The substring you get from spam[0:5] will include everything from spam[0] to spam[4], leaving out the space at index 5.

  Note that slicing a string does not modify the original string. You can capture a slice from one variable in a separate variable. Try typing the following into the interactive shell:

  >>> spam = 'Hello world!' >>> fizz = spam[0:5] >>> fizz 'Hello'

  By slicing and storing the resulting substring in another variable, you can have both the whole string and the substring handy for quick, easy access.

  The in and not in Operators with Strings

  The in and not in operators can be used with strings just like with list values. An expression with two strings joined using in or not in will evaluate to a Boolean True or False. Enter the following into the interactive shell:

  >>> 'Hello' in 'Hello World' True >>> 'Hello' in 'Hello' True >>> 'HELLO' in 'Hello World' False >>> '' in 'spam' True >>> 'cats' not in 'cats and dogs' False

  These expressions test whether the first string (the exact string, case sensitive) can be found within the second string.

  Useful String Methods

  Several string methods analyze strings or create transformed string values. This section describes the methods you’ll be using most often.

  The upper(), lower(), isupper(), and islower() String Methods

  The upper() and lower() string methods return a new string where all the letters in the original string have been converted to uppercase or lower-case, respectively. Nonletter characters in the string remain unchanged. Enter the following into the interactive shell:

  >>> spam = 'Hello world!' >>> spam = spam.upper() >>> spam 'HELLO WORLD!' >>> spam = spam.lower() >>> spam 'hello world!'

  Note that these methods do not change the string itself but return new string values. If you want to change the original string, you have to call upper() or lower() on the string and then assign the new string to the variable where the original was stored. This is why you must use spam = spam.upper() to change the string in spam instead of simply spam.upper(). (This is just like if a variable eggs contains the value 10. Writing eggs + 3 does not change the value of eggs, but eggs = eggs + 3 does.)

  The upper() and lower() methods are helpful if you need to make a case-insensitive comparison. The strings 'great' and 'GREat' are not equal to each other. But in the following small program, it does not matter whether the user types Great, GREAT, or grEAT, because the string is first converted to lowercase.

  print('How are you?') feeling = input() if feeling.lower() == 'great': print('I feel great too.') else: print('I hope the rest of your day is good.')

  When you run this program, the question is displayed, and entering a variation on great, such as GREat, will still give the output I feel great too. Adding code to your program to handle variations or mistakes in user input, such as inconsistent capitalization, will make your programs easier to use and less likely to fail.

  How are you? GREat I feel great too.

  The isupper() and islower() methods will return a Boolean True value if the string has at least one letter and all the letters are uppercase or lowercase, respectively. Otherwise, the method returns False. Enter the following into the interactive shell, and notice what each method call returns:

  >>> spam = 'Hello world!' >>> spam.islower() False >>> spam.isupper() False >>> 'HELLO'.isupper() True >>> 'abc12345'.islower() True >>> '12345'.islower() False >>> '12345'.isupper() False

  Since the upper() and lower() string methods themselves return strings, you can call string methods on those returned string values as well. Expressions that do this will look like a chain of method calls. Enter the following into the interactive shell:

  >>> 'Hello'.upper() 'HELLO' >>> 'Hello'.upper().lower() 'hello' >>> 'Hello'.upper().lower().upper() 'HELLO' >>> 'HELLO'.lower() 'hello' >>> 'HELLO'.lower().islower() True

  The isX String Methods

  Along with islower() and isupper(), there are several string methods that have names beginning with the word is. These methods return a Boolean value that describes the nature of the string. Here are some common isX string methods:

  isalpha() returns True if the string consists only of letters and is not blank.

  isalnum() returns True if the string consists only of letters and numbers and is not blank.

  isdecimal() returns True if the string consists only of numeric characters and is not blank.

  isspace() returns True if the string consists only of spaces, tabs, and new-lines and is not blank.

  istitle() returns True if the string consists only of words that begin with an uppercase letter followed by only lowercase letters.

  Enter the following into the interactive shell:

  >>> 'hello'.isalpha() True >>> 'hello123'.isalpha() False >>> 'hello123'.isalnum() True >>> 'hello'.isalnum() True >>> '123'.isdecimal() True >>> ' '.isspace() True >>> 'This Is Title Case'.istitle() True >>> 'This Is Title Case 123'.istitle() True >>> 'This Is not Title Case'.istitle() False >>> 'This Is NOT Title Case Either'.istitle() False

  The isX string methods are helpful when you need to validate user input. For example, the following program repeatedly asks users for their age and a password until they provide valid input. Open a new file editor window and enter this program, saving it as validateInput.py:

  while True: print('Enter your age:') age = input() if age.isdecimal(): break print('Please enter a number for your age.') while True: print('Select a new password (letters and numbers only):') password = input() if password.isalnum(): break print('Passwords can only have letters and numbers.')

  In the first while loop, we ask the user for their age and store their input in age. If age is a valid (decimal) value, we break out of this first while loop and move on to the second, which asks for a password. Otherwise, we inform the user that they need to enter a number and again ask them to enter their age. In the second while loop, we ask for a password, store the user’s input in password, and break out of the loop if the input was alphanumeric. If it wasn’t, we’re not satisfied so we tell the user the password needs to be alphanumeric and again ask them to enter a password.

  When run, the program’s output looks like this:

  Enter your age: forty two Please enter a number for your age. Enter your age: 42 Select a new password (letters and numbers only): secr3t! Passwords can only have letters and numbers. Select a new password (letters and numbers only): secr3t

  Calling isdecimal() and isalnum() on variables, we’re able to test whether the values stored in those variables are decimal or not, alphanumeric or not. Here, these tests help us reject the input forty two and accept 42, and reject secr3t! and accept secr3t.

  The startswith() and endswith() String M
ethods

  The startswith() and endswith() methods return True if the string value they are called on begins or ends (respectively) with the string passed to the method; otherwise, they return False. Enter the following into the interactive shell:

  >>> 'Hello world!'.startswith('Hello') True >>> 'Hello world!'.endswith('world!') True >>> 'abc123'.startswith('abcdef') False >>> 'abc123'.endswith('12') False >>> 'Hello world!'.startswith('Hello world!') True >>> 'Hello world!'.endswith('Hello world!') True

  These methods are useful alternatives to the == equals operator if you need to check only whether the first or last part of the string, rather than the whole thing, is equal to another string.

  The join() and split() String Methods

  The join() method is useful when you have a list of strings that need to be joined together into a single string value. The join() method is called on a string, gets passed a list of strings, and returns a string. The returned string is the concatenation of each string in the passed-in list. For example, enter the following into the interactive shell:

  >>> ', '.join(['cats', 'rats', 'bats']) 'cats, rats, bats' >>> ' '.join(['My', 'name', 'is', 'Simon']) 'My name is Simon' >>> 'ABC'.join(['My', 'name', 'is', 'Simon']) 'MyABCnameABCisABCSimon'

  Notice that the string join() calls on is inserted between each string of the list argument. For example, when join(['cats', 'rats', 'bats']) is called on the ', ' string, the returned string is ‘cats, rats, bats’.

  Remember that join() is called on a string value and is passed a list value. (It’s easy to accidentally call it the other way around.) The split() method does the opposite: It’s called on a string value and returns a list of strings. Enter the following into the interactive shell:

  >>> 'My name is Simon'.split() ['My', 'name', 'is', 'Simon']

  By default, the string 'My name is Simon' is split wherever whitespace characters such as the space, tab, or newline characters are found. These whitespace characters are not included in the strings in the returned list. You can pass a delimiter string to the split() method to specify a different string to split upon. For example, enter the following into the interactive shell:

  >>> 'MyABCnameABCisABCSimon'.split('ABC') ['My', 'name', 'is', 'Simon'] >>> 'My name is Simon'.split('m') ['My na', 'e is Si', 'on']

  A common use of split() is to split a multiline string along the newline characters. Enter the following into the interactive shell:

  >>> spam = '''Dear Alice, How have you been? I am fine. There is a container in the fridge that is labeled "Milk Experiment". Please do not drink it. Sincerely, Bob''' >>> spam.split('n') ['Dear Alice,', 'How have you been? I am fine.', 'There is a container in the fridge', 'that is labeled "Milk Experiment".', '', 'Please do not drink it.', 'Sincerely,', 'Bob']

  Passing split() the argument 'n' lets us split the multiline string stored in spam along the newlines and return a list in which each item corresponds to one line of the string.

  Justifying Text with rjust(), ljust(), and center()

  The rjust() and ljust() string methods return a padded version of the string they are called on, with spaces inserted to justify the text. The first argument to both methods is an integer length for the justified string. Enter the following into the interactive shell:

  >>> 'Hello'.rjust(10) ' Hello' >>> 'Hello'.rjust(20) ' Hello' >>> 'Hello World'.rjust(20) ' Hello World' >>> 'Hello'.ljust(10) 'Hello'

  'Hello'.rjust(10) says that we want to right-justify 'Hello' in a string of total length 10. 'Hello' is five characters, so five spaces will be added to its left, giving us a string of 10 characters with 'Hello' justified right.

  An optional second argument to rjust() and ljust() will specify a fill character other than a space character. Enter the following into the interactive shell:

  >>> 'Hello'.rjust(20, '*') '***************Hello' >>> 'Hello'.ljust(20, '-') 'Hello---------------'

  The center() string method works like ljust() and rjust() but centers the text rather than justifying it to the left or right. Enter the following into the interactive shell:

  >>> 'Hello'.center(20) ' Hello ' >>> 'Hello'.center(20, '=') '=======Hello========'

  These methods are especially useful when you need to print tabular data that has the correct spacing. Open a new file editor window and enter the following code, saving it as picnicTable.py:

  def printPicnic(itemsDict, leftWidth, rightWidth): print('PICNIC ITEMS'.center(leftWidth + rightWidth, '-')) for k, v in itemsDict.items(): print(k.ljust(leftWidth, '.') + str(v).rjust(rightWidth)) picnicItems = {'sandwiches': 4, 'apples': 12, 'cups': 4, 'cookies': 8000} printPicnic(picnicItems, 12, 5) printPicnic(picnicItems, 20, 6)

  In this program, we define a printPicnic() method that will take in a dictionary of information and use center(), ljust(), and rjust() to display that information in a neatly aligned table-like format.

  The dictionary that we’ll pass to printPicnic() is picnicItems. In picnicItems, we have 4 sandwiches, 12 apples, 4 cups, and 8000 cookies. We want to organize this information into two columns, with the name of the item on the left and the quantity on the right.

  To do this, we decide how wide we want the left and right columns to be. Along with our dictionary, we’ll pass these values to printPicnic().

  printPicnic() takes in a dictionary, a leftWidth for the left column of a table, and a rightWidth for the right column. It prints a title, PICNIC ITEMS, centered above the table. Then, it loops through the dictionary, printing each key-value pair on a line with the key justified left and padded by periods, and the value justified right and padded by spaces.

  After defining printPicnic(), we define the dictionary picnicItems and call printPicnic() twice, passing it different widths for the left and right table columns.

  When you run this program, the picnic items are displayed twice. The first time the left column is 12 characters wide, and the right column is 5 characters wide. The second time they are 20 and 6 characters wide, respectively.

  ---PICNIC ITEMS-- sandwiches.. 4 apples...... 12 cups........ 4 cookies..... 8000 -------PICNIC ITEMS------- sandwiches.......... 4 apples.............. 12 cups................ 4 cookies............. 8000

  Using rjust(), ljust(), and center() lets you ensure that strings are neatly aligned, even if you aren’t sure how many characters long your strings are.

  Removing Whitespace with strip(), rstrip(), and lstrip()

  Sometimes you may want to strip off whitespace characters (space, tab, and newline) from the left side, right side, or both sides of a string. The strip() string method will return a new string without any whitespace characters at the beginning or end. The lstrip() and rstrip() methods will remove whitespace characters from the left and right ends, respectively. Enter the following into the interactive shell:

  >>> spam = ' Hello World ' >>> spam.strip() 'Hello World' >>> spam.lstrip() 'Hello World ' >>> spam.rstrip() ' Hello World'

  Optionally, a string argument will specify which characters on the ends should be stripped. Enter the following into the interactive shell:

  >>> spam = 'SpamSpamBaconSpamEggsSpamSpam' >>> spam.strip('ampS') 'BaconSpamEggs'

  Passing strip() the argument 'ampS' will tell it to strip occurences of a, m, p, and capital S from the ends of the string stored in spam. The order of the characters in the string passed to strip() does not matter: strip('ampS') will do the same thing as strip('mapS') or strip('Spam').

  Copying and Pasting Strings with the pyperclip Module

  The pyperclip module has copy() and paste() functions that can send text to and receive text from your computer’s clipboard. Sending the output of your program to the clipboard will make it easy to paste it to an email, word processor, or some other software.

  Pyperclip does not come with Python. To install it, follow the directions for installing third-party modules in Appendix A. After installing the pyperclip module, enter the following into the interactive shell:

  >>> import pyperclip >>> pyperclip.copy('Hello world!') >>> pyperclip.paste() '
Hello world!'

  Of course, if something outside of your program changes the clipboard contents, the paste() function will return it. For example, if I copied this sentence to the clipboard and then called paste(), it would look like this:

  >>> pyperclip.paste() 'For example, if I copied this sentence to the clipboard and then called paste(), it would look like this:'

  Running Python Scripts Outside of IDLE

  So far, you’ve been running your Python scripts using the interactive shell and file editor in IDLE. However, you won’t want to go through the inconvenience of opening IDLE and the Python script each time you want to run a script. Fortunately, there are shortcuts you can set up to make running Python scripts easier. The steps are slightly different for Windows, OS X, and Linux, but each is described in Appendix B. Turn to Appendix B to learn how to run your Python scripts conveniently and be able to pass command line arguments to them. (You will not be able to pass command line arguments to your programs using IDLE.)

  Project: Password Locker

  You probably have accounts on many different websites. It’s a bad habit to use the same password for each of them because if any of those sites has a security breach, the hackers will learn the password to all of your other accounts. It’s best to use password manager software on your computer that uses one master password to unlock the password manager. Then you can copy any account password to the clipboard and paste it into the website’s Password field.

 

‹ Prev