|
| 1 | + |
| 2 | + |
| 3 | +## get_args |
| 4 | + |
| 5 | +More than half of my solution is just in defining the program's arguments to `argparse`. The effort is well worth the result, because `argparse` will ensure that each argument is a valid integer value because I set `type=int`. Notice there are no quotes around the `int` -- it's not the string `'int'` but a reference to the class in Python. You can use the `type` function in Python to find out how Python represents a value: |
| 6 | + |
| 7 | +```` |
| 8 | +>>> type(int) |
| 9 | +<class 'type'> |
| 10 | +>>> type('int') |
| 11 | +<class 'str'> |
| 12 | +```` |
| 13 | + |
| 14 | +For `--adjectives` and `--number`, I can set reasonable defaults so that no input is *required* from the user but the values are easily overridden. This makes your program dynamic, interesting, and testable. How do you know if your values are being used correctly unless you change them and test that the proper change was made in your program. Maybe you started off hardcoding the number of insults and forgot to change the `range` to use a variable. Without changing the input value and testing that the number of insults changed accordingly, it might be a user who discovers your bug, and that's somewhat embarrassing. |
| 15 | + |
| 16 | +Another reason I quite like `argparse` is that, if I find there is a problem with an argument, I can use `parser.error` to do four things: |
| 17 | + |
| 18 | +1. Print the short usage of the program to the user |
| 19 | +2. Print a specific message about the problem |
| 20 | +3. Halt execution of the program |
| 21 | +4. Return an error code to the operating system |
| 22 | + |
| 23 | +For instance, I can't very easily tell `argparse` that the `--number` should be a positive integer, only that it must be of type `int`. I can, however, inspect the value myself and call `parser.error('message')` if there is a problem. I do all this inside `get_args` so that, by the time I call `args = get_args()` in my `main` function, I know that all the arguments have been validated. I could have also added a similar check for `--adjectives`, but the main point was to highlight that such a thing is possible. As you write your own programs, you'll have to decide how much validation of user input you feel is necessary. |
| 24 | + |
| 25 | +## main |
| 26 | + |
| 27 | +Once I'm in `main` and have my arguments, I can control the randomness of the program by calling `random.seed(args.seed)` because: |
| 28 | + |
| 29 | +1. The default value of the `seed` is `None`, and setting `random.seed` to `None` is the same as not setting it at all. |
| 30 | +2. The `type` of `args.seed` is `int` which is the proper type for `random.seed`. I do not have to validate the argument further. Negative integers are valid values. |
| 31 | + |
| 32 | +To generate some `--number` of insults, I use the `range` function. Because I don't need the number of the insult, I can use the underscore (`_`) as a throwaway value: |
| 33 | + |
| 34 | +```` |
| 35 | +>>> num_insults = 2 |
| 36 | +>>> for _ in range(num_insults): |
| 37 | +... print('An insult!') |
| 38 | +... |
| 39 | +An insult! |
| 40 | +An insult! |
| 41 | +```` |
| 42 | + |
| 43 | +The underscore is a way to unpack a value and indicate that you do not intend to use it. That is, it's not possible to write this: |
| 44 | + |
| 45 | +```` |
| 46 | +>>> for in range(num_insults): |
| 47 | + File "<stdin>", line 1 |
| 48 | + for in range(num_insults): |
| 49 | +```` |
| 50 | + |
| 51 | +You have to put *something* after the `for` that looks like a variable. If you put a named variable like `n` and then don't use it in the loop, some tools like `pylint` will detect this as a possible error (and well it could be). The `_` shows that you won't use it, which is good information for your future self, some other user, or external tools to know. |
| 52 | + |
| 53 | +You can use multiple `_`, e.g., here I can unpack a 3-tuple so as to get the middle value: |
| 54 | + |
| 55 | +```` |
| 56 | +>>> x = 'Jesus', 'Mary', 'Joseph' |
| 57 | +>>> _, name, _ = x |
| 58 | +>>> name |
| 59 | +'Mary' |
| 60 | +```` |
| 61 | + |
| 62 | +To create my list of adjectives, I used the `str.split` method on a long, multi-line string I created using three quotes: |
| 63 | + |
| 64 | +```` |
| 65 | +>>> adjectives = """ |
| 66 | +... bankrupt base caterwauling corrupt cullionly detestable dishonest |
| 67 | +... false filthsome filthy foolish foul gross heedless indistinguishable |
| 68 | +... infected insatiate irksome lascivious lecherous loathsome lubbery old |
| 69 | +... peevish rascaly rotten ruinous scurilous scurvy slanderous |
| 70 | +... sodden-witted thin-faced toad-spotted unmannered vile wall-eyed |
| 71 | +... """.strip().split() |
| 72 | +>>> nouns = """ |
| 73 | +... Judas Satan ape ass barbermonger beggar block boy braggart butt |
| 74 | +... carbuncle coward coxcomb cur dandy degenerate fiend fishmonger fool |
| 75 | +... gull harpy jack jolthead knave liar lunatic maw milksop minion |
| 76 | +... ratcatcher recreant rogue scold slave swine traitor varlet villain worm |
| 77 | +... """.strip().split() |
| 78 | +>>> len(adjectives) |
| 79 | +36 |
| 80 | +>>> len(nouns) |
| 81 | +39 |
| 82 | +```` |
| 83 | + |
| 84 | +To select some number of adjectives, I chose to use `random.sample` function since I needed more than one: |
| 85 | + |
| 86 | +```` |
| 87 | +>>> import random |
| 88 | +>>> random.sample(adjectives, k=3) |
| 89 | +['filthsome', 'cullionly', 'insatiate'] |
| 90 | +```` |
| 91 | + |
| 92 | +For just one randomly selected value, I use `random.choice`: |
| 93 | + |
| 94 | +```` |
| 95 | +>>> random.choice(nouns) |
| 96 | +'boy' |
| 97 | +```` |
| 98 | + |
| 99 | +To concatenante them together, I need to put `', '` (a comma and a space) between each of the adjectives, and I can use `str.join` for that: |
| 100 | + |
| 101 | +```` |
| 102 | +>>> adjs = random.sample(adjectives, k=3) |
| 103 | +>>> adjs |
| 104 | +['thin-faced', 'scurvy', 'sodden-witted'] |
| 105 | +>>> ', '.join(adjs) |
| 106 | +'thin-faced, scurvy, sodden-witted' |
| 107 | +```` |
| 108 | + |
| 109 | +And feed all this to a format string: |
| 110 | + |
| 111 | +```` |
| 112 | +>>> noun = random.choice(nouns) |
| 113 | +>>> print('You {} {}!'.format(', '.join(adjs), noun)) |
| 114 | +You thin-faced, scurvy, sodden-witted liar! |
| 115 | +```` |
| 116 | + |
| 117 | +And now you have a handy way to make enemies and influence people. |
0 commit comments