Today: lambda warmup, modules 1.0, wordcount module, HW7 preview, bluescreen art contest

## Lambda Warmup

Do this in the interpreter

Suppose have a list of strings. How to sort these into increasing order by length? What 1-liner / lambda will pull out the string with the largest length?

```>>> strs = ['apple', 'glaze donut', 'pear', 'banana']
>>>
```

Solution

```>>> # project out len(s) for each string
>>> sorted(strs, key=lambda s: len(s))
['pear', 'apple', 'banana', 'glaze donut']
>>>
>>> # max pulls out largest one
>>> max(strs, key=lambda s: len(s))
'glaze donut'
```

## Modules

• "module" - unit of code to use, "library"
• Every module has a name, e.g. "math"
• Module contains lots of functions, solving common problems
• Modern coding:
1. Part you build on code from a module
2. Part you write custom

## Standard Modules - import math

• Python comes with "standard" modules
• Standard modules are installed when Python is installed, so no extra step required
• e.g. the "math" module - mathematics
• e.g. the "sys" module - interface with operating system
• import module by name
• Use dot to refer to functions etc. in the module
`math.sqrt(2)` - function call
`math.pi` - pi constant within math
• Shown here in interpreter, but works in .py too
• Common error: forgetting to do the import
• Aside: there are other import forms, but this name/dot form is the most important
```>>> import math
>>> math.sqrt(2)  # call sqrt() fn
1.4142135623730951
>>> math.sqrt

>>>
>>> math.log(10)
2.302585092994046
>>> math.pi       # constants in module too
3.141592653589793
```

Restart interpreter without the import, see common error:

```>>> # quit and restart interpreter
>>> math.sqrt(2)  # OOPS forgot the import
Traceback (most recent call last):
NameError: name 'math' is not defined
>>>
>>> import math
>>> math.sqrt(2)  # now it works
1.4142135623730951
```

## Hacker: Use dir() and help()

• Feel like a hacker, use dir() and help() on module
• In the interpreter >>>
• `dir(module)` - shows a list of all the defs in the module
• `help(module.fn)` - shows some help text for that function
```>>> import math
>>> dir(math)
['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians', 'remainder', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc']
>>>
>>> help(math.sqrt)
Help on built-in function sqrt in module math:

sqrt(x, /)
Return the square root of x.
>>>
>>> help(math.cos)
Help on built-in function cos in module math:

cos(x, /)
Return the cosine of x (measured in radians).
```

## Module Recap

• What's a module?
• Has a name
• Holds lots of functions
i.e. "library" of functions
• Use `import math` to bring it in
• Use `math.sqrt(5)` syntax to call a function in a module

## wordcount.py Is a Module

• Suppose you have built some useful functions
• Someone else in your lab wants to use them....
Them pasting in their own copy is not ideal
• What does a module contain?
• We have wordcount.py
• python3 wordcount.py - runs main()
• wordcount.py is also a module named just "wordcount"
• Think of all the defs in wordcount: read_counts(), clean(), print_counts(),
• import works on wordcount (in the same directory)
• Access functions as module.xxx just like usual
• Run python interpreter in wordcount directory to try this
• Try importing wordcount, calling the read_counts() function
• Call wordcount.clean()
```>>> # Run interpreter in wordcount directory
>>> import wordcount
>>>
{'a': 2, 'b': 2}
```
• A module/file contains many defs
• Can import a module/file, call its defs:
• module.fn_name()
• Style: for a function to be usable from another module...
it should take in data as parameters and return a value
i.e. black box style
we've done this all along, see now the bigger picture
• HW7 babygraphics:
treat babynames.py as a module
import babynames

## dir() and help() work on wordcount Too.

• dir() and help() work too
• See where the """Pydoc""" goes!
```>>> dir(wordcount)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'clean', 'main', 'print_counts', 'print_top', 'read_counts', 'sys']
>>>

Help on function read_counts in module wordcount:

Given filename, reads its text, splits it into words.
Returns a "counts" dict where each word
...
```

## Two Ways of wordcount.py

• Two ways this file can be used
• 1. `python3 wordcount.py poem.txt`
load up all the wordcount.py code
run main() ... it runs all the functions
• 2. Some code does `import wordcount`
In this case:
do not run main
Module sits there
Waiting for a call like wordcount.read_counts() to happen
• How are these two cases distinguished?
• (1) is common BTW, (2) is rare but should work

## How Does Python Know To Run main()?

• There is a special variable
`__name__`
• Python aside: when a name begins with underbars
Signifies an internal detail that normal code should not mess with
• When __name__ has the special value __main__
It means we have case (1), we are supposed to run main()
• This is why there's that crazy if-statement at the bottom of the file!

Typical last 2 lines of .py file:

```if __name__ == '__main__':
main()
```

Experiment: Put these lines at end of wordcount.py. Then try running wordcount from command line, and loading it in interpreter.

```if __name__ == '__main__':
print("I feel like running main()")
main()
else:
print("Not running main()")
```

## Design Idea: Easy Things Should be Easy

Design idea: doing the ordinary thing should be easy, not require thought. Doing something hard should be possible, but may require work.

This __name__ business seems a weak point in Python's design. It is not great that every vanilla python program has to carry around these 2 obscure looking lines. There should be a less obscure way of getting the default behavior that 99% of python programs want.

## Demo HW7 Baby Graphics

• It's just calling your babynames.xxx functions
• Code in here draws lines, colors

## Demo HW7 Ghost

• Look at image series - think about outlier
clock tower
monster
• Algorithmic Look At Pixels

## Bluescreen Art Contest (optional!)

• We'll have optional HW7c art project you can do for fun
Slight extra credit, not affecting curve
Really just for fun after you're done with HW7
Art show in class, prizes
• Recall - Bluescreen algorithm
• 1. "front" strategy
• Detect blue pixels - average technique
• Replace blue pixels in image with background pixels
• More details Monday (do HW7 first)
• Demo here - comment out the pixel.red = xxx lines to see original image