chr() and ord() functions
isalpha() string method
isupper() and islower() string methods
The program in this chapter is not really a game, but it is fun to play with nonetheless. Our program will convert normal English into a secret code, and also convert secret codes back into regular English again. Only someone who is knowledgeable about secret codes will be able to understand our secret messages.
Because this program manipulates text in order to convert it into secret messages, we will learn several new functions and methods that come with Python for manipulating strings. We will also learn how programs can do math with text strings just as it can with numbers.
The science of writing secret codes is called cryptography.
In
Hello there! The keys to the house are hidden under the reddish flower pot.
When we convert the
Ckkz fkx kj becqnejc kqp pdeo oaynap iaoowca!
But if we know about the cipher used to encrypt the message, we can decrypt the
Many ciphers also use keys. Keys are secret values that let you
When we encrypt a message using a cipher, we will choose the key that is used to encrypt and
The Caesar Cipher was one of the earliest ciphers ever invented. In this cipher, you encrypt a message by taking each letter in the message (in
(рис 14.1) Shifting over letters by three spaces. Here, B becomes E.
To get each shifted letter, draw out a row of boxes with each letter of the
(рис 14.2) The entire alphabet shifted by three spaces.
The number of spaces we shift is the key in the Caesar Cipher. The example above shows the letter translations for the key 3.
Using a key of 3, if we encrypt the
We will keep any non-letter characters the same. In order to
You can find out more about the Caesar Cipher from Wikipedia at http://en.wikipedia.org/wiki/Caesar_cipher
How do we implement this shifting of the letters in our program? We can do this by representing each letter as a number (called an ordinal), and then adding or subtracting from this number to form a new number (and a new letter). ASCII (pronounced "ask-ee" and stands for American Standard Code for Information Interchange) is a code that connects each character to a number between 32 and 127. The numbers less than 32 refer to "unprintable" characters, so we will not be using them.
The capital letters "A" through "Z" have the ASCII numbers 65 through 90. The
| 32 | (space) | 48 | 0 | 64 | @ | 80 | P | 96 | ` | 112 | p |
| 33 | ! | 49 | 1 | 65 | A | 81 | Q | 97 | a | 113 | q |
| 34 | " | 50 | 2 | 66 | B | 82 | R | 98 | b | 114 | r |
| 35 | # | 51 | 3 | 67 | C | 83 | S | 99 | c | 115 | s |
| 36 | $ | 52 | 4 | 68 | D | 84 | T | 100 | d | 116 | t |
| 37 | % | 53 | 5 | 69 | E | 85 | U | 101 | e | 117 | u |
| 38 | 54 | 6 | 70 | F | 86 | V | 102 | f | 118 | v | |
| 39 | ' | 55 | 7 | 71 | G | 87 | W | 103 | g | 119 | w |
| 40 | ( | 56 | 8 | 72 | H | 88 | X | 104 | h | 120 | x |
| 41 | ) | 57 | 9 | 73 | I | 89 | Y | 105 | i | 121 | y |
| 42 | * | 58 | : | 74 | J | 90 | Z | 106 | j | 122 | z |
| 43 | + | 59 | ; | 75 | K | 91 | [ | 107 | k | 123 | { |
| 44 | , | 60 | < | 76 | L | 92 | \ | 108 | l | 124 | | |
| 45 | - | 61 | = | 77 | M | 93 | ] | 109 | m | 125 | } |
| 46 | . | 62 | > | 78 | N | 94 | ^ | 110 | n | 126 | ~ |
| 47 | / | 63 | ? | 79 | O | 95 | _ | 111 | o |
So if we wanted to shift "A" by three spaces, we first convert it to a number (65). Then we add 3 to 65, to get 68. Then we convert the number 68 back to a letter ("D"). We will use the chr() and ord() functions to convert between letters and numbers.
For example, the letter "A" is represented by the number 65. The letter "m" is represented by the number 109. A table of all the ASCII characters from 32 to 12 is in Table 14.1.
The chr() function (pronounced "char", short for "character") takes an integer ASCII number for the parameter and returns the single-ord() function (short for "
>>> chr(65)
'A'
>>> ord('A')
65
>>> chr(65+8)
'I'
>>> chr(52)
'4'
>>> chr(ord('F'))
'F'
>>> ord(chr(68))
68
>>>
On the third line, chr(65+8) evaluates to chr(73). If you look at the ASCII table, you can see that 73 is the chr(ord ('F')) evaluates to chr(70) which evaluates to 'F'. Feeding the result of ord() to chr() will give you back the original argument. The same goes for feeding the result of chr() to ord(), as shown by the sixth line.
Using chr() and ord() will come in handy for our Caesar Cipher program. They are also helpful when we need to convert strings to numbers and numbers to strings.
Here is a sample run of the Caesar Cipher program, encrypting a message:
Do you wish to encrypt or decrypt a message? encrypt Enter your message: The sky above the port was the color of television, tuned to a dead channel. Enter the key number (1-26) 13 Your translated text is: Gur fxl nobir gur cbeg jnf gur pbybe bs gryrivfvba, gharq gb n qrnq punaary.
Now we will run the program and decrypt the text that we just encrypted.
Do you wish to encrypt or decrypt a message? decrypt Enter your message: Gur fxl nobir gur cbeg jnf gur pbybe bs gryrivfvba, gharq gb n qrnq punaary. Enter the key number (1-26) 13 Your translated text is: The sky above the port was the color of television, tuned to a dead channel.
On this run we will try to
Do you wish to encrypt or decrypt a message? decrypt Enter your message: Gur fxl nobir gur cbeg jnf gur pbybe bs gryrivfvba, gharq gb n qrnq punaary. Enter the key number (1-26) 15 Your translated text is: Rfc qiw yzmtc rfc nmpr uyq rfc amjmp md rcjctgqgml, rslcb rm y bcyb afyllcj.
Here is the source code for the Caesar Cipher program. If you don't want to type all of this code in, you can visit this book's website at the URL http://inventwithpython.com/chapter14 and follow the instructions to download the source code. After you type this code in, save the file as cipher.py
cipher.py
This code can be downloaded from http://inventwithpython.com/cipher.py
If you get errors after typing this code in, compare it to the book's code with the online
diff tool at http://inventwithpython.com/diff or email the author at
al@inventwithpython.com
1. # Caesar Cipher
2.
3. MAX_KEY_SIZE = 26
4.
5. def getMode() :
6. while True:
7. print('Do you wish to encrypt or decrypt a message?')
8. mode = input().lower()
9. if mode in 'encrypt e decrypt d'.split():
10. return mode
11. else:
12. print('Enter either "encrypt" or "e" or "decrypt" or "d".')
13.
14. def getMessage() :
15. print('Enter your message:')
16. return input ()
17.
18. def getKey() :
19. key = 0
20. while True:
21. print('Enter the key number (1-%s)' %(MAX_KEY_SIZE))
22. key = int(input())
23. if (key >= 1 and key <= MAX_KEY_SIZE):
24. return key
25.
26. def getTranslatedMessage(mode, message, key):
27. if mode[0] = = 'd' :
28. key = -key
29. translated = ''
30.
31. for symbol in message:
32. if symbol.isalpha():
33. num = ord(symbol)
34. num += key 35 .
36. if symbol.isupper():
37. if num > ord('Z'):
38. num -= 26
39. elif num < ord('A') :
40. num += 26
41. elif symbol.islower():
42. if num > ord('z'):
43. num -= 26
44. elif num < ord('a'):
45. num += 26
46.
47. translated += chr(num)
48. else:
49. translated += symbol
50. return translated
51.
52. mode = getMode()
53. message = getMessage()
54. key = getKey()
55.
56. print('Your translated text is:')
57. print(getTranslatedMessage(mode, message, key))
This code is much shorter compared to our other games. The encryption and
1. # Caesar Cipher 2 . 3. MAX_KEY_SIZE = 26
The first line is simply a comment. The Caesar Cipher is one cipher of a type of ciphers called simple
MAX_KEY_SIZE is a variable that stores the integer 26 in it. MAX_KEY_SIZE reminds us that in this program, the key used in our cipher should be between 1 and 26.
5. def getMode() :
6. while True:
7. print('Do you wish to encrypt or decrypt a message?')
8. mode = input().lower()
9. if mode in 'encrypt e decrypt d'.split():
10. return mode
11. else:
12. print('Enter either "encrypt" or "e" or "decrypt" or "d".')
The getMode() function will let the user type in if they want to encrypt or input() (which then has the lower() mode. The if statement's condition checks if the string stored in mode exists in the list returned by 'encrypt e . This list is ['encrypt', 'e', ', but it is easier for the programmer to just type in 'encrypt e and not type in all those quotes and commas. But you can use whatever is easiest for you; they both evaluate to the same list value.
This function will return the first character in mode as long as mode is equal to 'encrypt', 'e', ', or 'd'. This means that getMode() will return the string 'e' or the string 'd'.
14. def getMessage() :
15. print('Enter your message:')
16. return input ()
The getMessage() function simply gets the message to encrypt or
18. def getKey() :
19. key = 0
20. while True:
21. print('Enter the key number (1-%s)' % (MAX_KEY_SIZE))
22. key = int(input())
23 . if (key >= 1 and key <= MAX_KEY_SIZE) :
24. return key
The getKey() function lets the player type in key they will use to encrypt or while loop ensures that the function only returns a valid key. A valid key here is one that is between the integer values 1 and 26 (remember that MAX_KEY_SIZE will only have the value 26 because it is constant). It then returns this key. Remember that on line 22 that key was set to the integer version of what the user typed in, and so getKey() returns an integer.
26. def getTranslatedMessage(mode, message, key): 27. if mode[0] = = 'd' : 28. key = -key 29. translated = ''
getTranslatedMessage() is the function that does the encrypting and decrypting in our program. It has three parameters. mode sets the function to encryption mode or message is the key is the key that is used in this cipher.
The first line in the getTranslatedMessage() function determines if we are in encryption mode or mode variable is the string 'd', then we are in key was the integer 22, then in -22. The reason for this will be explained later.
translated is the string that will hold the end result: either the translated. (A variable must be defined with some string value first before a string can be concatenated to it.)
The isalpha() string method will return True if the string is an uppercase or isalpha() will return False. Try typing the following into the interactive shell:
>>> 'Hello'.isalpha() True >>> 'Forty two'.isalpha() False >>> 'Fortytwo'.isalpha() True >>> '42'.isalpha() False >>> ''.isalpha() False >>>
As you can see, 'Forty two'.isalpha() will return False because 'Forty two' has a space in it, which is a non-letter character. 'Fortytwo'.isalpha() returns True because it does not have this space. '42'.isalpha() returns False because both '4' and '2' are non-letter characters. And ''.isalpha() is False because isalpha() only returns True if the string has only letter characters and is not blank.
We will use the isalpha() method in our program next.
31. for symbol in message: 32. if symbol.isalpha(): 33. num = ord(symbol) 34. num += key
We will run a for loop over each letter (remember in message string. Strings are treated just like lists of single-message had the string 'Hello', then for symbol in 'Hello' would be the same as for symbol in ['H', 'e', 'l', 'l', 'o'] . On each iteration through this loop, symbol will have the value of a letter in message.
The reason we have the if statement on line 32 is because we will only encrypt/num variable will hold the integer symbol. Line 34 then "shifts" the value in num by the value in key.
The isupper() and islower() string methods (which are on line 36 and 41) work in a way that is very similar to the isdigit() and isalpha() methods. isupper () will return True if the string it is called on contains at least one islower() returns True if the string it is called on contains at least one False. The existence of non-letter characters like numbers and spaces does not affect the False. Try typing the following into the interactive shell:
>>> 'HELLO'.isupper() True >>> 'hello'.isupper() False >>> 'hello'.islower() True >>> 'Hello'.islower() False >>> 'LOOK OUT BEHIND YOU!'.isupper() True >>> '42'.isupper() False >>> '42'.islower() False >>> ''.isupper() False >>> ''.islower() False >>>
The process of encrypting (or decrypting) each letter is fairly simple. We want to apply the same Python code to every letter character in the string, which is what the next several lines of code do.
36. if symbol.isupper():
37. num > ord('Z'):
38. num -= 2 6
39. elif num < ord('A') :
40. num += 2 6
This code checks if the symbol is an symbol was 'Z' and key was 4? If that were the case, the value of num here would be the character '^' (The '^' is 94). But ^ isn' a letter at all. We wanted the
The way we can do this is to check if key has a value larger than the largest possible letter's ASCII value (which is a capital "Z"). If so, then we want to subtract 26 (because there are 26 letters in total) from num. After doing this, the value of num is 68, which is the ASCII value for 'D'.
41. elif symbol.islower():
42. if num > ord('z'):
43. num -= 2 6
44. elif num < ord('a'):
45. num += 2 6
If the symbol is a ord('z') and ord('a') instead of ord ('Z') and ord('A').
If we were in decrypting mode, then key would be negative. Then we would have the special case where num -= 26 might be less than the smallest possible value (which is ord('A'), that is, 65). If this is the case, we want to add 26 to num to have it "wrap around".
47. translated += chr(num) 48. else: 49. translated += symbol
The translated string will be appended with the encrypted/translated string. This means that spaces, numbers,
50. return translated
The last line in the getTranslatedMessage() function returns the translated string.
52. mode = getMode()
53. message = getMessage()
54. key = getKey()
55 .
56. print('Your translated text is:')
57. print(getTranslatedMessage(mode, message, key))
This is the main part of our program. We call each of the three functions we have defined above in turn to get the mode, message, and key that the user wants to use. We then pass these three values as arguments to getTranslatedMessage(), whose return value (the translated string) is printed to the user.
That's the entire Caesar Cipher. However, while this cipher may fool some people who don't understand
Do you wish to encrypt or decrypt a message? encrypt Enter your message: Doubts may not be pleasant, but certainty is absurd. Enter the key number (1-26) 8 Your translated text is: Lwcjba uig vwb jm xtmiaivb, jcb kmzbiqvbg qa ijaczl.
The whole point of
Lwcjba uig vwb jm xtmiaivb, jcb kmzbiqvbg qa ijaczl.
One method of cryptanalysis is called brute force. Brute force is the technique of trying every single possible key. If the
First, change lines 7, 9, and 12 (which are in the getMode() function) to look like the following (the changes are in bold):
5. def getMode() :
6. while True:
7. print('Do you wish to encrypt or decrypt or brute force a message?')
8. mode = input().lower()
9. if mode in 'encrypt e decrypt d brute b'.split():
10. return mode[0]
11. else:
12. print('Enter either "encrypt" or "e" or "decrypt" or "d" or "brute" or "b".')
This will let us select "brute force" as a mode for our program. Then modify and add the following changes to the main part of the program:
52. mode = getMode()
53. message = getMessage()
54. if mode[0] != 'b':
55. key = getKey() 56 .
57. print('Your translated text is:')
58. if mode[0] != 'b':
59. print(getTranslatedMessage(mode, message, key))
60. else:
61. for key in range(1, MAX_KEY_SIZE + 1) :
62. print(key, getTranslatedMessage('decrypt', message, key))
These changes make our program ask the user for a key if they are not in "brute force" mode. If they are not in "brute force" mode, then the original getTranslatedMessage () call is made and the translated string is printed.
However, otherwise we are in "brute force" mode, and we run a getTranslatedMessage() loop that iterates from 1 all the way up to MAX_KEY_SIZE (which is 26). Remember that when the range() function returns a list of integers up to but not including the second parameter, which is why we have + 1. This program will print out every possible translation of the message (including the key number used in the translation). Here is a sample run of this modified program:
Do you wish to encrypt or decrypt or brute force a message? brute Enter your message: Lwcjba uig vwb jm xtmiaivb, jcb kmzbiqvbg qa ijaczl. Your translated text is: 1 Kvbiaz thf uva il wslhzhua, iba jlyahpuaf pz hizbyk. 2 Juahzy sge tuz hk vrkgygtz, haz ikxzgotze oy ghyaxj. 3 Itzgyx rfd sty gj uqjfxfsy, gzy hjwyfnsyd nx fgxzwi. 4 Hsyfxw qec rsx fi tpiewerx, fyx givxemrxc mw efwyvh. 5 Grxewv pdb qrw eh sohdvdqw, exw fhuwdlqwb lv devxug. 6 Fqwdvu oca pqv dg rngcucpv, dwv egtvckpva ku cduwtf. 7 Epvcut nbz opu cf qmfbtbou, cvu dfsubjouz jt bctvse. |8 Doubts may not be pleasant, but certainty is absurd. 9 Cntasr lzx mns ad okdzrzms, ats bdqszhmsx hr zartqc. 10 Bmszrq kyw lmr zc njcyqylr, zsr acpryglrw gq yzqspb. 11 Alryqp jxv klq yb mibxpxkq, yrq zboqxfkqv fp xyproa. 12 Zkqxpo iwu jkp xa lhawowjp, xqp yanpwejpu eo wxoqnz. 13 Yjpwon hvt ijo wz kgzvnvio, wpo xzmovdiot dn vwnpmy. 14 Xiovnm gus hin vy jfyumuhn, von wylnuchns cm uvmolx. 15 Whnuml ftr ghm ux iextltgm, unm vxkmtbgmr bl tulnkw. 16 Vgmtlk esq fgl tw hdwsksfl, tml uwjlsaflq ak stkmjv. 17 Uflskj drp efk sv gcvrjrek, slk tvikrzekp zj rsjliu. 18 Tekrji cqo dej ru fbuqiqdj, rkj suhjqydjo yi qrikht. 19 Sdjqih bpn cdi qt eatphpci, qji rtgipxcin xh pqhjgs. 20 Rciphg aom bch ps dzsogobh, pih qsfhowbhm wg opgifr. 21 Qbhogf znl abg or cyrnfnag, ohg pregnvagl vf nofheq. 22 Pagnfe ymk zaf nq bxqmemzf, ngf oqdfmuzfk ue mnegdp. 23 Ozfmed xlj yze mp awpldlye, mfe npceltyej td lmdfco. 24 Nyeldc wki xyd lo zvokckxd, led mobdksxdi sc klcebn. 25 Mxdkcb vjh wxc kn yunjbjwc, kdc lnacjrwch rb jkbdam. 26 Lwcjba uig vwb jm xtmiaivb, jcb kmzbiqvbg qa ijaczl.
After looking over each row, you can see that the 8th message is not garbage, but plain English! The 8. This brute force would have been difficult to do back in the days of Caesars and the Roman
Computers are very good at doing mathematics. When we create a system to translate some piece of information into numbers (such as we do with text and ASCII or with space and
But while our Caesar cipher program here can encrypt messages that will keep them secret from people who have to figure it out with
A large part of figuring out how to write a program is figuring out how to represent the information you want to manipulate as numbers. I hope this chapter has especially shown you how this can be done. The next chapter will present our final game, Reversi (also known as Othello). The AI that plays this game will be much more advanced than the AI that played
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.