def f(x):
return x * x
y = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
print(list(y))
[1, 4, 9, 16, 25, 36, 49, 64, 81]
print(list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])))
['1', '2', '3', '4', '5', '6', '7', '8', '9']
def k(x):
return x%2 == 0
y = list(filter(k, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
print(y)
[2, 4, 6, 8]
def add( x, y ):
return x + y
lambda x, y: x + y
lambda x, y = 2: x + y
lambda *z: z
Sometimes the anonymous function is convenient.
It has only one expression. (You do not have to use return)
print(list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9])))
print(list(filter(lambda x: x%2==0, [1, 2, 3, 4, 5, 6, 7, 8, 9])))
[ expression for value in iterable if condition ]
>>> [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
>>> [x * x for x in range(1, 11) if x % 2 == 0]
[4, 16, 36, 64, 100]
>>> [m + n for m in 'ABC' for n in 'XYZ']
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
>>> d = {'x': 'A', 'y': 'B', 'z': 'C' }
>>> [k + '=' + v for k, v in d.items()]
['y=B', 'x=A', 'z=C']
>>> L = ['Hello', 'World', 'IBM', 'Apple']
>>> [s.lower() for s in L]
['hello', 'world', 'ibm', 'apple']
def print_msg(msg):
def printer():
print(msg)
return printer
another = print_msg("zen of python")
print(another())
We must have a nested function (function inside a function).
The nested function must refer to a value defined in the enclosing function.
The enclosing function must return the nested function.
When to use closures?
Closures can avoid the use of global values and provides some form of data hiding. It can also provide an object oriented solution to the problem.
def lazy_sum(*args):
def calc_sum():
ax = 0
for n in args:
ax = ax + n
return ax
return calc_sum
f = lazy_sum(1, 3, 5, 7, 9)
print(f())
print(type(f))
25
<class 'function'>
def make_multiplier_of(n):
def multiplier(x):
return x * n
return multiplier
times3 = make_multiplier_of(3)
times5 = make_multiplier_of(5)
print(times3(9))
print(times5(3))
print(times5(times3(2)))
Decorators are "wrappers", which means that they let you execute code before and after the function they decorate without modifying the function itself.
def new_decorator(a_function_to_decorate):
def the_wrapper():
print("Before the function runs")
a_function_to_decorate()
print("After the function runs")
return the_wrapper
def a_function():
print("I am a stand alone function.")
a_function_decorated = new_decorator(a_function)
a_function_decorated()
Before the function runs
I am a stand alone function.
After the function runs
@new_decorator
def another_stand_alone_function():
print("Leave me alone")
another_stand_alone_function()
Before the function runs
Leave me alone
After the function runs
def bread(func):
def wrapper():
print("''''''\>")
func()
print("<\______/>")
return wrapper
def ingredients(func):
def wrapper():
print("#tomatoes#")
func()
print("~salad~")
return wrapper
def sandwich(food="--ham--"):
print(food)
sandwich()
--ham--
@bread
@ingredients # The order matters here.
def sandwich(food="--ham--"):
print(food)
sandwich()
''''''\>
#tomatoes#
--ham--
~salad~
<\______/>
Taking decorators to the next level
Passing arguments to the decorated function
def passing_arguments(function_to_decorate):
def wrapper(arg1, arg2):
print(f"I got args! Look: {arg1}, {arg2}")
function_to_decorate(arg1, arg2)
return wrapper
@passing_arguments
def print_name(first_name, last_name):
print(f"My name is {first_name}, {last_name}")
print_name("Peter", "Venkman")
I got args! Look: Peter, Venkman
My name is Peter, Venkman
If you're making general-purpose decorator--one you'll apply to any function or method, no matter its arguments--then just use *args, **kwargs:
def passing_arbitrary_arguments(function_to_decorate):
def wrapper(*args, **kwargs):
print("Do I have args?:")
print(args)
print(kwargs)
function_to_decorate(*args, **kwargs)
return wrapper
@passing_arbitrary_arguments
def function_with_no_argument():
print("Python is cool, no argument here.")
function_with_no_argument()
Do I have args?:
()
{}
Python is cool, no argument here.
@passing_arbitrary_arguments
def function_with_arguments(a, b, c, d):
print(a, b, c, d)
function_with_arguments(1,2,3,4)
Do I have args?:
(1, 2, 3, 4)
{}
1 2 3 4
function_with_arguments(1,2,3,d = "banana")
Do I have args?:
(1, 2, 3)
{'d': 'banana'}
1 2 3 banana
pi_digits.txt
3.1415926535
8979323846
2643383279
with open('pi_digits.txt') as file_object:
contents = file_object.read() # string
print(contents.rstrip())
3.1415926535
8979323846
2643383279
relative path
with open('text_files/filename.txt') as file_object: # Linux or OSX
pass
with open('text_files\filename.txt') as file_object: # Windows
pass
absolute path
# Linux or OSX
file_path = '/home/ehmatthes/other_files/text_files/filename.txt'
with open(file_path) as file_object:
pass
# Windows
file_path = r'C:\Users\ehmatthes\other_files\text_files\filename.txt'
with open(file_path) as file_object:
pass
filename = 'pi_digits.txt'
with open(filename) as file_object:
for line in file_object:
print(line)
3.1415926535
8979323846
2643383279
filename = 'pi_digits.txt'
with open(filename) as file_object:
for line in file_object:
print(line.rstrip())
3.1415926535
8979323846
2643383279
Making a List of Lines from a File
filename = 'pi_digits.txt'
with open(filename) as file_object:
lines = file_object.readlines() #List
Working with a File's Contents
pi_string = ''
for line in lines:
pi_string = pi_string + line.rstrip()
print(pi_string)
print(len(pi_string))
3.141592653589793238462643383279 # string
32
filename = 'programming.txt'
with open(filename, 'w') as file_object:
file_object.write("I love programming.")
The second argument, 'w', tells Python that we want to open the file in write mode. You can open a file 198 Chapter 10 in read mode ('r'), write mode ('w'), append mode ('a'), or a mode that allows you to read and write to the file ('r+'). If you omit the mode argument, Python opens the file in read-only mode by default.
Python can only write strings to a text file. If you want to store numerical data in a text file, you'll have to convert the data to string format first using the str() function.
Writing Multiple Lines
filename = 'programming.txt'
with open(filename, 'w') as file_object:
file_object.write("I love programming.")
file_object.write("I love creating new games.")
I love programming.I love creating new games.
filename = 'programming.txt'
with open(filename, 'w') as file_object:
file_object.write("I love programming.\n")
file_object.write("I love creating new games.\n")
I love programming.
I love creating new games.
Appending to a File
filename = 'programming.txt'
message.py
with open(filename, 'a') as file_object:
file_object.write("I also love finding meaning in large datasets.\n")
file_object.write("I love creating apps that can run in a browser.\n")
I love programming.
I love creating new games.
I also love finding meaning in large datasets.
I love creating apps that can run in a browser.
Handling the FileNotFoundError Exception
filename = 'alice.txt'
with open(filename) as f_obj:
contents = f_obj.read() #Error
filename = 'alice.txt'
try:
with open(filename) as f_obj:
contents = f_obj.read()
except FileNotFoundError:
msg = f"Sorry, the file {filename} does not exist."
print(msg)
Sorry, the file alice.txt does not exist.
ZeroDivisionError
filename = 'alice.txt'
try:
with open(filename) as f_obj:
contents = f_obj.read()
except FileNotFoundError:
msg = f"Sorry, the file {filename} does not exist."
print(msg)
else:
# Count the approximate number of words in the file.
words = contents.split()
num_words = len(words)
print(f"The file {filename} has about {num_words} words.")
import json
numbers = [2, 3, 5, 7, 11, 13]
filename = 'numbers.json'
with open(filename, 'w') as f_obj:
json.dump(numbers, f_obj)
import json
filename = 'numbers.json'
with open(filename) as f_obj:
numbers = json.load(f_obj)
print(numbers)
[2, 3, 5, 7, 11, 13]
Saving and Reading User-Generated Data
import json
filename = 'username.json'
username = input("What is your name? ")
with open(filename, 'w') as f_obj:
json.dump(username, f_obj)
print(f"We'll remember you when you come back, {username}!")
import json
filename = 'username.json'
with open(filename) as f_obj:
username = json.load(f_obj)
print(f"Welcome back, {username}!")
import json
filename = 'username.json'
try:
with open(filename) as f_obj:
username = json.load(f_obj)
except FileNotFoundError:
username = input("What is your name? ")
with open(filename, 'w') as f_obj:
json.dump(username, f_obj)
print(f"We'll remember you when you come back, {username}!")
else:
print(f"Welcome back, {username}!")
What is your name? Eric #First time
We'll remember you when you come back, Eric!
Welcome back, Eric!