def outer():
def inner():
num = 100
print(num)
inner()
outer()
num = 3 # Global(全局)
def outer():
num = 10 # Enclosing(外层)
def inner():
num = 100 # Local(局部)
print(num)
inner()
print(num)
outer()
(引用顺序)Local$\rightarrow$Enclosing$\rightarrow$Global$\rightarrow$ Build-in (LEGB principle)
num = 3
def outer():
num = 10
def inner():
print(num)
inner()
outer()
# output?
def outer():
num = 10
def inner():
nonlocal num
num = 100
print(num)
inner()
print(num)
outer()
100
100
def outer():
num = 10
def inner():
global num
num = 100
print(num)
inner()
print(num)
outer()
100
10
def outer():
global num
num = 10
def inner():
global num
num = 100
print(num)
inner()
print(num)
outer()
100
100
def outer():
global num
num = 10
def inner():
num = 100
print(num)
inner()
print(num)
outer()
100
10
num = 3
def outer():
global num
num = 10
def inner():
num = 100
print(num)
inner()
print(num)
outer()
print(num)
100
10
10
num = 3
def outer():
num = 10
def inner():
global num
num = 100
print(num)
inner()
print(num)
outer()
print(num)
100
10
100
num = 3
def outer():
num = 10
def inner():
nonlocal num
num = 100
print(num)
inner()
print(num)
outer()
print(num)
100
100
3
num = 3
def outer():
global num
num = 10
def inner():
global num
num = 100
print(num)
inner()
print(num)
outer()
print(num)
100
100
100
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 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)))
def create_city_order_system(city):
user_data = {}
def process_order(user, price):
nonlocal user_data
if user not in user_data:
user_data[user] = {"count": 0, "total": 0}
user_data[user]["count"] += 1
user_data[user]["total"] += price
print(f"[{city}站] {user} 本次消费 {price} 元")
print(f"[{city}站] 累计订单:{user_data[user]['count']}")
print(f"[{city}站] 累计消费:{user_data[user]['total']} 元\n")
return process_order
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
def log_order(func):
def wrapper(user, price):
print(f"[日志] 收到订单:用户={user}, 金额={price}")
func(user, price)
return wrapper
def create_city_order_system(city):
user_data = {}
@log_order
def process_order(user, price):
nonlocal user_data
if user not in user_data:
user_data[user] = {"count": 0, "total": 0}
user_data[user]["count"] += 1
user_data[user]["total"] += price
print(f"[{city}站] {user} 本次消费 {price} 元")
print(f"[{city}站] 累计订单:{user_data[user]['count']}")
print(f"[{city}站] 累计消费:{user_data[user]['total']} 元\n")
return process_order
def exercise(minutes):
print(f"运动了 {minutes} 分钟")
先热身 3 分钟!
pi_digits.txt
3.1415926535
8979323846
2643383279
from pathlib import Path
path = Path('pi_digits.txt')
contents = path.read_text()
contents = contents.rstrip()
print(contents)
3.1415926535
8979323846
2643383279
relative path(相对路径)
path = Path('text_files/filename.txt')
absolute path(绝对路径)
path = Path('/home/eric/data_files/text_files/filename.txt')
path = Path('c:/text_files/filename.txt') # recommended
path = Path(r'c:\text_files\filename.txt')
path = Path('c:\\text_files\\filename.txt')
path = Path('c:\text_files\filename.txt') # error
Making a List of Lines from a File
from pathlib import Path
path = Path('pi_digits.txt')
contents = path.read_text()
lines = contents.splitlines()
print(lines)
['3.1415926535', '8979323846', '2643383279']
from pathlib import Path
path = Path('programming.txt')
path.write_text("I love programming.")
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.
from pathlib import Path
contents = "I love programming.\n"
contents += "I love creating new games.\n"
contents += "I also love working with data.\n"
path = Path('programming.txt')
path.write_text(contents)
I love programming.
I love creating new games.
I also love working with data.
from pathlib import Path
path = Path('alice.txt') # File does not exist
contents = path.read_text(encoding='utf-8')
FileNotFoundError: [Errno 2] No such file or directory: 'alice.txt'
from pathlib import Path
path = Path('alice.txt')
try:
contents = path.read_text(encoding='utf-8')
except FileNotFoundError:
print(f"Sorry, the file {path} does not exist.")
else:
words = contents.split()
num_words = len(words)
print(f"The file {path} has about {num_words} words.")
Sorry, the file alice.txt does not exist.
import os
from pathlib import Path
folder_path = r"C:\Users\Lu\Downloads\marvel"
summary = {}
for filename in os.listdir(folder_path): #列出所有文件
# 组成绝对路径
path = Path(os.path.join(folder_path, filename))
contents = path.read_text(errors="ignore") # 跳过非法字符
summary[filename] = len(contents.splitlines()) # 有多少句台词
from pathlib import Path
import json
numbers = [2, 3, 5, 7, 11, 13]
path = Path('numbers.json')
contents = json.dumps(numbers)
path.write_text(contents)
from pathlib import Path
import json
path = Path('numbers.json')
contents = path.read_text()
numbers = json.loads(contents)
print(numbers)
# output: [2, 3, 5, 7, 11, 13]
from pathlib import Path
import json
path = Path('yelp_sample.json')
contents = path.read_text()
lines = contents.splitlines()
yelp = []
for line in lines:
yelp.append(json.loads(line))
print(len(yelp))
print(yelp[100])
import os
from pathlib import Path
folder_path = r"C:\Users\Lu\Downloads\marvel"
summary = {}
for filename in os.listdir(folder_path):
path = Path(os.path.join(folder_path, filename))
contents = path.read_text(errors="ignore")
summary[filename] = len(contents.splitlines())
from pathlib import Path
import json
numbers = [2, 3, 5, 7, 11, 13]
path = Path('numbers.json')
contents = json.dumps(numbers)
path.write_text(contents)
from pathlib import Path
import json
path = Path('numbers.json')
contents = path.read_text()
numbers = json.loads(contents)
print(numbers)