You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
PyLzuCSEdu/4 装饰器-知识版.ipynb

359 lines
7.9 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 函数装饰器\n",
"\n",
"装饰器Decorator是 Python 中一个非常重要的概念,装饰器在不修改原函数代码的情况下,给原函数动态地增加功能。\n",
"\n",
"装饰器本质上是一个高阶函数,它接受一个函数作为参数并返回一个新的函数。\n",
"\n",
"装饰器的常见用途:日志记录、性能测试、权限验证、缓存、事务处理等\n",
"\n",
"装饰器是 Python 中非常强大的特性,合理使用可以让代码更加简洁、优雅,并且符合 DRYDon't Repeat Yourself原则。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 一、基本语法"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 基本装饰器"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"执行前\n",
"Hello!\n",
"执行后\n"
]
}
],
"source": [
"def my_decorator(func):\n",
" def wrapper():\n",
" print(\"执行前\")\n",
" func()\n",
" print(\"执行后\")\n",
" return wrapper\n",
"\n",
"@my_decorator\n",
"def say_hello():\n",
" print(\"Hello!\")\n",
"\n",
"# 调用函数\n",
"say_hello()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 带参数的装饰器"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"执行前\n",
"执行后\n",
"8\n",
"执行前\n",
"执行后\n",
"ChinaLanzhou\n"
]
}
],
"source": [
"def my_decorator(func):\n",
" def wrapper(*args, **kwargs):\n",
" print(\"执行前\")\n",
" result = func(*args, **kwargs)\n",
" print(\"执行后\")\n",
" return result\n",
" return wrapper\n",
"\n",
"@my_decorator\n",
"def add(a, b):\n",
" return a + b\n",
"\n",
"# 调用函数\n",
"print(add(3, 5))\n",
"print(add('China', 'Lanzhou'))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 装饰器带参数"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"你好,小明!\n",
"你好,小明!\n",
"你好,小明!\n"
]
}
],
"source": [
"def repeat(times):\n",
" def decorator(func):\n",
" def wrapper(*args, **kwargs):\n",
" for _ in range(times):\n",
" result = func(*args, **kwargs)\n",
" return result\n",
" return wrapper\n",
" return decorator\n",
"\n",
"@repeat(3)\n",
"def greet(name):\n",
" print(f\"你好,{name}!\")\n",
"\n",
"# 调用函数\n",
"greet(\"小明\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 二、语法设计动机"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"装饰器的基本语法如下\n",
"\n",
"<code>\n",
"@decorator\n",
"def function_to_decorate(*args, **kwargs):\n",
" # 函数体 \n",
"</code> \n",
"\n",
"这等同于:\n",
"<code>\n",
"def function_to_decorate(*args, **kwargs):\n",
" # 函数体 \n",
"function_to_decorate = decorator(function_to_decorate)\n",
"</code> "
]
},
{
"cell_type": "raw",
"metadata": {},
"source": [
"在下面例子中uppercase_decorator 接受一个函数 func 作为参数,并返回一个新的函数 wrapper。\n",
"wrapper 函数将 func 的结果转换为大写。"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"HELLO, ALICE!\n"
]
}
],
"source": [
"# 高阶函数的写法\n",
"\n",
"def greet(name):\n",
" return f\"Hello, {name}!\"\n",
"\n",
"def uppercase_decorator(func):\n",
" def wrapper(name):\n",
" result = func(name)\n",
" return result.upper()\n",
" return wrapper\n",
"\n",
"greet_uppercase = uppercase_decorator(greet)\n",
"print(greet_uppercase(\"Alice\"))"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"HELLO, ALICE!\n"
]
}
],
"source": [
"# 装饰器的写法\n",
"\n",
"def uppercase_decorator(func):\n",
" def wrapper(name):\n",
" result = func(name)\n",
" return result.upper()\n",
" return wrapper\n",
"\n",
"@uppercase_decorator\n",
"def greet(name):\n",
" return f\"Hello, {name}!\"\n",
"\n",
"print(greet(\"Alice\"))"
]
},
{
"cell_type": "raw",
"metadata": {},
"source": [
"在这个例子中,@uppercase_decorator 等价于 greet = uppercase_decorator(greet)。\n",
"使用装饰器,结构更清楚,使用更方便。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 三、应用"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"函数执行完毕\n",
"函数 slow_function 执行时间1.0016472339630127秒\n"
]
}
],
"source": [
"# 一个简单的计时装饰器\n",
"\n",
"import time\n",
"\n",
"def timer(func):\n",
" def wrapper(*args, **kwargs):\n",
" start = time.time()\n",
" result = func(*args, **kwargs)\n",
" end = time.time()\n",
" print(f\"函数 {func.__name__} 执行时间:{end - start}秒\")\n",
" return result\n",
" return wrapper\n",
"\n",
"@timer\n",
"def slow_function():\n",
" time.sleep(1)\n",
" print(\"函数执行完毕\")\n",
"\n",
"# 调用函数\n",
"slow_function()"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'<b><i> hello china 2025 </i></b>'"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"### 一个标记文本生成工具\n",
"\n",
"def make_bold(fn): \n",
" def inner(s): return \"<b>\" + fn(s) + \"</b>\" \n",
" return inner\n",
"def make_italic(fn): \n",
" def inner(s): return \"<i>\" + fn(s) + \"</i>\" \n",
" return inner\n",
"\n",
"@make_bold\n",
"@make_italic\n",
"def hello(s) : return s\n",
"\n",
"hello( ' hello china 2025 ')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 其它\n",
"\n",
"- 当有多个装饰器时,装饰器的执行顺序是**从下到上**\n",
"- Python 内置了很多实用的装饰器,如 @property、@staticmethod、@classmethod 等\n",
"- 装饰器也可以使用类创建"
]
}
],
"metadata": {
"hide_input": false,
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.3"
}
},
"nbformat": 4,
"nbformat_minor": 4
}