4660 lines
200 KiB
Plaintext
4660 lines
200 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# \u7b2c\u4e5d\u7ae0\uff1a\u5143\u7f16\u7a0b\n \u8f6f\u4ef6\u5f00\u53d1\u9886\u57df\u4e2d\u6700\u7ecf\u5178\u7684\u53e3\u5934\u7985\u5c31\u662f\u201cdon\u2019t repeat yourself\u201d\u3002\n\u4e5f\u5c31\u662f\u8bf4\uff0c\u4efb\u4f55\u65f6\u5019\u5f53\u4f60\u7684\u7a0b\u5e8f\u4e2d\u5b58\u5728\u9ad8\u5ea6\u91cd\u590d(\u6216\u8005\u662f\u901a\u8fc7\u526a\u5207\u590d\u5236)\u7684\u4ee3\u7801\u65f6\uff0c\u90fd\u5e94\u8be5\u60f3\u60f3\u662f\u5426\u6709\u66f4\u597d\u7684\u89e3\u51b3\u65b9\u6848\u3002\n\u5728Python\u5f53\u4e2d\uff0c\u901a\u5e38\u90fd\u53ef\u4ee5\u901a\u8fc7\u5143\u7f16\u7a0b\u6765\u89e3\u51b3\u8fd9\u7c7b\u95ee\u9898\u3002\n\u7b80\u800c\u8a00\u4e4b\uff0c\u5143\u7f16\u7a0b\u5c31\u662f\u5173\u4e8e\u521b\u5efa\u64cd\u4f5c\u6e90\u4ee3\u7801(\u6bd4\u5982\u4fee\u6539\u3001\u751f\u6210\u6216\u5305\u88c5\u539f\u6765\u7684\u4ee3\u7801)\u7684\u51fd\u6570\u548c\u7c7b\u3002\n\u4e3b\u8981\u6280\u672f\u662f\u4f7f\u7528\u88c5\u9970\u5668\u3001\u7c7b\u88c5\u9970\u5668\u548c\u5143\u7c7b\u3002\u4e0d\u8fc7\u8fd8\u6709\u4e00\u4e9b\u5176\u4ed6\u6280\u672f\uff0c\n\u5305\u62ec\u7b7e\u540d\u5bf9\u8c61\u3001\u4f7f\u7528 exec() \u6267\u884c\u4ee3\u7801\u4ee5\u53ca\u5bf9\u5185\u90e8\u51fd\u6570\u548c\u7c7b\u7684\u53cd\u5c04\u6280\u672f\u7b49\u3002\n\u672c\u7ae0\u7684\u4e3b\u8981\u76ee\u7684\u662f\u5411\u5927\u5bb6\u4ecb\u7ecd\u8fd9\u4e9b\u5143\u7f16\u7a0b\u6280\u672f\uff0c\u5e76\u4e14\u7ed9\u51fa\u5b9e\u4f8b\u6765\u6f14\u793a\u5b83\u4eec\u662f\u600e\u6837\u5b9a\u5236\u5316\u4f60\u7684\u6e90\u4ee3\u7801\u884c\u4e3a\u7684\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 9.1 \u5728\u51fd\u6570\u4e0a\u6dfb\u52a0\u5305\u88c5\u5668\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u95ee\u9898\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f60\u60f3\u5728\u51fd\u6570\u4e0a\u6dfb\u52a0\u4e00\u4e2a\u5305\u88c5\u5668\uff0c\u589e\u52a0\u989d\u5916\u7684\u64cd\u4f5c\u5904\u7406(\u6bd4\u5982\u65e5\u5fd7\u3001\u8ba1\u65f6\u7b49)\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u89e3\u51b3\u65b9\u6848\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5982\u679c\u4f60\u60f3\u4f7f\u7528\u989d\u5916\u7684\u4ee3\u7801\u5305\u88c5\u4e00\u4e2a\u51fd\u6570\uff0c\u53ef\u4ee5\u5b9a\u4e49\u4e00\u4e2a\u88c5\u9970\u5668\u51fd\u6570\uff0c\u4f8b\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import time\nfrom functools import wraps\n\ndef timethis(func):\n '''\n Decorator that reports the execution time.\n '''\n @wraps(func)\n def wrapper(*args, **kwargs):\n start = time.time()\n result = func(*args, **kwargs)\n end = time.time()\n print(func.__name__, end-start)\n return result\n return wrapper"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e0b\u9762\u662f\u4f7f\u7528\u88c5\u9970\u5668\u7684\u4f8b\u5b50\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"@timethis\ndef countdown(n):\n '''\n Counts down\n '''\n while n > 0:\n n -= 1\ncountdown(100000)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"countdown(10000000)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u8ba8\u8bba\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e00\u4e2a\u88c5\u9970\u5668\u5c31\u662f\u4e00\u4e2a\u51fd\u6570\uff0c\u5b83\u63a5\u53d7\u4e00\u4e2a\u51fd\u6570\u4f5c\u4e3a\u53c2\u6570\u5e76\u8fd4\u56de\u4e00\u4e2a\u65b0\u7684\u51fd\u6570\u3002\n\u5f53\u4f60\u50cf\u4e0b\u9762\u8fd9\u6837\u5199\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"@timethis\ndef countdown(n):\n pass"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u8ddf\u50cf\u4e0b\u9762\u8fd9\u6837\u5199\u5176\u5b9e\u6548\u679c\u662f\u4e00\u6837\u7684\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def countdown(n):\n pass\ncountdown = timethis(countdown)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u987a\u4fbf\u8bf4\u4e00\u4e0b\uff0c\u5185\u7f6e\u7684\u88c5\u9970\u5668\u6bd4\u5982 @staticmethod, @classmethod,@property \u539f\u7406\u4e5f\u662f\u4e00\u6837\u7684\u3002\n\u4f8b\u5982\uff0c\u4e0b\u9762\u8fd9\u4e24\u4e2a\u4ee3\u7801\u7247\u6bb5\u662f\u7b49\u4ef7\u7684\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class A:\n @classmethod\n def method(cls):\n pass\n\nclass B:\n # Equivalent definition of a class method\n def method(cls):\n pass\n method = classmethod(method)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5728\u4e0a\u9762\u7684 wrapper() \u51fd\u6570\u4e2d\uff0c\n\u88c5\u9970\u5668\u5185\u90e8\u5b9a\u4e49\u4e86\u4e00\u4e2a\u4f7f\u7528 *args \u548c **kwargs \u6765\u63a5\u53d7\u4efb\u610f\u53c2\u6570\u7684\u51fd\u6570\u3002\n\u5728\u8fd9\u4e2a\u51fd\u6570\u91cc\u9762\u8c03\u7528\u4e86\u539f\u59cb\u51fd\u6570\u5e76\u5c06\u5176\u7ed3\u679c\u8fd4\u56de\uff0c\u4e0d\u8fc7\u4f60\u8fd8\u53ef\u4ee5\u6dfb\u52a0\u5176\u4ed6\u989d\u5916\u7684\u4ee3\u7801(\u6bd4\u5982\u8ba1\u65f6)\u3002\n\u7136\u540e\u8fd9\u4e2a\u65b0\u7684\u51fd\u6570\u5305\u88c5\u5668\u88ab\u4f5c\u4e3a\u7ed3\u679c\u8fd4\u56de\u6765\u4ee3\u66ff\u539f\u59cb\u51fd\u6570\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u9700\u8981\u5f3a\u8c03\u7684\u662f\u88c5\u9970\u5668\u5e76\u4e0d\u4f1a\u4fee\u6539\u539f\u59cb\u51fd\u6570\u7684\u53c2\u6570\u7b7e\u540d\u4ee5\u53ca\u8fd4\u56de\u503c\u3002\n\u4f7f\u7528 *args \u548c **kwargs \u76ee\u7684\u5c31\u662f\u786e\u4fdd\u4efb\u4f55\u53c2\u6570\u90fd\u80fd\u9002\u7528\u3002\n\u800c\u8fd4\u56de\u7ed3\u679c\u503c\u57fa\u672c\u90fd\u662f\u8c03\u7528\u539f\u59cb\u51fd\u6570 func(*args, **kwargs) \u7684\u8fd4\u56de\u7ed3\u679c\uff0c\u5176\u4e2dfunc\u5c31\u662f\u539f\u59cb\u51fd\u6570\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u521a\u5f00\u59cb\u5b66\u4e60\u88c5\u9970\u5668\u7684\u65f6\u5019\uff0c\u4f1a\u4f7f\u7528\u4e00\u4e9b\u7b80\u5355\u7684\u4f8b\u5b50\u6765\u8bf4\u660e\uff0c\u6bd4\u5982\u4e0a\u9762\u6f14\u793a\u7684\u8fd9\u4e2a\u3002\n\u4e0d\u8fc7\u5b9e\u9645\u573a\u666f\u4f7f\u7528\u65f6\uff0c\u8fd8\u662f\u6709\u4e00\u4e9b\u7ec6\u8282\u95ee\u9898\u8981\u6ce8\u610f\u7684\u3002\n\u6bd4\u5982\u4e0a\u9762\u4f7f\u7528 @wraps(func) \u6ce8\u89e3\u662f\u5f88\u91cd\u8981\u7684\uff0c\n\u5b83\u80fd\u4fdd\u7559\u539f\u59cb\u51fd\u6570\u7684\u5143\u6570\u636e(\u4e0b\u4e00\u5c0f\u8282\u4f1a\u8bb2\u5230)\uff0c\u65b0\u624b\u7ecf\u5e38\u4f1a\u5ffd\u7565\u8fd9\u4e2a\u7ec6\u8282\u3002\n\u63a5\u4e0b\u6765\u7684\u51e0\u4e2a\u5c0f\u8282\u6211\u4eec\u4f1a\u66f4\u52a0\u6df1\u5165\u7684\u8bb2\u89e3\u88c5\u9970\u5668\u51fd\u6570\u7684\u7ec6\u8282\u95ee\u9898\uff0c\u5982\u679c\u4f60\u60f3\u6784\u9020\u4f60\u81ea\u5df1\u7684\u88c5\u9970\u5668\u51fd\u6570\uff0c\u9700\u8981\u8ba4\u771f\u770b\u4e00\u4e0b\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 9.2 \u521b\u5efa\u88c5\u9970\u5668\u65f6\u4fdd\u7559\u51fd\u6570\u5143\u4fe1\u606f\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u95ee\u9898\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f60\u5199\u4e86\u4e00\u4e2a\u88c5\u9970\u5668\u4f5c\u7528\u5728\u67d0\u4e2a\u51fd\u6570\u4e0a\uff0c\u4f46\u662f\u8fd9\u4e2a\u51fd\u6570\u7684\u91cd\u8981\u7684\u5143\u4fe1\u606f\u6bd4\u5982\u540d\u5b57\u3001\u6587\u6863\u5b57\u7b26\u4e32\u3001\u6ce8\u89e3\u548c\u53c2\u6570\u7b7e\u540d\u90fd\u4e22\u5931\u4e86\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u89e3\u51b3\u65b9\u6848\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4efb\u4f55\u65f6\u5019\u4f60\u5b9a\u4e49\u88c5\u9970\u5668\u7684\u65f6\u5019\uff0c\u90fd\u5e94\u8be5\u4f7f\u7528 functools \u5e93\u4e2d\u7684 @wraps \u88c5\u9970\u5668\u6765\u6ce8\u89e3\u5e95\u5c42\u5305\u88c5\u51fd\u6570\u3002\u4f8b\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import time\nfrom functools import wraps\ndef timethis(func):\n '''\n Decorator that reports the execution time.\n '''\n @wraps(func)\n def wrapper(*args, **kwargs):\n start = time.time()\n result = func(*args, **kwargs)\n end = time.time()\n print(func.__name__, end-start)\n return result\n return wrapper"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e0b\u9762\u6211\u4eec\u4f7f\u7528\u8fd9\u4e2a\u88ab\u5305\u88c5\u540e\u7684\u51fd\u6570\u5e76\u68c0\u67e5\u5b83\u7684\u5143\u4fe1\u606f\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"@timethis\ndef countdown(n):\n '''\n Counts down\n '''\n while n > 0:\n n -= 1\ncountdown(100000)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"countdown.__name__"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"countdown.__doc__"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"countdown.__annotations__"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u8ba8\u8bba\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5728\u7f16\u5199\u88c5\u9970\u5668\u7684\u65f6\u5019\u590d\u5236\u5143\u4fe1\u606f\u662f\u4e00\u4e2a\u975e\u5e38\u91cd\u8981\u7684\u90e8\u5206\u3002\u5982\u679c\u4f60\u5fd8\u8bb0\u4e86\u4f7f\u7528 @wraps \uff0c\n\u90a3\u4e48\u4f60\u4f1a\u53d1\u73b0\u88ab\u88c5\u9970\u51fd\u6570\u4e22\u5931\u4e86\u6240\u6709\u6709\u7528\u7684\u4fe1\u606f\u3002\u6bd4\u5982\u5982\u679c\u5ffd\u7565 @wraps \u540e\u7684\u6548\u679c\u662f\u4e0b\u9762\u8fd9\u6837\u7684\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"countdown.__name__"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"countdown.__doc__\ncountdown.__annotations__"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"@wraps \u6709\u4e00\u4e2a\u91cd\u8981\u7279\u5f81\u662f\u5b83\u80fd\u8ba9\u4f60\u901a\u8fc7\u5c5e\u6027 __wrapped__ \u76f4\u63a5\u8bbf\u95ee\u88ab\u5305\u88c5\u51fd\u6570\u3002\u4f8b\u5982:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"countdown.__wrapped__(100000)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"__wrapped__ \u5c5e\u6027\u8fd8\u80fd\u8ba9\u88ab\u88c5\u9970\u51fd\u6570\u6b63\u786e\u66b4\u9732\u5e95\u5c42\u7684\u53c2\u6570\u7b7e\u540d\u4fe1\u606f\u3002\u4f8b\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from inspect import signature\nprint(signature(countdown))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e00\u4e2a\u5f88\u666e\u904d\u7684\u95ee\u9898\u662f\u600e\u6837\u8ba9\u88c5\u9970\u5668\u53bb\u76f4\u63a5\u590d\u5236\u539f\u59cb\u51fd\u6570\u7684\u53c2\u6570\u7b7e\u540d\u4fe1\u606f\uff0c\n\u5982\u679c\u60f3\u81ea\u5df1\u624b\u52a8\u5b9e\u73b0\u7684\u8bdd\u9700\u8981\u505a\u5927\u91cf\u7684\u5de5\u4f5c\uff0c\u6700\u597d\u5c31\u7b80\u5355\u7684\u4f7f\u7528 @wraps \u88c5\u9970\u5668\u3002\n\u901a\u8fc7\u5e95\u5c42\u7684 __wrapped__ \u5c5e\u6027\u8bbf\u95ee\u5230\u51fd\u6570\u7b7e\u540d\u4fe1\u606f\u3002\u66f4\u591a\u5173\u4e8e\u7b7e\u540d\u7684\u5185\u5bb9\u53ef\u4ee5\u53c2\u80039.16\u5c0f\u8282\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 9.3 \u89e3\u9664\u4e00\u4e2a\u88c5\u9970\u5668\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u95ee\u9898\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e00\u4e2a\u88c5\u9970\u5668\u5df2\u7ecf\u4f5c\u7528\u5728\u4e00\u4e2a\u51fd\u6570\u4e0a\uff0c\u4f60\u60f3\u64a4\u9500\u5b83\uff0c\u76f4\u63a5\u8bbf\u95ee\u539f\u59cb\u7684\u672a\u5305\u88c5\u7684\u90a3\u4e2a\u51fd\u6570\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u89e3\u51b3\u65b9\u6848\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5047\u8bbe\u88c5\u9970\u5668\u662f\u901a\u8fc7 @wraps (\u53c2\u80039.2\u5c0f\u8282)\u6765\u5b9e\u73b0\u7684\uff0c\u90a3\u4e48\u4f60\u53ef\u4ee5\u901a\u8fc7\u8bbf\u95ee __wrapped__ \u5c5e\u6027\u6765\u8bbf\u95ee\u539f\u59cb\u51fd\u6570\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"@somedecorator\ndef add(x, y):\n return x + y\norig_add = add.__wrapped__\norig_add(3, 4)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u8ba8\u8bba\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u76f4\u63a5\u8bbf\u95ee\u672a\u5305\u88c5\u7684\u539f\u59cb\u51fd\u6570\u5728\u8c03\u8bd5\u3001\u5185\u7701\u548c\u5176\u4ed6\u51fd\u6570\u64cd\u4f5c\u65f6\u662f\u5f88\u6709\u7528\u7684\u3002\n\u4f46\u662f\u6211\u4eec\u8fd9\u91cc\u7684\u65b9\u6848\u4ec5\u4ec5\u9002\u7528\u4e8e\u5728\u5305\u88c5\u5668\u4e2d\u6b63\u786e\u4f7f\u7528\u4e86 @wraps \u6216\u8005\u76f4\u63a5\u8bbe\u7f6e\u4e86 __wrapped__ \u5c5e\u6027\u7684\u60c5\u51b5\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5982\u679c\u6709\u591a\u4e2a\u5305\u88c5\u5668\uff0c\u90a3\u4e48\u8bbf\u95ee __wrapped__ \u5c5e\u6027\u7684\u884c\u4e3a\u662f\u4e0d\u53ef\u9884\u77e5\u7684\uff0c\u5e94\u8be5\u907f\u514d\u8fd9\u6837\u505a\u3002\n\u5728Python3.3\u4e2d\uff0c\u5b83\u4f1a\u7565\u8fc7\u6240\u6709\u7684\u5305\u88c5\u5c42\uff0c\u6bd4\u5982\uff0c\u5047\u5982\u4f60\u6709\u5982\u4e0b\u7684\u4ee3\u7801\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from functools import wraps\n\ndef decorator1(func):\n @wraps(func)\n def wrapper(*args, **kwargs):\n print('Decorator 1')\n return func(*args, **kwargs)\n return wrapper\n\ndef decorator2(func):\n @wraps(func)\n def wrapper(*args, **kwargs):\n print('Decorator 2')\n return func(*args, **kwargs)\n return wrapper\n\n@decorator1\n@decorator2\ndef add(x, y):\n return x + y"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e0b\u9762\u6211\u4eec\u5728Python3.3\u4e0b\u6d4b\u8bd5\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"add(2, 3)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"add.__wrapped__(2, 3)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e0b\u9762\u6211\u4eec\u5728Python3.4\u4e0b\u6d4b\u8bd5\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"add(2, 3)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"add.__wrapped__(2, 3)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u6700\u540e\u8981\u8bf4\u7684\u662f\uff0c\u5e76\u4e0d\u662f\u6240\u6709\u7684\u88c5\u9970\u5668\u90fd\u4f7f\u7528\u4e86 @wraps \uff0c\u56e0\u6b64\u8fd9\u91cc\u7684\u65b9\u6848\u5e76\u4e0d\u5168\u90e8\u9002\u7528\u3002\n\u7279\u522b\u7684\uff0c\u5185\u7f6e\u7684\u88c5\u9970\u5668 @staticmethod \u548c @classmethod \u5c31\u6ca1\u6709\u9075\u5faa\u8fd9\u4e2a\u7ea6\u5b9a\n(\u5b83\u4eec\u628a\u539f\u59cb\u51fd\u6570\u5b58\u50a8\u5728\u5c5e\u6027 __func__ \u4e2d)\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 9.4 \u5b9a\u4e49\u4e00\u4e2a\u5e26\u53c2\u6570\u7684\u88c5\u9970\u5668\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u95ee\u9898\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f60\u60f3\u5b9a\u4e49\u4e00\u4e2a\u53ef\u4ee5\u63a5\u53d7\u53c2\u6570\u7684\u88c5\u9970\u5668"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u89e3\u51b3\u65b9\u6848\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u6211\u4eec\u7528\u4e00\u4e2a\u4f8b\u5b50\u8be6\u7ec6\u9610\u8ff0\u4e0b\u63a5\u53d7\u53c2\u6570\u7684\u5904\u7406\u8fc7\u7a0b\u3002\n\u5047\u8bbe\u4f60\u60f3\u5199\u4e00\u4e2a\u88c5\u9970\u5668\uff0c\u7ed9\u51fd\u6570\u6dfb\u52a0\u65e5\u5fd7\u529f\u80fd\uff0c\u540c\u65f6\u5141\u8bb8\u7528\u6237\u6307\u5b9a\u65e5\u5fd7\u7684\u7ea7\u522b\u548c\u5176\u4ed6\u7684\u9009\u9879\u3002\n\u4e0b\u9762\u662f\u8fd9\u4e2a\u88c5\u9970\u5668\u7684\u5b9a\u4e49\u548c\u4f7f\u7528\u793a\u4f8b\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from functools import wraps\nimport logging\n\ndef logged(level, name=None, message=None):\n \"\"\"\n Add logging to a function. level is the logging\n level, name is the logger name, and message is the\n log message. If name and message aren't specified,\n they default to the function's module and name.\n \"\"\"\n def decorate(func):\n logname = name if name else func.__module__\n log = logging.getLogger(logname)\n logmsg = message if message else func.__name__\n\n @wraps(func)\n def wrapper(*args, **kwargs):\n log.log(level, logmsg)\n return func(*args, **kwargs)\n return wrapper\n return decorate\n\n# Example use\n@logged(logging.DEBUG)\ndef add(x, y):\n return x + y\n\n@logged(logging.CRITICAL, 'example')\ndef spam():\n print('Spam!')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u521d\u770b\u8d77\u6765\uff0c\u8fd9\u79cd\u5b9e\u73b0\u770b\u4e0a\u53bb\u5f88\u590d\u6742\uff0c\u4f46\u662f\u6838\u5fc3\u601d\u60f3\u5f88\u7b80\u5355\u3002\n\u6700\u5916\u5c42\u7684\u51fd\u6570 logged() \u63a5\u53d7\u53c2\u6570\u5e76\u5c06\u5b83\u4eec\u4f5c\u7528\u5728\u5185\u90e8\u7684\u88c5\u9970\u5668\u51fd\u6570\u4e0a\u9762\u3002\n\u5185\u5c42\u7684\u51fd\u6570 decorate() \u63a5\u53d7\u4e00\u4e2a\u51fd\u6570\u4f5c\u4e3a\u53c2\u6570\uff0c\u7136\u540e\u5728\u51fd\u6570\u4e0a\u9762\u653e\u7f6e\u4e00\u4e2a\u5305\u88c5\u5668\u3002\n\u8fd9\u91cc\u7684\u5173\u952e\u70b9\u662f\u5305\u88c5\u5668\u662f\u53ef\u4ee5\u4f7f\u7528\u4f20\u9012\u7ed9 logged() \u7684\u53c2\u6570\u7684\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u8ba8\u8bba\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5b9a\u4e49\u4e00\u4e2a\u63a5\u53d7\u53c2\u6570\u7684\u5305\u88c5\u5668\u770b\u4e0a\u53bb\u6bd4\u8f83\u590d\u6742\u4e3b\u8981\u662f\u56e0\u4e3a\u5e95\u5c42\u7684\u8c03\u7528\u5e8f\u5217\u3002\u7279\u522b\u7684\uff0c\u5982\u679c\u4f60\u6709\u4e0b\u9762\u8fd9\u4e2a\u4ee3\u7801\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"@decorator(x, y, z)\ndef func(a, b):\n pass"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u88c5\u9970\u5668\u5904\u7406\u8fc7\u7a0b\u8ddf\u4e0b\u9762\u7684\u8c03\u7528\u662f\u7b49\u6548\u7684;"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def func(a, b):\n pass\nfunc = decorator(x, y, z)(func)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"decorator(x, y, z) \u7684\u8fd4\u56de\u7ed3\u679c\u5fc5\u987b\u662f\u4e00\u4e2a\u53ef\u8c03\u7528\u5bf9\u8c61\uff0c\u5b83\u63a5\u53d7\u4e00\u4e2a\u51fd\u6570\u4f5c\u4e3a\u53c2\u6570\u5e76\u5305\u88c5\u5b83\uff0c\n\u53ef\u4ee5\u53c2\u80039.7\u5c0f\u8282\u4e2d\u53e6\u5916\u4e00\u4e2a\u53ef\u63a5\u53d7\u53c2\u6570\u7684\u5305\u88c5\u5668\u4f8b\u5b50\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 9.5 \u53ef\u81ea\u5b9a\u4e49\u5c5e\u6027\u7684\u88c5\u9970\u5668\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u95ee\u9898\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f60\u60f3\u5199\u4e00\u4e2a\u88c5\u9970\u5668\u6765\u5305\u88c5\u4e00\u4e2a\u51fd\u6570\uff0c\u5e76\u4e14\u5141\u8bb8\u7528\u6237\u63d0\u4f9b\u53c2\u6570\u5728\u8fd0\u884c\u65f6\u63a7\u5236\u88c5\u9970\u5668\u884c\u4e3a\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u89e3\u51b3\u65b9\u6848\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5f15\u5165\u4e00\u4e2a\u8bbf\u95ee\u51fd\u6570\uff0c\u4f7f\u7528 nonlocal \u6765\u4fee\u6539\u5185\u90e8\u53d8\u91cf\u3002\n\u7136\u540e\u8fd9\u4e2a\u8bbf\u95ee\u51fd\u6570\u88ab\u4f5c\u4e3a\u4e00\u4e2a\u5c5e\u6027\u8d4b\u503c\u7ed9\u5305\u88c5\u51fd\u6570\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from functools import wraps, partial\nimport logging\n# Utility decorator to attach a function as an attribute of obj\ndef attach_wrapper(obj, func=None):\n if func is None:\n return partial(attach_wrapper, obj)\n setattr(obj, func.__name__, func)\n return func\n\ndef logged(level, name=None, message=None):\n '''\n Add logging to a function. level is the logging\n level, name is the logger name, and message is the\n log message. If name and message aren't specified,\n they default to the function's module and name.\n '''\n def decorate(func):\n logname = name if name else func.__module__\n log = logging.getLogger(logname)\n logmsg = message if message else func.__name__\n\n @wraps(func)\n def wrapper(*args, **kwargs):\n log.log(level, logmsg)\n return func(*args, **kwargs)\n\n # Attach setter functions\n @attach_wrapper(wrapper)\n def set_level(newlevel):\n nonlocal level\n level = newlevel\n\n @attach_wrapper(wrapper)\n def set_message(newmsg):\n nonlocal logmsg\n logmsg = newmsg\n\n return wrapper\n\n return decorate\n\n# Example use\n@logged(logging.DEBUG)\ndef add(x, y):\n return x + y\n\n@logged(logging.CRITICAL, 'example')\ndef spam():\n print('Spam!')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e0b\u9762\u662f\u4ea4\u4e92\u73af\u5883\u4e0b\u7684\u4f7f\u7528\u4f8b\u5b50\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import logging\nlogging.basicConfig(level=logging.DEBUG)\nadd(2, 3)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Change the log message\nadd.set_message('Add called')\nadd(2, 3)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Change the log level\nadd.set_level(logging.WARNING)\nadd(2, 3)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u8ba8\u8bba\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u8fd9\u4e00\u5c0f\u8282\u7684\u5173\u952e\u70b9\u5728\u4e8e\u8bbf\u95ee\u51fd\u6570(\u5982 set_message() \u548c set_level() )\uff0c\u5b83\u4eec\u88ab\u4f5c\u4e3a\u5c5e\u6027\u8d4b\u7ed9\u5305\u88c5\u5668\u3002\n\u6bcf\u4e2a\u8bbf\u95ee\u51fd\u6570\u5141\u8bb8\u4f7f\u7528 nonlocal \u6765\u4fee\u6539\u51fd\u6570\u5185\u90e8\u7684\u53d8\u91cf\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u8fd8\u6709\u4e00\u4e2a\u4ee4\u4eba\u5403\u60ca\u7684\u5730\u65b9\u662f\u8bbf\u95ee\u51fd\u6570\u4f1a\u5728\u591a\u5c42\u88c5\u9970\u5668\u95f4\u4f20\u64ad(\u5982\u679c\u4f60\u7684\u88c5\u9970\u5668\u90fd\u4f7f\u7528\u4e86 @functools.wraps \u6ce8\u89e3)\u3002\n\u4f8b\u5982\uff0c\u5047\u8bbe\u4f60\u5f15\u5165\u53e6\u5916\u4e00\u4e2a\u88c5\u9970\u5668\uff0c\u6bd4\u59829.2\u5c0f\u8282\u4e2d\u7684 @timethis \uff0c\u50cf\u4e0b\u9762\u8fd9\u6837\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"@timethis\n@logged(logging.DEBUG)\ndef countdown(n):\n while n > 0:\n n -= 1"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f60\u4f1a\u53d1\u73b0\u8bbf\u95ee\u51fd\u6570\u4f9d\u65e7\u6709\u6548\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"countdown(10000000)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"countdown.set_level(logging.WARNING)\ncountdown.set_message(\"Counting down to zero\")\ncountdown(10000000)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f60\u8fd8\u4f1a\u53d1\u73b0\u5373\u4f7f\u88c5\u9970\u5668\u50cf\u4e0b\u9762\u8fd9\u6837\u4ee5\u76f8\u53cd\u7684\u65b9\u5411\u6392\u653e\uff0c\u6548\u679c\u4e5f\u662f\u4e00\u6837\u7684\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"@logged(logging.DEBUG)\n@timethis\ndef countdown(n):\n while n > 0:\n n -= 1"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u8fd8\u80fd\u901a\u8fc7\u4f7f\u7528lambda\u8868\u8fbe\u5f0f\u4ee3\u7801\u6765\u8ba9\u8bbf\u95ee\u51fd\u6570\u7684\u8fd4\u56de\u4e0d\u540c\u7684\u8bbe\u5b9a\u503c\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"@attach_wrapper(wrapper)\ndef get_level():\n return level\n\n# Alternative\nwrapper.get_level = lambda: level"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e00\u4e2a\u6bd4\u8f83\u96be\u7406\u89e3\u7684\u5730\u65b9\u5c31\u662f\u5bf9\u4e8e\u8bbf\u95ee\u51fd\u6570\u7684\u9996\u6b21\u4f7f\u7528\u3002\u4f8b\u5982\uff0c\u4f60\u53ef\u80fd\u4f1a\u8003\u8651\u53e6\u5916\u4e00\u4e2a\u65b9\u6cd5\u76f4\u63a5\u8bbf\u95ee\u51fd\u6570\u7684\u5c5e\u6027\uff0c\u5982\u4e0b\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"@wraps(func)\ndef wrapper(*args, **kwargs):\n wrapper.log.log(wrapper.level, wrapper.logmsg)\n return func(*args, **kwargs)\n\n# Attach adjustable attributes\nwrapper.level = level\nwrapper.logmsg = logmsg\nwrapper.log = log"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u8fd9\u4e2a\u65b9\u6cd5\u4e5f\u53ef\u80fd\u6b63\u5e38\u5de5\u4f5c\uff0c\u4f46\u524d\u63d0\u662f\u5b83\u5fc5\u987b\u662f\u6700\u5916\u5c42\u7684\u88c5\u9970\u5668\u624d\u884c\u3002\n\u5982\u679c\u5b83\u7684\u4e0a\u9762\u8fd8\u6709\u53e6\u5916\u7684\u88c5\u9970\u5668(\u6bd4\u5982\u4e0a\u9762\u63d0\u5230\u7684 @timethis \u4f8b\u5b50)\uff0c\u90a3\u4e48\u5b83\u4f1a\u9690\u85cf\u5e95\u5c42\u5c5e\u6027\uff0c\u4f7f\u5f97\u4fee\u6539\u5b83\u4eec\u6ca1\u6709\u4efb\u4f55\u4f5c\u7528\u3002\n\u800c\u901a\u8fc7\u4f7f\u7528\u8bbf\u95ee\u51fd\u6570\u5c31\u80fd\u907f\u514d\u8fd9\u6837\u7684\u5c40\u9650\u6027\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u6700\u540e\u63d0\u4e00\u70b9\uff0c\u8fd9\u4e00\u5c0f\u8282\u7684\u65b9\u6848\u4e5f\u53ef\u4ee5\u4f5c\u4e3a9.9\u5c0f\u8282\u4e2d\u88c5\u9970\u5668\u7c7b\u7684\u53e6\u4e00\u79cd\u5b9e\u73b0\u65b9\u6cd5\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 9.6 \u5e26\u53ef\u9009\u53c2\u6570\u7684\u88c5\u9970\u5668\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u95ee\u9898\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f60\u60f3\u5199\u4e00\u4e2a\u88c5\u9970\u5668\uff0c\u65e2\u53ef\u4ee5\u4e0d\u4f20\u53c2\u6570\u7ed9\u5b83\uff0c\u6bd4\u5982 @decorator \uff0c\n\u4e5f\u53ef\u4ee5\u4f20\u9012\u53ef\u9009\u53c2\u6570\u7ed9\u5b83\uff0c\u6bd4\u5982 @decorator(x,y,z) \u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u89e3\u51b3\u65b9\u6848\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e0b\u9762\u662f9.5\u5c0f\u8282\u4e2d\u65e5\u5fd7\u88c5\u9970\u5668\u7684\u4e00\u4e2a\u4fee\u6539\u7248\u672c\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from functools import wraps, partial\nimport logging\n\ndef logged(func=None, *, level=logging.DEBUG, name=None, message=None):\n if func is None:\n return partial(logged, level=level, name=name, message=message)\n\n logname = name if name else func.__module__\n log = logging.getLogger(logname)\n logmsg = message if message else func.__name__\n\n @wraps(func)\n def wrapper(*args, **kwargs):\n log.log(level, logmsg)\n return func(*args, **kwargs)\n\n return wrapper\n\n# Example use\n@logged\ndef add(x, y):\n return x + y\n\n@logged(level=logging.CRITICAL, name='example')\ndef spam():\n print('Spam!')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u53ef\u4ee5\u770b\u5230\uff0c@logged \u88c5\u9970\u5668\u53ef\u4ee5\u540c\u65f6\u4e0d\u5e26\u53c2\u6570\u6216\u5e26\u53c2\u6570\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u8ba8\u8bba\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u8fd9\u91cc\u63d0\u5230\u7684\u8fd9\u4e2a\u95ee\u9898\u5c31\u662f\u901a\u5e38\u6240\u8bf4\u7684\u7f16\u7a0b\u4e00\u81f4\u6027\u95ee\u9898\u3002\n\u5f53\u6211\u4eec\u4f7f\u7528\u88c5\u9970\u5668\u7684\u65f6\u5019\uff0c\u5927\u90e8\u5206\u7a0b\u5e8f\u5458\u4e60\u60ef\u4e86\u8981\u4e48\u4e0d\u7ed9\u5b83\u4eec\u4f20\u9012\u4efb\u4f55\u53c2\u6570\uff0c\u8981\u4e48\u7ed9\u5b83\u4eec\u4f20\u9012\u786e\u5207\u53c2\u6570\u3002\n\u5176\u5b9e\u4ece\u6280\u672f\u4e0a\u6765\u8bb2\uff0c\u6211\u4eec\u53ef\u4ee5\u5b9a\u4e49\u4e00\u4e2a\u6240\u6709\u53c2\u6570\u90fd\u662f\u53ef\u9009\u7684\u88c5\u9970\u5668\uff0c\u5c31\u50cf\u4e0b\u9762\u8fd9\u6837\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"@logged()\ndef add(x, y):\n return x+y"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f46\u662f\uff0c\u8fd9\u79cd\u5199\u6cd5\u5e76\u4e0d\u7b26\u5408\u6211\u4eec\u7684\u4e60\u60ef\uff0c\u6709\u65f6\u5019\u7a0b\u5e8f\u5458\u5fd8\u8bb0\u52a0\u4e0a\u540e\u9762\u7684\u62ec\u53f7\u4f1a\u5bfc\u81f4\u9519\u8bef\u3002\n\u8fd9\u91cc\u6211\u4eec\u5411\u4f60\u5c55\u793a\u4e86\u5982\u4f55\u4ee5\u4e00\u81f4\u7684\u7f16\u7a0b\u98ce\u683c\u6765\u540c\u65f6\u6ee1\u8db3\u6ca1\u6709\u62ec\u53f7\u548c\u6709\u62ec\u53f7\u4e24\u79cd\u60c5\u51b5\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e3a\u4e86\u7406\u89e3\u4ee3\u7801\u662f\u5982\u4f55\u5de5\u4f5c\u7684\uff0c\u4f60\u9700\u8981\u975e\u5e38\u719f\u6089\u88c5\u9970\u5668\u662f\u5982\u4f55\u4f5c\u7528\u5230\u51fd\u6570\u4e0a\u4ee5\u53ca\u5b83\u4eec\u7684\u8c03\u7528\u89c4\u5219\u3002\n\u5bf9\u4e8e\u4e00\u4e2a\u50cf\u4e0b\u9762\u8fd9\u6837\u7684\u7b80\u5355\u88c5\u9970\u5668\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Example use\n@logged\ndef add(x, y):\n return x + y"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u8fd9\u4e2a\u8c03\u7528\u5e8f\u5217\u8ddf\u4e0b\u9762\u7b49\u4ef7\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def add(x, y):\n return x + y\n\nadd = logged(add)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u8fd9\u65f6\u5019\uff0c\u88ab\u88c5\u9970\u51fd\u6570\u4f1a\u88ab\u5f53\u505a\u7b2c\u4e00\u4e2a\u53c2\u6570\u76f4\u63a5\u4f20\u9012\u7ed9 logged \u88c5\u9970\u5668\u3002\n\u56e0\u6b64\uff0clogged() \u4e2d\u7684\u7b2c\u4e00\u4e2a\u53c2\u6570\u5c31\u662f\u88ab\u5305\u88c5\u51fd\u6570\u672c\u8eab\u3002\u6240\u6709\u5176\u4ed6\u53c2\u6570\u90fd\u5fc5\u987b\u6709\u9ed8\u8ba4\u503c\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u800c\u5bf9\u4e8e\u4e00\u4e2a\u4e0b\u9762\u8fd9\u6837\u6709\u53c2\u6570\u7684\u88c5\u9970\u5668\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"@logged(level=logging.CRITICAL, name='example')\ndef spam():\n print('Spam!')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u8c03\u7528\u5e8f\u5217\u8ddf\u4e0b\u9762\u7b49\u4ef7\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def spam():\n print('Spam!')\nspam = logged(level=logging.CRITICAL, name='example')(spam)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u521d\u59cb\u8c03\u7528 logged() \u51fd\u6570\u65f6\uff0c\u88ab\u5305\u88c5\u51fd\u6570\u5e76\u6ca1\u6709\u4f20\u9012\u8fdb\u6765\u3002\n\u56e0\u6b64\u5728\u88c5\u9970\u5668\u5185\uff0c\u5b83\u5fc5\u987b\u662f\u53ef\u9009\u7684\u3002\u8fd9\u4e2a\u53cd\u8fc7\u6765\u4f1a\u8feb\u4f7f\u5176\u4ed6\u53c2\u6570\u5fc5\u987b\u4f7f\u7528\u5173\u952e\u5b57\u6765\u6307\u5b9a\u3002\n\u5e76\u4e14\uff0c\u4f46\u8fd9\u4e9b\u53c2\u6570\u88ab\u4f20\u9012\u8fdb\u6765\u540e\uff0c\u88c5\u9970\u5668\u8981\u8fd4\u56de\u4e00\u4e2a\u63a5\u53d7\u4e00\u4e2a\u51fd\u6570\u53c2\u6570\u5e76\u5305\u88c5\u5b83\u7684\u51fd\u6570(\u53c2\u80039.5\u5c0f\u8282)\u3002\n\u4e3a\u4e86\u8fd9\u6837\u505a\uff0c\u6211\u4eec\u4f7f\u7528\u4e86\u4e00\u4e2a\u6280\u5de7\uff0c\u5c31\u662f\u5229\u7528 functools.partial \u3002\n\u5b83\u4f1a\u8fd4\u56de\u4e00\u4e2a\u672a\u5b8c\u5168\u521d\u59cb\u5316\u7684\u81ea\u8eab\uff0c\u9664\u4e86\u88ab\u5305\u88c5\u51fd\u6570\u5916\u5176\u4ed6\u53c2\u6570\u90fd\u5df2\u7ecf\u786e\u5b9a\u4e0b\u6765\u4e86\u3002\n\u53ef\u4ee5\u53c2\u80037.8\u5c0f\u8282\u83b7\u53d6\u66f4\u591a partial() \u65b9\u6cd5\u7684\u77e5\u8bc6\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 9.7 \u5229\u7528\u88c5\u9970\u5668\u5f3a\u5236\u51fd\u6570\u4e0a\u7684\u7c7b\u578b\u68c0\u67e5\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u95ee\u9898\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f5c\u4e3a\u67d0\u79cd\u7f16\u7a0b\u89c4\u7ea6\uff0c\u4f60\u60f3\u5728\u5bf9\u51fd\u6570\u53c2\u6570\u8fdb\u884c\u5f3a\u5236\u7c7b\u578b\u68c0\u67e5\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u89e3\u51b3\u65b9\u6848\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5728\u6f14\u793a\u5b9e\u9645\u4ee3\u7801\u524d\uff0c\u5148\u8bf4\u660e\u6211\u4eec\u7684\u76ee\u6807\uff1a\u80fd\u5bf9\u51fd\u6570\u53c2\u6570\u7c7b\u578b\u8fdb\u884c\u65ad\u8a00\uff0c\u7c7b\u4f3c\u4e0b\u9762\u8fd9\u6837\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"@typeassert(int, int)\ndef add(x, y):\n return x + y\nadd(2, 3)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"add(2, 'hello')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e0b\u9762\u662f\u4f7f\u7528\u88c5\u9970\u5668\u6280\u672f\u6765\u5b9e\u73b0 @typeassert \uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from inspect import signature\nfrom functools import wraps\n\ndef typeassert(*ty_args, **ty_kwargs):\n def decorate(func):\n # If in optimized mode, disable type checking\n if not __debug__:\n return func\n\n # Map function argument names to supplied types\n sig = signature(func)\n bound_types = sig.bind_partial(*ty_args, **ty_kwargs).arguments\n\n @wraps(func)\n def wrapper(*args, **kwargs):\n bound_values = sig.bind(*args, **kwargs)\n # Enforce type assertions across supplied arguments\n for name, value in bound_values.arguments.items():\n if name in bound_types:\n if not isinstance(value, bound_types[name]):\n raise TypeError(\n 'Argument {} must be {}'.format(name, bound_types[name])\n )\n return func(*args, **kwargs)\n return wrapper\n return decorate"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u53ef\u4ee5\u770b\u51fa\u8fd9\u4e2a\u88c5\u9970\u5668\u975e\u5e38\u7075\u6d3b\uff0c\u65e2\u53ef\u4ee5\u6307\u5b9a\u6240\u6709\u53c2\u6570\u7c7b\u578b\uff0c\u4e5f\u53ef\u4ee5\u53ea\u6307\u5b9a\u90e8\u5206\u3002\n\u5e76\u4e14\u53ef\u4ee5\u901a\u8fc7\u4f4d\u7f6e\u6216\u5173\u952e\u5b57\u6765\u6307\u5b9a\u53c2\u6570\u7c7b\u578b\u3002\u4e0b\u9762\u662f\u4f7f\u7528\u793a\u4f8b\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"@typeassert(int, z=int)\ndef spam(x, y, z=42):\n print(x, y, z)\nspam(1, 2, 3)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"spam(1, 'hello', 3)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"spam(1, 'hello', 'world')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u8ba8\u8bba\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u8fd9\u8282\u662f\u9ad8\u7ea7\u88c5\u9970\u5668\u793a\u4f8b\uff0c\u5f15\u5165\u4e86\u5f88\u591a\u91cd\u8981\u7684\u6982\u5ff5\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u9996\u5148\uff0c\u88c5\u9970\u5668\u53ea\u4f1a\u5728\u51fd\u6570\u5b9a\u4e49\u65f6\u88ab\u8c03\u7528\u4e00\u6b21\u3002\n\u6709\u65f6\u5019\u4f60\u53bb\u6389\u88c5\u9970\u5668\u7684\u529f\u80fd\uff0c\u90a3\u4e48\u4f60\u53ea\u9700\u8981\u7b80\u5355\u7684\u8fd4\u56de\u88ab\u88c5\u9970\u51fd\u6570\u5373\u53ef\u3002\n\u4e0b\u9762\u7684\u4ee3\u7801\u4e2d\uff0c\u5982\u679c\u5168\u5c40\u53d8\u91cf\u3000__debug__ \u88ab\u8bbe\u7f6e\u6210\u4e86False(\u5f53\u4f60\u4f7f\u7528-O\u6216-OO\u53c2\u6570\u7684\u4f18\u5316\u6a21\u5f0f\u6267\u884c\u7a0b\u5e8f\u65f6)\uff0c\n\u90a3\u4e48\u5c31\u76f4\u63a5\u8fd4\u56de\u672a\u4fee\u6539\u8fc7\u7684\u51fd\u6570\u672c\u8eab\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def decorate(func):\n # If in optimized mode, disable type checking\n if not __debug__:\n return func"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5176\u6b21\uff0c\u8fd9\u91cc\u8fd8\u5bf9\u88ab\u5305\u88c5\u51fd\u6570\u7684\u53c2\u6570\u7b7e\u540d\u8fdb\u884c\u4e86\u68c0\u67e5\uff0c\u6211\u4eec\u4f7f\u7528\u4e86 inspect.signature() \u51fd\u6570\u3002\n\u7b80\u5355\u6765\u8bb2\uff0c\u5b83\u8fd0\u884c\u4f60\u63d0\u53d6\u4e00\u4e2a\u53ef\u8c03\u7528\u5bf9\u8c61\u7684\u53c2\u6570\u7b7e\u540d\u4fe1\u606f\u3002\u4f8b\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from inspect import signature\ndef spam(x, y, z=42):\n pass\nsig = signature(spam)\nprint(sig)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"sig.parameters"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"sig.parameters['z'].name"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"sig.parameters['z'].default"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"sig.parameters['z'].kind"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u88c5\u9970\u5668\u7684\u5f00\u59cb\u90e8\u5206\uff0c\u6211\u4eec\u4f7f\u7528\u4e86 bind_partial() \u65b9\u6cd5\u6765\u6267\u884c\u4ece\u6307\u5b9a\u7c7b\u578b\u5230\u540d\u79f0\u7684\u90e8\u5206\u7ed1\u5b9a\u3002\n\u4e0b\u9762\u662f\u4f8b\u5b50\u6f14\u793a\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"bound_types = sig.bind_partial(int,z=int)\nbound_types"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"bound_types.arguments"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5728\u8fd9\u4e2a\u90e8\u5206\u7ed1\u5b9a\u4e2d\uff0c\u4f60\u53ef\u4ee5\u6ce8\u610f\u5230\u7f3a\u5931\u7684\u53c2\u6570\u88ab\u5ffd\u7565\u4e86(\u6bd4\u5982\u5e76\u6ca1\u6709\u5bf9y\u8fdb\u884c\u7ed1\u5b9a)\u3002\n\u4e0d\u8fc7\u6700\u91cd\u8981\u7684\u662f\u521b\u5efa\u4e86\u4e00\u4e2a\u6709\u5e8f\u5b57\u5178 bound_types.arguments \u3002\n\u8fd9\u4e2a\u5b57\u5178\u4f1a\u5c06\u53c2\u6570\u540d\u4ee5\u51fd\u6570\u7b7e\u540d\u4e2d\u76f8\u540c\u987a\u5e8f\u6620\u5c04\u5230\u6307\u5b9a\u7684\u7c7b\u578b\u503c\u4e0a\u9762\u53bb\u3002\n\u5728\u6211\u4eec\u7684\u88c5\u9970\u5668\u4f8b\u5b50\u4e2d\uff0c\u8fd9\u4e2a\u6620\u5c04\u5305\u542b\u4e86\u6211\u4eec\u8981\u5f3a\u5236\u6307\u5b9a\u7684\u7c7b\u578b\u65ad\u8a00\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5728\u88c5\u9970\u5668\u521b\u5efa\u7684\u5b9e\u9645\u5305\u88c5\u51fd\u6570\u4e2d\u4f7f\u7528\u5230\u4e86 sig.bind() \u65b9\u6cd5\u3002\nbind() \u8ddf bind_partial() \u7c7b\u4f3c\uff0c\u4f46\u662f\u5b83\u4e0d\u5141\u8bb8\u5ffd\u7565\u4efb\u4f55\u53c2\u6570\u3002\u56e0\u6b64\u6709\u4e86\u4e0b\u9762\u7684\u7ed3\u679c\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"bound_values = sig.bind(1, 2, 3)\nbound_values.arguments"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f7f\u7528\u8fd9\u4e2a\u6620\u5c04\u6211\u4eec\u53ef\u4ee5\u5f88\u8f7b\u677e\u7684\u5b9e\u73b0\u6211\u4eec\u7684\u5f3a\u5236\u7c7b\u578b\u68c0\u67e5\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"for name, value in bound_values.arguments.items():\n if name in bound_types.arguments:\n if not isinstance(value, bound_types.arguments[name]):\n raise TypeError()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e0d\u8fc7\u8fd9\u4e2a\u65b9\u6848\u8fd8\u6709\u70b9\u5c0f\u7455\u75b5\uff0c\u5b83\u5bf9\u4e8e\u6709\u9ed8\u8ba4\u503c\u7684\u53c2\u6570\u5e76\u4e0d\u9002\u7528\u3002\n\u6bd4\u5982\u4e0b\u9762\u7684\u4ee3\u7801\u53ef\u4ee5\u6b63\u5e38\u5de5\u4f5c\uff0c\u5c3d\u7ba1items\u7684\u7c7b\u578b\u662f\u9519\u8bef\u7684\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"@typeassert(int, list)\ndef bar(x, items=None):\n if items is None:\n items = []\n items.append(x)\n return items\nbar(2)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"bar(2,3)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"bar(4, [1, 2, 3])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u6700\u540e\u4e00\u70b9\u662f\u5173\u4e8e\u9002\u7528\u88c5\u9970\u5668\u53c2\u6570\u548c\u51fd\u6570\u6ce8\u89e3\u4e4b\u95f4\u7684\u4e89\u8bba\u3002\n\u4f8b\u5982\uff0c\u4e3a\u4ec0\u4e48\u4e0d\u50cf\u4e0b\u9762\u8fd9\u6837\u5199\u4e00\u4e2a\u88c5\u9970\u5668\u6765\u67e5\u627e\u51fd\u6570\u4e2d\u7684\u6ce8\u89e3\u5462\uff1f"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"@typeassert\ndef spam(x:int, y, z:int = 42):\n print(x,y,z)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e00\u4e2a\u53ef\u80fd\u7684\u539f\u56e0\u662f\u5982\u679c\u4f7f\u7528\u4e86\u51fd\u6570\u53c2\u6570\u6ce8\u89e3\uff0c\u90a3\u4e48\u5c31\u88ab\u9650\u5236\u4e86\u3002\n\u5982\u679c\u6ce8\u89e3\u88ab\u7528\u6765\u505a\u7c7b\u578b\u68c0\u67e5\u5c31\u4e0d\u80fd\u505a\u5176\u4ed6\u4e8b\u60c5\u4e86\u3002\u800c\u4e14 @typeassert \u4e0d\u80fd\u518d\u7528\u4e8e\u4f7f\u7528\u6ce8\u89e3\u505a\u5176\u4ed6\u4e8b\u60c5\u7684\u51fd\u6570\u4e86\u3002\n\u800c\u4f7f\u7528\u4e0a\u9762\u7684\u88c5\u9970\u5668\u53c2\u6570\u7075\u6d3b\u6027\u5927\u591a\u4e86\uff0c\u4e5f\u66f4\u52a0\u901a\u7528\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u53ef\u4ee5\u5728PEP 362\u4ee5\u53ca inspect \u6a21\u5757\u4e2d\u627e\u5230\u66f4\u591a\u5173\u4e8e\u51fd\u6570\u53c2\u6570\u5bf9\u8c61\u7684\u4fe1\u606f\u3002\u57289.16\u5c0f\u8282\u8fd8\u6709\u53e6\u5916\u4e00\u4e2a\u4f8b\u5b50\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 9.8 \u5c06\u88c5\u9970\u5668\u5b9a\u4e49\u4e3a\u7c7b\u7684\u4e00\u90e8\u5206\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u95ee\u9898\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f60\u60f3\u5728\u7c7b\u4e2d\u5b9a\u4e49\u88c5\u9970\u5668\uff0c\u5e76\u5c06\u5176\u4f5c\u7528\u5728\u5176\u4ed6\u51fd\u6570\u6216\u65b9\u6cd5\u4e0a\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u89e3\u51b3\u65b9\u6848\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5728\u7c7b\u91cc\u9762\u5b9a\u4e49\u88c5\u9970\u5668\u5f88\u7b80\u5355\uff0c\u4f46\u662f\u4f60\u9996\u5148\u8981\u786e\u8ba4\u5b83\u7684\u4f7f\u7528\u65b9\u5f0f\u3002\u6bd4\u5982\u5230\u5e95\u662f\u4f5c\u4e3a\u4e00\u4e2a\u5b9e\u4f8b\u65b9\u6cd5\u8fd8\u662f\u7c7b\u65b9\u6cd5\u3002\n\u4e0b\u9762\u6211\u4eec\u7528\u4f8b\u5b50\u6765\u9610\u8ff0\u5b83\u4eec\u7684\u4e0d\u540c\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from functools import wraps\n\nclass A:\n # Decorator as an instance method\n def decorator1(self, func):\n @wraps(func)\n def wrapper(*args, **kwargs):\n print('Decorator 1')\n return func(*args, **kwargs)\n return wrapper\n\n # Decorator as a class method\n @classmethod\n def decorator2(cls, func):\n @wraps(func)\n def wrapper(*args, **kwargs):\n print('Decorator 2')\n return func(*args, **kwargs)\n return wrapper"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e0b\u9762\u662f\u4e00\u4f7f\u7528\u4f8b\u5b50\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# As an instance method\na = A()\n@a.decorator1\ndef spam():\n pass\n# As a class method\n@A.decorator2\ndef grok():\n pass"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4ed4\u7ec6\u89c2\u5bdf\u53ef\u4ee5\u53d1\u73b0\u4e00\u4e2a\u662f\u5b9e\u4f8b\u8c03\u7528\uff0c\u4e00\u4e2a\u662f\u7c7b\u8c03\u7528\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u8ba8\u8bba\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5728\u7c7b\u4e2d\u5b9a\u4e49\u88c5\u9970\u5668\u521d\u770b\u4e0a\u53bb\u597d\u50cf\u5f88\u5947\u602a\uff0c\u4f46\u662f\u5728\u6807\u51c6\u5e93\u4e2d\u6709\u5f88\u591a\u8fd9\u6837\u7684\u4f8b\u5b50\u3002\n\u7279\u522b\u7684\uff0c@property \u88c5\u9970\u5668\u5b9e\u9645\u4e0a\u662f\u4e00\u4e2a\u7c7b\uff0c\u5b83\u91cc\u9762\u5b9a\u4e49\u4e86\u4e09\u4e2a\u65b9\u6cd5 getter(), setter(), deleter() ,\n\u6bcf\u4e00\u4e2a\u65b9\u6cd5\u90fd\u662f\u4e00\u4e2a\u88c5\u9970\u5668\u3002\u4f8b\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class Person:\n # Create a property instance\n first_name = property()\n\n # Apply decorator methods\n @first_name.getter\n def first_name(self):\n return self._first_name\n\n @first_name.setter\n def first_name(self, value):\n if not isinstance(value, str):\n raise TypeError('Expected a string')\n self._first_name = value"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5b83\u4e3a\u4ec0\u4e48\u8981\u8fd9\u4e48\u5b9a\u4e49\u7684\u4e3b\u8981\u539f\u56e0\u662f\u5404\u79cd\u4e0d\u540c\u7684\u88c5\u9970\u5668\u65b9\u6cd5\u4f1a\u5728\u5173\u8054\u7684 property \u5b9e\u4f8b\u4e0a\u64cd\u4f5c\u5b83\u7684\u72b6\u6001\u3002\n\u56e0\u6b64\uff0c\u4efb\u4f55\u65f6\u5019\u53ea\u8981\u4f60\u78b0\u5230\u9700\u8981\u5728\u88c5\u9970\u5668\u4e2d\u8bb0\u5f55\u6216\u7ed1\u5b9a\u4fe1\u606f\uff0c\u90a3\u4e48\u8fd9\u4e0d\u5931\u4e3a\u4e00\u79cd\u53ef\u884c\u65b9\u6cd5\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5728\u7c7b\u4e2d\u5b9a\u4e49\u88c5\u9970\u5668\u6709\u4e2a\u96be\u7406\u89e3\u7684\u5730\u65b9\u5c31\u662f\u5bf9\u4e8e\u989d\u5916\u53c2\u6570 self \u6216 cls \u7684\u6b63\u786e\u4f7f\u7528\u3002\n\u5c3d\u7ba1\u6700\u5916\u5c42\u7684\u88c5\u9970\u5668\u51fd\u6570\u6bd4\u5982 decorator1() \u6216 decorator2() \u9700\u8981\u63d0\u4f9b\u4e00\u4e2a self \u6216 cls \u53c2\u6570\uff0c\n\u4f46\u662f\u5728\u4e24\u4e2a\u88c5\u9970\u5668\u5185\u90e8\u88ab\u521b\u5efa\u7684 wrapper() \u51fd\u6570\u5e76\u4e0d\u9700\u8981\u5305\u542b\u8fd9\u4e2a self \u53c2\u6570\u3002\n\u4f60\u552f\u4e00\u9700\u8981\u8fd9\u4e2a\u53c2\u6570\u662f\u5728\u4f60\u786e\u5b9e\u8981\u8bbf\u95ee\u5305\u88c5\u5668\u4e2d\u8fd9\u4e2a\u5b9e\u4f8b\u7684\u67d0\u4e9b\u90e8\u5206\u7684\u65f6\u5019\u3002\u5176\u4ed6\u60c5\u51b5\u4e0b\u90fd\u4e0d\u7528\u53bb\u7ba1\u5b83\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5bf9\u4e8e\u7c7b\u91cc\u9762\u5b9a\u4e49\u7684\u5305\u88c5\u5668\u8fd8\u6709\u4e00\u70b9\u6bd4\u8f83\u96be\u7406\u89e3\uff0c\u5c31\u662f\u5728\u6d89\u53ca\u5230\u7ee7\u627f\u7684\u65f6\u5019\u3002\n\u4f8b\u5982\uff0c\u5047\u8bbe\u4f60\u60f3\u8ba9\u5728A\u4e2d\u5b9a\u4e49\u7684\u88c5\u9970\u5668\u4f5c\u7528\u5728\u5b50\u7c7bB\u4e2d\u3002\u4f60\u9700\u8981\u50cf\u4e0b\u9762\u8fd9\u6837\u5199\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class B(A):\n @A.decorator2\n def bar(self):\n pass"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e5f\u5c31\u662f\u8bf4\uff0c\u88c5\u9970\u5668\u8981\u88ab\u5b9a\u4e49\u6210\u7c7b\u65b9\u6cd5\u5e76\u4e14\u4f60\u5fc5\u987b\u663e\u5f0f\u7684\u4f7f\u7528\u7236\u7c7b\u540d\u53bb\u8c03\u7528\u5b83\u3002\n\u4f60\u4e0d\u80fd\u4f7f\u7528 @B.decorator2 \uff0c\u56e0\u4e3a\u5728\u65b9\u6cd5\u5b9a\u4e49\u65f6\uff0c\u8fd9\u4e2a\u7c7bB\u8fd8\u6ca1\u6709\u88ab\u521b\u5efa\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 9.9 \u5c06\u88c5\u9970\u5668\u5b9a\u4e49\u4e3a\u7c7b\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u95ee\u9898\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f60\u60f3\u4f7f\u7528\u4e00\u4e2a\u88c5\u9970\u5668\u53bb\u5305\u88c5\u51fd\u6570\uff0c\u4f46\u662f\u5e0c\u671b\u8fd4\u56de\u4e00\u4e2a\u53ef\u8c03\u7528\u7684\u5b9e\u4f8b\u3002\n\u4f60\u9700\u8981\u8ba9\u4f60\u7684\u88c5\u9970\u5668\u53ef\u4ee5\u540c\u65f6\u5de5\u4f5c\u5728\u7c7b\u5b9a\u4e49\u7684\u5185\u90e8\u548c\u5916\u90e8\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u89e3\u51b3\u65b9\u6848\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e3a\u4e86\u5c06\u88c5\u9970\u5668\u5b9a\u4e49\u6210\u4e00\u4e2a\u5b9e\u4f8b\uff0c\u4f60\u9700\u8981\u786e\u4fdd\u5b83\u5b9e\u73b0\u4e86 __call__() \u548c __get__() \u65b9\u6cd5\u3002\n\u4f8b\u5982\uff0c\u4e0b\u9762\u7684\u4ee3\u7801\u5b9a\u4e49\u4e86\u4e00\u4e2a\u7c7b\uff0c\u5b83\u5728\u5176\u4ed6\u51fd\u6570\u4e0a\u653e\u7f6e\u4e00\u4e2a\u7b80\u5355\u7684\u8bb0\u5f55\u5c42\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import types\nfrom functools import wraps\n\nclass Profiled:\n def __init__(self, func):\n wraps(func)(self)\n self.ncalls = 0\n\n def __call__(self, *args, **kwargs):\n self.ncalls += 1\n return self.__wrapped__(*args, **kwargs)\n\n def __get__(self, instance, cls):\n if instance is None:\n return self\n else:\n return types.MethodType(self, instance)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f60\u53ef\u4ee5\u5c06\u5b83\u5f53\u505a\u4e00\u4e2a\u666e\u901a\u7684\u88c5\u9970\u5668\u6765\u4f7f\u7528\uff0c\u5728\u7c7b\u91cc\u9762\u6216\u5916\u9762\u90fd\u53ef\u4ee5\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"@Profiled\ndef add(x, y):\n return x + y\n\nclass Spam:\n @Profiled\n def bar(self, x):\n print(self, x)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5728\u4ea4\u4e92\u73af\u5883\u4e2d\u7684\u4f7f\u7528\u793a\u4f8b\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"add(2, 3)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"add(4, 5)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"add.ncalls"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"s = Spam()\ns.bar(1)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"s.bar(2)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"s.bar(3)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"Spam.bar.ncalls"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u8ba8\u8bba\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5c06\u88c5\u9970\u5668\u5b9a\u4e49\u6210\u7c7b\u901a\u5e38\u662f\u5f88\u7b80\u5355\u7684\u3002\u4f46\u662f\u8fd9\u91cc\u8fd8\u662f\u6709\u4e00\u4e9b\u7ec6\u8282\u9700\u8981\u89e3\u91ca\u4e0b\uff0c\u7279\u522b\u662f\u5f53\u4f60\u60f3\u5c06\u5b83\u4f5c\u7528\u5728\u5b9e\u4f8b\u65b9\u6cd5\u4e0a\u7684\u65f6\u5019\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u9996\u5148\uff0c\u4f7f\u7528 functools.wraps() \u51fd\u6570\u7684\u4f5c\u7528\u8ddf\u4e4b\u524d\u8fd8\u662f\u4e00\u6837\uff0c\u5c06\u88ab\u5305\u88c5\u51fd\u6570\u7684\u5143\u4fe1\u606f\u590d\u5236\u5230\u53ef\u8c03\u7528\u5b9e\u4f8b\u4e2d\u53bb\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5176\u6b21\uff0c\u901a\u5e38\u5f88\u5bb9\u6613\u4f1a\u5ffd\u89c6\u4e0a\u9762\u7684 __get__() \u65b9\u6cd5\u3002\u5982\u679c\u4f60\u5ffd\u7565\u5b83\uff0c\u4fdd\u6301\u5176\u4ed6\u4ee3\u7801\u4e0d\u53d8\u518d\u6b21\u8fd0\u884c\uff0c\n\u4f60\u4f1a\u53d1\u73b0\u5f53\u4f60\u53bb\u8c03\u7528\u88ab\u88c5\u9970\u5b9e\u4f8b\u65b9\u6cd5\u65f6\u51fa\u73b0\u5f88\u5947\u602a\u7684\u95ee\u9898\u3002\u4f8b\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"s = Spam()\ns.bar(3)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u51fa\u9519\u539f\u56e0\u662f\u5f53\u65b9\u6cd5\u51fd\u6570\u5728\u4e00\u4e2a\u7c7b\u4e2d\u88ab\u67e5\u627e\u65f6\uff0c\u5b83\u4eec\u7684 __get__() \u65b9\u6cd5\u4f9d\u636e\u63cf\u8ff0\u5668\u534f\u8bae\u88ab\u8c03\u7528\uff0c\n\u57288.9\u5c0f\u8282\u5df2\u7ecf\u8bb2\u8ff0\u8fc7\u63cf\u8ff0\u5668\u534f\u8bae\u4e86\u3002\u5728\u8fd9\u91cc\uff0c__get__() \u7684\u76ee\u7684\u662f\u521b\u5efa\u4e00\u4e2a\u7ed1\u5b9a\u65b9\u6cd5\u5bf9\u8c61\n(\u6700\u7ec8\u4f1a\u7ed9\u8fd9\u4e2a\u65b9\u6cd5\u4f20\u9012self\u53c2\u6570)\u3002\u4e0b\u9762\u662f\u4e00\u4e2a\u4f8b\u5b50\u6765\u6f14\u793a\u5e95\u5c42\u539f\u7406\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"s = Spam()\ndef grok(self, x):\n pass\ngrok.__get__(s, Spam)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"__get__() \u65b9\u6cd5\u662f\u4e3a\u4e86\u786e\u4fdd\u7ed1\u5b9a\u65b9\u6cd5\u5bf9\u8c61\u80fd\u88ab\u6b63\u786e\u7684\u521b\u5efa\u3002\ntype.MethodType() \u624b\u52a8\u521b\u5efa\u4e00\u4e2a\u7ed1\u5b9a\u65b9\u6cd5\u6765\u4f7f\u7528\u3002\u53ea\u6709\u5f53\u5b9e\u4f8b\u88ab\u4f7f\u7528\u7684\u65f6\u5019\u7ed1\u5b9a\u65b9\u6cd5\u624d\u4f1a\u88ab\u521b\u5efa\u3002\n\u5982\u679c\u8fd9\u4e2a\u65b9\u6cd5\u662f\u5728\u7c7b\u4e0a\u9762\u6765\u8bbf\u95ee\uff0c\n\u90a3\u4e48 __get__() \u4e2d\u7684instance\u53c2\u6570\u4f1a\u88ab\u8bbe\u7f6e\u6210None\u5e76\u76f4\u63a5\u8fd4\u56de Profiled \u5b9e\u4f8b\u672c\u8eab\u3002\n\u8fd9\u6837\u7684\u8bdd\u6211\u4eec\u5c31\u53ef\u4ee5\u63d0\u53d6\u5b83\u7684 ncalls \u5c5e\u6027\u4e86\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5982\u679c\u4f60\u60f3\u907f\u514d\u4e00\u4e9b\u6df7\u4e71\uff0c\u4e5f\u53ef\u4ee5\u8003\u8651\u53e6\u5916\u4e00\u4e2a\u4f7f\u7528\u95ed\u5305\u548c nonlocal \u53d8\u91cf\u5b9e\u73b0\u7684\u88c5\u9970\u5668\uff0c\u8fd9\u4e2a\u57289.5\u5c0f\u8282\u6709\u8bb2\u5230\u3002\u4f8b\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import types\nfrom functools import wraps\n\ndef profiled(func):\n ncalls = 0\n @wraps(func)\n def wrapper(*args, **kwargs):\n nonlocal ncalls\n ncalls += 1\n return func(*args, **kwargs)\n wrapper.ncalls = lambda: ncalls\n return wrapper\n\n# Example\n@profiled\ndef add(x, y):\n return x + y"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u8fd9\u4e2a\u65b9\u5f0f\u8ddf\u4e4b\u524d\u7684\u6548\u679c\u51e0\u4e4e\u4e00\u6837\uff0c\u9664\u4e86\u5bf9\u4e8e ncalls \u7684\u8bbf\u95ee\u73b0\u5728\u662f\u901a\u8fc7\u4e00\u4e2a\u88ab\u7ed1\u5b9a\u4e3a\u5c5e\u6027\u7684\u51fd\u6570\u6765\u5b9e\u73b0\uff0c\u4f8b\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"add(2, 3)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"add(4, 5)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"add.ncalls()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 9.10 \u4e3a\u7c7b\u548c\u9759\u6001\u65b9\u6cd5\u63d0\u4f9b\u88c5\u9970\u5668\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u95ee\u9898\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f60\u60f3\u7ed9\u7c7b\u6216\u9759\u6001\u65b9\u6cd5\u63d0\u4f9b\u88c5\u9970\u5668\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u89e3\u51b3\u65b9\u6848\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u7ed9\u7c7b\u6216\u9759\u6001\u65b9\u6cd5\u63d0\u4f9b\u88c5\u9970\u5668\u662f\u5f88\u7b80\u5355\u7684\uff0c\u4e0d\u8fc7\u8981\u786e\u4fdd\u88c5\u9970\u5668\u5728 @classmethod \u6216 @staticmethod \u4e4b\u524d\u3002\u4f8b\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import time\nfrom functools import wraps\n\n# A simple decorator\ndef timethis(func):\n @wraps(func)\n def wrapper(*args, **kwargs):\n start = time.time()\n r = func(*args, **kwargs)\n end = time.time()\n print(end-start)\n return r\n return wrapper\n\n# Class illustrating application of the decorator to different kinds of methods\nclass Spam:\n @timethis\n def instance_method(self, n):\n print(self, n)\n while n > 0:\n n -= 1\n\n @classmethod\n @timethis\n def class_method(cls, n):\n print(cls, n)\n while n > 0:\n n -= 1\n\n @staticmethod\n @timethis\n def static_method(n):\n print(n)\n while n > 0:\n n -= 1"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u88c5\u9970\u540e\u7684\u7c7b\u548c\u9759\u6001\u65b9\u6cd5\u53ef\u6b63\u5e38\u5de5\u4f5c\uff0c\u53ea\u4e0d\u8fc7\u589e\u52a0\u4e86\u989d\u5916\u7684\u8ba1\u65f6\u529f\u80fd\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"s = Spam()\ns.instance_method(1000000)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"Spam.class_method(1000000)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"Spam.static_method(1000000)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u8ba8\u8bba\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5982\u679c\u4f60\u628a\u88c5\u9970\u5668\u7684\u987a\u5e8f\u5199\u9519\u4e86\u5c31\u4f1a\u51fa\u9519\u3002\u4f8b\u5982\uff0c\u5047\u8bbe\u4f60\u50cf\u4e0b\u9762\u8fd9\u6837\u5199\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class Spam:\n @timethis\n @staticmethod\n def static_method(n):\n print(n)\n while n > 0:\n n -= 1"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u90a3\u4e48\u4f60\u8c03\u7528\u8fd9\u4e2a\u9759\u6001\u65b9\u6cd5\u65f6\u5c31\u4f1a\u62a5\u9519\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"Spam.static_method(1000000)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u95ee\u9898\u5728\u4e8e @classmethod \u548c @staticmethod \u5b9e\u9645\u4e0a\u5e76\u4e0d\u4f1a\u521b\u5efa\u53ef\u76f4\u63a5\u8c03\u7528\u7684\u5bf9\u8c61\uff0c\n\u800c\u662f\u521b\u5efa\u7279\u6b8a\u7684\u63cf\u8ff0\u5668\u5bf9\u8c61(\u53c2\u80038.9\u5c0f\u8282)\u3002\u56e0\u6b64\u5f53\u4f60\u8bd5\u7740\u5728\u5176\u4ed6\u88c5\u9970\u5668\u4e2d\u5c06\u5b83\u4eec\u5f53\u505a\u51fd\u6570\u6765\u4f7f\u7528\u65f6\u5c31\u4f1a\u51fa\u9519\u3002\n\u786e\u4fdd\u8fd9\u79cd\u88c5\u9970\u5668\u51fa\u73b0\u5728\u88c5\u9970\u5668\u94fe\u4e2d\u7684\u7b2c\u4e00\u4e2a\u4f4d\u7f6e\u53ef\u4ee5\u4fee\u590d\u8fd9\u4e2a\u95ee\u9898\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5f53\u6211\u4eec\u5728\u62bd\u8c61\u57fa\u7c7b\u4e2d\u5b9a\u4e49\u7c7b\u65b9\u6cd5\u548c\u9759\u6001\u65b9\u6cd5(\u53c2\u80038.12\u5c0f\u8282)\u65f6\uff0c\u8fd9\u91cc\u8bb2\u5230\u7684\u77e5\u8bc6\u5c31\u5f88\u6709\u7528\u4e86\u3002\n\u4f8b\u5982\uff0c\u5982\u679c\u4f60\u60f3\u5b9a\u4e49\u4e00\u4e2a\u62bd\u8c61\u7c7b\u65b9\u6cd5\uff0c\u53ef\u4ee5\u4f7f\u7528\u7c7b\u4f3c\u4e0b\u9762\u7684\u4ee3\u7801\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from abc import ABCMeta, abstractmethod\nclass A(metaclass=ABCMeta):\n @classmethod\n @abstractmethod\n def method(cls):\n pass"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5728\u8fd9\u6bb5\u4ee3\u7801\u4e2d\uff0c@classmethod \u8ddf @abstractmethod \u4e24\u8005\u7684\u987a\u5e8f\u662f\u6709\u8bb2\u7a76\u7684\uff0c\u5982\u679c\u4f60\u8c03\u6362\u5b83\u4eec\u7684\u987a\u5e8f\u5c31\u4f1a\u51fa\u9519\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 9.11 \u88c5\u9970\u5668\u4e3a\u88ab\u5305\u88c5\u51fd\u6570\u589e\u52a0\u53c2\u6570\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u95ee\u9898\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f60\u60f3\u5728\u88c5\u9970\u5668\u4e2d\u7ed9\u88ab\u5305\u88c5\u51fd\u6570\u589e\u52a0\u989d\u5916\u7684\u53c2\u6570\uff0c\u4f46\u662f\u4e0d\u80fd\u5f71\u54cd\u8fd9\u4e2a\u51fd\u6570\u73b0\u6709\u7684\u8c03\u7528\u89c4\u5219\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u89e3\u51b3\u65b9\u6848\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u53ef\u4ee5\u4f7f\u7528\u5173\u952e\u5b57\u53c2\u6570\u6765\u7ed9\u88ab\u5305\u88c5\u51fd\u6570\u589e\u52a0\u989d\u5916\u53c2\u6570\u3002\u8003\u8651\u4e0b\u9762\u7684\u88c5\u9970\u5668\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from functools import wraps\n\ndef optional_debug(func):\n @wraps(func)\n def wrapper(*args, debug=False, **kwargs):\n if debug:\n print('Calling', func.__name__)\n return func(*args, **kwargs)\n\n return wrapper"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"@optional_debug\ndef spam(a,b,c):\n print(a,b,c)\nspam(1,2,3)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"spam(1,2,3, debug=True)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u8ba8\u8bba\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u901a\u8fc7\u88c5\u9970\u5668\u6765\u7ed9\u88ab\u5305\u88c5\u51fd\u6570\u589e\u52a0\u53c2\u6570\u7684\u505a\u6cd5\u5e76\u4e0d\u5e38\u89c1\u3002\n\u5c3d\u7ba1\u5982\u6b64\uff0c\u6709\u65f6\u5019\u5b83\u53ef\u4ee5\u907f\u514d\u4e00\u4e9b\u91cd\u590d\u4ee3\u7801\u3002\u4f8b\u5982\uff0c\u5982\u679c\u4f60\u6709\u4e0b\u9762\u8fd9\u6837\u7684\u4ee3\u7801\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def a(x, debug=False):\n if debug:\n print('Calling a')\n\ndef b(x, y, z, debug=False):\n if debug:\n print('Calling b')\n\ndef c(x, y, debug=False):\n if debug:\n print('Calling c')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u90a3\u4e48\u4f60\u53ef\u4ee5\u5c06\u5176\u91cd\u6784\u6210\u8fd9\u6837\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from functools import wraps\nimport inspect\n\ndef optional_debug(func):\n if 'debug' in inspect.getargspec(func).args:\n raise TypeError('debug argument already defined')\n\n @wraps(func)\n def wrapper(*args, debug=False, **kwargs):\n if debug:\n print('Calling', func.__name__)\n return func(*args, **kwargs)\n return wrapper\n\n@optional_debug\ndef a(x):\n pass\n\n@optional_debug\ndef b(x, y, z):\n pass\n\n@optional_debug\ndef c(x, y):\n pass"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u8fd9\u79cd\u5b9e\u73b0\u65b9\u6848\u4e4b\u6240\u4ee5\u884c\u5f97\u901a\uff0c\u5728\u4e8e\u5f3a\u5236\u5173\u952e\u5b57\u53c2\u6570\u5f88\u5bb9\u6613\u88ab\u6dfb\u52a0\u5230\u63a5\u53d7 *args \u548c **kwargs \u53c2\u6570\u7684\u51fd\u6570\u4e2d\u3002\n\u901a\u8fc7\u4f7f\u7528\u5f3a\u5236\u5173\u952e\u5b57\u53c2\u6570\uff0c\u5b83\u88ab\u4f5c\u4e3a\u4e00\u4e2a\u7279\u6b8a\u60c5\u51b5\u88ab\u6311\u9009\u51fa\u6765\uff0c\n\u5e76\u4e14\u63a5\u4e0b\u6765\u4ec5\u4ec5\u4f7f\u7528\u5269\u4f59\u7684\u4f4d\u7f6e\u548c\u5173\u952e\u5b57\u53c2\u6570\u53bb\u8c03\u7528\u8fd9\u4e2a\u51fd\u6570\u65f6\uff0c\u8fd9\u4e2a\u7279\u6b8a\u53c2\u6570\u4f1a\u88ab\u6392\u9664\u5728\u5916\u3002\n\u4e5f\u5c31\u662f\u8bf4\uff0c\u5b83\u5e76\u4e0d\u4f1a\u88ab\u7eb3\u5165\u5230 **kwargs \u4e2d\u53bb\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u8fd8\u6709\u4e00\u4e2a\u96be\u70b9\u5c31\u662f\u5982\u4f55\u53bb\u5904\u7406\u88ab\u6dfb\u52a0\u7684\u53c2\u6570\u4e0e\u88ab\u5305\u88c5\u51fd\u6570\u53c2\u6570\u76f4\u63a5\u7684\u540d\u5b57\u51b2\u7a81\u3002\n\u4f8b\u5982\uff0c\u5982\u679c\u88c5\u9970\u5668 @optional_debug \u4f5c\u7528\u5728\u4e00\u4e2a\u5df2\u7ecf\u62e5\u6709\u4e00\u4e2a debug \u53c2\u6570\u7684\u51fd\u6570\u4e0a\u65f6\u4f1a\u6709\u95ee\u9898\u3002\n\u8fd9\u91cc\u6211\u4eec\u589e\u52a0\u4e86\u4e00\u6b65\u540d\u5b57\u68c0\u67e5\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e0a\u9762\u7684\u65b9\u6848\u8fd8\u53ef\u4ee5\u66f4\u5b8c\u7f8e\u4e00\u70b9\uff0c\u56e0\u4e3a\u7cbe\u660e\u7684\u7a0b\u5e8f\u5458\u5e94\u8be5\u53d1\u73b0\u4e86\u88ab\u5305\u88c5\u51fd\u6570\u7684\u51fd\u6570\u7b7e\u540d\u5176\u5b9e\u662f\u9519\u8bef\u7684\u3002\u4f8b\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"@optional_debug\ndef add(x,y):\n return x+y\nimport inspect\nprint(inspect.signature(add))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u901a\u8fc7\u5982\u4e0b\u7684\u4fee\u6539\uff0c\u53ef\u4ee5\u89e3\u51b3\u8fd9\u4e2a\u95ee\u9898\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from functools import wraps\nimport inspect\n\ndef optional_debug(func):\n if 'debug' in inspect.getargspec(func).args:\n raise TypeError('debug argument already defined')\n\n @wraps(func)\n def wrapper(*args, debug=False, **kwargs):\n if debug:\n print('Calling', func.__name__)\n return func(*args, **kwargs)\n\n sig = inspect.signature(func)\n parms = list(sig.parameters.values())\n parms.append(inspect.Parameter('debug',\n inspect.Parameter.KEYWORD_ONLY,\n default=False))\n wrapper.__signature__ = sig.replace(parameters=parms)\n return wrapper"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u901a\u8fc7\u8fd9\u6837\u7684\u4fee\u6539\uff0c\u5305\u88c5\u540e\u7684\u51fd\u6570\u7b7e\u540d\u5c31\u80fd\u6b63\u786e\u7684\u663e\u793a debug \u53c2\u6570\u7684\u5b58\u5728\u4e86\u3002\u4f8b\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"@optional_debug\ndef add(x,y):\n return x+y\nprint(inspect.signature(add))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"add(2,3)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u53c2\u80039.16\u5c0f\u8282\u83b7\u53d6\u66f4\u591a\u5173\u4e8e\u51fd\u6570\u7b7e\u540d\u7684\u4fe1\u606f\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 9.12 \u4f7f\u7528\u88c5\u9970\u5668\u6269\u5145\u7c7b\u7684\u529f\u80fd\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u95ee\u9898\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f60\u60f3\u901a\u8fc7\u53cd\u7701\u6216\u8005\u91cd\u5199\u7c7b\u5b9a\u4e49\u7684\u67d0\u90e8\u5206\u6765\u4fee\u6539\u5b83\u7684\u884c\u4e3a\uff0c\u4f46\u662f\u4f60\u53c8\u4e0d\u5e0c\u671b\u4f7f\u7528\u7ee7\u627f\u6216\u5143\u7c7b\u7684\u65b9\u5f0f\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u89e3\u51b3\u65b9\u6848\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u8fd9\u79cd\u60c5\u51b5\u53ef\u80fd\u662f\u7c7b\u88c5\u9970\u5668\u6700\u597d\u7684\u4f7f\u7528\u573a\u666f\u4e86\u3002\u4f8b\u5982\uff0c\u4e0b\u9762\u662f\u4e00\u4e2a\u91cd\u5199\u4e86\u7279\u6b8a\u65b9\u6cd5 __getattribute__ \u7684\u7c7b\u88c5\u9970\u5668\uff0c\n\u53ef\u4ee5\u6253\u5370\u65e5\u5fd7\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def log_getattribute(cls):\n # Get the original implementation\n orig_getattribute = cls.__getattribute__\n\n # Make a new definition\n def new_getattribute(self, name):\n print('getting:', name)\n return orig_getattribute(self, name)\n\n # Attach to the class and return\n cls.__getattribute__ = new_getattribute\n return cls\n\n# Example use\n@log_getattribute\nclass A:\n def __init__(self,x):\n self.x = x\n def spam(self):\n pass"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e0b\u9762\u662f\u4f7f\u7528\u6548\u679c\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"a = A(42)\na.x"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"a.spam()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u8ba8\u8bba\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u7c7b\u88c5\u9970\u5668\u901a\u5e38\u53ef\u4ee5\u4f5c\u4e3a\u5176\u4ed6\u9ad8\u7ea7\u6280\u672f\u6bd4\u5982\u6df7\u5165\u6216\u5143\u7c7b\u7684\u4e00\u79cd\u975e\u5e38\u7b80\u6d01\u7684\u66ff\u4ee3\u65b9\u6848\u3002\n\u6bd4\u5982\uff0c\u4e0a\u9762\u793a\u4f8b\u4e2d\u7684\u53e6\u5916\u4e00\u79cd\u5b9e\u73b0\u4f7f\u7528\u5230\u7ee7\u627f\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class LoggedGetattribute:\n def __getattribute__(self, name):\n print('getting:', name)\n return super().__getattribute__(name)\n\n# Example:\nclass A(LoggedGetattribute):\n def __init__(self,x):\n self.x = x\n def spam(self):\n pass"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u8fd9\u79cd\u65b9\u6848\u4e5f\u884c\u5f97\u901a\uff0c\u4f46\u662f\u4e3a\u4e86\u53bb\u7406\u89e3\u5b83\uff0c\u4f60\u5c31\u5fc5\u987b\u77e5\u9053\u65b9\u6cd5\u8c03\u7528\u987a\u5e8f\u3001super() \u4ee5\u53ca\u5176\u5b838.7\u5c0f\u8282\u4ecb\u7ecd\u7684\u7ee7\u627f\u77e5\u8bc6\u3002\n\u67d0\u79cd\u7a0b\u5ea6\u4e0a\u6765\u8bb2\uff0c\u7c7b\u88c5\u9970\u5668\u65b9\u6848\u5c31\u663e\u5f97\u66f4\u52a0\u76f4\u89c2\uff0c\u5e76\u4e14\u5b83\u4e0d\u4f1a\u5f15\u5165\u65b0\u7684\u7ee7\u627f\u4f53\u7cfb\u3002\u5b83\u7684\u8fd0\u884c\u901f\u5ea6\u4e5f\u66f4\u5feb\u4e00\u4e9b\uff0c\n\u56e0\u4e3a\u4ed6\u5e76\u4e0d\u4f9d\u8d56 super() \u51fd\u6570\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5982\u679c\u4f60\u7cfb\u60f3\u5728\u4e00\u4e2a\u7c7b\u4e0a\u9762\u4f7f\u7528\u591a\u4e2a\u7c7b\u88c5\u9970\u5668\uff0c\u90a3\u4e48\u5c31\u9700\u8981\u6ce8\u610f\u4e0b\u987a\u5e8f\u95ee\u9898\u3002\n\u4f8b\u5982\uff0c\u4e00\u4e2a\u88c5\u9970\u5668A\u4f1a\u5c06\u5176\u88c5\u9970\u7684\u65b9\u6cd5\u5b8c\u6574\u66ff\u6362\u6210\u53e6\u4e00\u79cd\u5b9e\u73b0\uff0c\n\u800c\u53e6\u4e00\u4e2a\u88c5\u9970\u5668B\u53ea\u662f\u7b80\u5355\u7684\u5728\u5176\u88c5\u9970\u7684\u65b9\u6cd5\u4e2d\u6dfb\u52a0\u70b9\u989d\u5916\u903b\u8f91\u3002\n\u90a3\u4e48\u8fd9\u65f6\u5019\u88c5\u9970\u5668A\u5c31\u9700\u8981\u653e\u5728\u88c5\u9970\u5668B\u7684\u524d\u9762\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f60\u8fd8\u53ef\u4ee5\u56de\u987e\u4e00\u4e0b8.13\u5c0f\u8282\u53e6\u5916\u4e00\u4e2a\u5173\u4e8e\u7c7b\u88c5\u9970\u5668\u7684\u6709\u7528\u7684\u4f8b\u5b50\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 9.13 \u4f7f\u7528\u5143\u7c7b\u63a7\u5236\u5b9e\u4f8b\u7684\u521b\u5efa\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u95ee\u9898\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f60\u60f3\u901a\u8fc7\u6539\u53d8\u5b9e\u4f8b\u521b\u5efa\u65b9\u5f0f\u6765\u5b9e\u73b0\u5355\u4f8b\u3001\u7f13\u5b58\u6216\u5176\u4ed6\u7c7b\u4f3c\u7684\u7279\u6027\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u89e3\u51b3\u65b9\u6848\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Python\u7a0b\u5e8f\u5458\u90fd\u77e5\u9053\uff0c\u5982\u679c\u4f60\u5b9a\u4e49\u4e86\u4e00\u4e2a\u7c7b\uff0c\u5c31\u80fd\u50cf\u51fd\u6570\u4e00\u6837\u7684\u8c03\u7528\u5b83\u6765\u521b\u5efa\u5b9e\u4f8b\uff0c\u4f8b\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class Spam:\n def __init__(self, name):\n self.name = name\n\na = Spam('Guido')\nb = Spam('Diana')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5982\u679c\u4f60\u60f3\u81ea\u5b9a\u4e49\u8fd9\u4e2a\u6b65\u9aa4\uff0c\u4f60\u53ef\u4ee5\u5b9a\u4e49\u4e00\u4e2a\u5143\u7c7b\u5e76\u81ea\u5df1\u5b9e\u73b0 __call__() \u65b9\u6cd5\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e3a\u4e86\u6f14\u793a\uff0c\u5047\u8bbe\u4f60\u4e0d\u60f3\u4efb\u4f55\u4eba\u521b\u5efa\u8fd9\u4e2a\u7c7b\u7684\u5b9e\u4f8b\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class NoInstances(type):\n def __call__(self, *args, **kwargs):\n raise TypeError(\"Can't instantiate directly\")\n\n# Example\nclass Spam(metaclass=NoInstances):\n @staticmethod\n def grok(x):\n print('Spam.grok')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u8fd9\u6837\u7684\u8bdd\uff0c\u7528\u6237\u53ea\u80fd\u8c03\u7528\u8fd9\u4e2a\u7c7b\u7684\u9759\u6001\u65b9\u6cd5\uff0c\u800c\u4e0d\u80fd\u4f7f\u7528\u901a\u5e38\u7684\u65b9\u6cd5\u6765\u521b\u5efa\u5b83\u7684\u5b9e\u4f8b\u3002\u4f8b\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"Spam.grok(42)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"s = Spam()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u73b0\u5728\uff0c\u5047\u5982\u4f60\u60f3\u5b9e\u73b0\u5355\u4f8b\u6a21\u5f0f\uff08\u53ea\u80fd\u521b\u5efa\u552f\u4e00\u5b9e\u4f8b\u7684\u7c7b\uff09\uff0c\u5b9e\u73b0\u8d77\u6765\u4e5f\u5f88\u7b80\u5355\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class Singleton(type):\n def __init__(self, *args, **kwargs):\n self.__instance = None\n super().__init__(*args, **kwargs)\n\n def __call__(self, *args, **kwargs):\n if self.__instance is None:\n self.__instance = super().__call__(*args, **kwargs)\n return self.__instance\n else:\n return self.__instance\n\n# Example\nclass Spam(metaclass=Singleton):\n def __init__(self):\n print('Creating Spam')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u90a3\u4e48Spam\u7c7b\u5c31\u53ea\u80fd\u521b\u5efa\u552f\u4e00\u7684\u5b9e\u4f8b\u4e86\uff0c\u6f14\u793a\u5982\u4e0b\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"a = Spam()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"b = Spam()\na is b"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"c = Spam()\na is c"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u6700\u540e\uff0c\u5047\u8bbe\u4f60\u60f3\u521b\u5efa8.25\u5c0f\u8282\u4e2d\u90a3\u6837\u7684\u7f13\u5b58\u5b9e\u4f8b\u3002\u4e0b\u9762\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u5143\u7c7b\u6765\u5b9e\u73b0\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import weakref\n\nclass Cached(type):\n def __init__(self, *args, **kwargs):\n super().__init__(*args, **kwargs)\n self.__cache = weakref.WeakValueDictionary()\n\n def __call__(self, *args):\n if args in self.__cache:\n return self.__cache[args]\n else:\n obj = super().__call__(*args)\n self.__cache[args] = obj\n return obj\n\n# Example\nclass Spam(metaclass=Cached):\n def __init__(self, name):\n print('Creating Spam({!r})'.format(name))\n self.name = name"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u7136\u540e\u6211\u4e5f\u6765\u6d4b\u8bd5\u4e00\u4e0b\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"a = Spam('Guido')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"b = Spam('Diana')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"c = Spam('Guido') # Cached\na is b"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"a is c # Cached value returned"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u8ba8\u8bba\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5229\u7528\u5143\u7c7b\u5b9e\u73b0\u591a\u79cd\u5b9e\u4f8b\u521b\u5efa\u6a21\u5f0f\u901a\u5e38\u8981\u6bd4\u4e0d\u4f7f\u7528\u5143\u7c7b\u7684\u65b9\u5f0f\u4f18\u96c5\u5f97\u591a\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5047\u8bbe\u4f60\u4e0d\u4f7f\u7528\u5143\u7c7b\uff0c\u4f60\u53ef\u80fd\u9700\u8981\u5c06\u7c7b\u9690\u85cf\u5728\u67d0\u4e9b\u5de5\u5382\u51fd\u6570\u540e\u9762\u3002\n\u6bd4\u5982\u4e3a\u4e86\u5b9e\u73b0\u4e00\u4e2a\u5355\u4f8b\uff0c\u4f60\u4f60\u53ef\u80fd\u4f1a\u50cf\u4e0b\u9762\u8fd9\u6837\u5199\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class _Spam:\n def __init__(self):\n print('Creating Spam')\n\n_spam_instance = None\n\ndef Spam():\n global _spam_instance\n\n if _spam_instance is not None:\n return _spam_instance\n else:\n _spam_instance = _Spam()\n return _spam_instance"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5c3d\u7ba1\u4f7f\u7528\u5143\u7c7b\u53ef\u80fd\u4f1a\u6d89\u53ca\u5230\u6bd4\u8f83\u9ad8\u7ea7\u70b9\u7684\u6280\u672f\uff0c\u4f46\u662f\u5b83\u7684\u4ee3\u7801\u770b\u8d77\u6765\u4f1a\u66f4\u52a0\u7b80\u6d01\u8212\u670d\uff0c\u800c\u4e14\u4e5f\u66f4\u52a0\u76f4\u89c2\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u66f4\u591a\u5173\u4e8e\u521b\u5efa\u7f13\u5b58\u5b9e\u4f8b\u3001\u5f31\u5f15\u7528\u7b49\u5185\u5bb9\uff0c\u8bf7\u53c2\u80038.25\u5c0f\u8282\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 9.14 \u6355\u83b7\u7c7b\u7684\u5c5e\u6027\u5b9a\u4e49\u987a\u5e8f\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u95ee\u9898\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f60\u60f3\u81ea\u52a8\u8bb0\u5f55\u4e00\u4e2a\u7c7b\u4e2d\u5c5e\u6027\u548c\u65b9\u6cd5\u5b9a\u4e49\u7684\u987a\u5e8f\uff0c\n\u7136\u540e\u53ef\u4ee5\u5229\u7528\u5b83\u6765\u505a\u5f88\u591a\u64cd\u4f5c\uff08\u6bd4\u5982\u5e8f\u5217\u5316\u3001\u6620\u5c04\u5230\u6570\u636e\u5e93\u7b49\u7b49\uff09\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u89e3\u51b3\u65b9\u6848\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5229\u7528\u5143\u7c7b\u53ef\u4ee5\u5f88\u5bb9\u6613\u7684\u6355\u83b7\u7c7b\u7684\u5b9a\u4e49\u4fe1\u606f\u3002\u4e0b\u9762\u662f\u4e00\u4e2a\u4f8b\u5b50\uff0c\u4f7f\u7528\u4e86\u4e00\u4e2aOrderedDict\u6765\u8bb0\u5f55\u63cf\u8ff0\u5668\u7684\u5b9a\u4e49\u987a\u5e8f\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from collections import OrderedDict\n\n# A set of descriptors for various types\nclass Typed:\n _expected_type = type(None)\n def __init__(self, name=None):\n self._name = name\n\n def __set__(self, instance, value):\n if not isinstance(value, self._expected_type):\n raise TypeError('Expected ' + str(self._expected_type))\n instance.__dict__[self._name] = value\n\nclass Integer(Typed):\n _expected_type = int\n\nclass Float(Typed):\n _expected_type = float\n\nclass String(Typed):\n _expected_type = str\n\n# Metaclass that uses an OrderedDict for class body\nclass OrderedMeta(type):\n def __new__(cls, clsname, bases, clsdict):\n d = dict(clsdict)\n order = []\n for name, value in clsdict.items():\n if isinstance(value, Typed):\n value._name = name\n order.append(name)\n d['_order'] = order\n return type.__new__(cls, clsname, bases, d)\n\n @classmethod\n def __prepare__(cls, clsname, bases):\n return OrderedDict()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5728\u8fd9\u4e2a\u5143\u7c7b\u4e2d\uff0c\u6267\u884c\u7c7b\u4e3b\u4f53\u65f6\u63cf\u8ff0\u5668\u7684\u5b9a\u4e49\u987a\u5e8f\u4f1a\u88ab\u4e00\u4e2a OrderedDict``\u6355\u83b7\u5230\uff0c\n\u751f\u6210\u7684\u6709\u5e8f\u540d\u79f0\u4ece\u5b57\u5178\u4e2d\u63d0\u53d6\u51fa\u6765\u5e76\u653e\u5165\u7c7b\u5c5e\u6027 ``_order \u4e2d\u3002\u8fd9\u6837\u7684\u8bdd\u7c7b\u4e2d\u7684\u65b9\u6cd5\u53ef\u4ee5\u901a\u8fc7\u591a\u79cd\u65b9\u5f0f\u6765\u4f7f\u7528\u5b83\u3002\n\u4f8b\u5982\uff0c\u4e0b\u9762\u662f\u4e00\u4e2a\u7b80\u5355\u7684\u7c7b\uff0c\u4f7f\u7528\u8fd9\u4e2a\u6392\u5e8f\u5b57\u5178\u6765\u5b9e\u73b0\u5c06\u4e00\u4e2a\u7c7b\u5b9e\u4f8b\u7684\u6570\u636e\u5e8f\u5217\u5316\u4e3a\u4e00\u884cCSV\u6570\u636e\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class Structure(metaclass=OrderedMeta):\n def as_csv(self):\n return ','.join(str(getattr(self,name)) for name in self._order)\n\n# Example use\nclass Stock(Structure):\n name = String()\n shares = Integer()\n price = Float()\n\n def __init__(self, name, shares, price):\n self.name = name\n self.shares = shares\n self.price = price"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u6211\u4eec\u5728\u4ea4\u4e92\u5f0f\u73af\u5883\u4e2d\u6d4b\u8bd5\u4e00\u4e0b\u8fd9\u4e2aStock\u7c7b\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"s = Stock('GOOG',100,490.1)\ns.name"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"s.as_csv()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"t = Stock('AAPL','a lot', 610.23)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u8ba8\u8bba\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u672c\u8282\u4e00\u4e2a\u5173\u952e\u70b9\u5c31\u662fOrderedMeta\u5143\u7c7b\u4e2d\u5b9a\u4e49\u7684 `` __prepare__()`` \u65b9\u6cd5\u3002\n\u8fd9\u4e2a\u65b9\u6cd5\u4f1a\u5728\u5f00\u59cb\u5b9a\u4e49\u7c7b\u548c\u5b83\u7684\u7236\u7c7b\u7684\u65f6\u5019\u88ab\u6267\u884c\u3002\u5b83\u5fc5\u987b\u8fd4\u56de\u4e00\u4e2a\u6620\u5c04\u5bf9\u8c61\u4ee5\u4fbf\u5728\u7c7b\u5b9a\u4e49\u4f53\u4e2d\u88ab\u4f7f\u7528\u5230\u3002\n\u6211\u4eec\u8fd9\u91cc\u901a\u8fc7\u8fd4\u56de\u4e86\u4e00\u4e2aOrderedDict\u800c\u4e0d\u662f\u4e00\u4e2a\u666e\u901a\u7684\u5b57\u5178\uff0c\u53ef\u4ee5\u5f88\u5bb9\u6613\u7684\u6355\u83b7\u5b9a\u4e49\u7684\u987a\u5e8f\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5982\u679c\u4f60\u60f3\u6784\u9020\u81ea\u5df1\u7684\u7c7b\u5b57\u5178\u5bf9\u8c61\uff0c\u53ef\u4ee5\u5f88\u5bb9\u6613\u7684\u6269\u5c55\u8fd9\u4e2a\u529f\u80fd\u3002\u6bd4\u5982\uff0c\u4e0b\u9762\u7684\u8fd9\u4e2a\u4fee\u6539\u65b9\u6848\u53ef\u4ee5\u9632\u6b62\u91cd\u590d\u7684\u5b9a\u4e49\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from collections import OrderedDict\n\nclass NoDupOrderedDict(OrderedDict):\n def __init__(self, clsname):\n self.clsname = clsname\n super().__init__()\n def __setitem__(self, name, value):\n if name in self:\n raise TypeError('{} already defined in {}'.format(name, self.clsname))\n super().__setitem__(name, value)\n\nclass OrderedMeta(type):\n def __new__(cls, clsname, bases, clsdict):\n d = dict(clsdict)\n d['_order'] = [name for name in clsdict if name[0] != '_']\n return type.__new__(cls, clsname, bases, d)\n\n @classmethod\n def __prepare__(cls, clsname, bases):\n return NoDupOrderedDict(clsname)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e0b\u9762\u6211\u4eec\u6d4b\u8bd5\u91cd\u590d\u7684\u5b9a\u4e49\u4f1a\u51fa\u73b0\u4ec0\u4e48\u60c5\u51b5\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class A(metaclass=OrderedMeta):\ndef spam(self):\npass\ndef spam(self):\npass"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u6700\u540e\u8fd8\u6709\u4e00\u70b9\u5f88\u91cd\u8981\uff0c\u5c31\u662f\u5728 __new__() \u65b9\u6cd5\u4e2d\u5bf9\u4e8e\u5143\u7c7b\u4e2d\u88ab\u4fee\u6539\u5b57\u5178\u7684\u5904\u7406\u3002\n\u5c3d\u7ba1\u7c7b\u4f7f\u7528\u4e86\u53e6\u5916\u4e00\u4e2a\u5b57\u5178\u6765\u5b9a\u4e49\uff0c\u5728\u6784\u9020\u6700\u7ec8\u7684 class \u5bf9\u8c61\u7684\u65f6\u5019\uff0c\n\u6211\u4eec\u4ecd\u7136\u9700\u8981\u5c06\u8fd9\u4e2a\u5b57\u5178\u8f6c\u6362\u4e3a\u4e00\u4e2a\u6b63\u786e\u7684 dict \u5b9e\u4f8b\u3002\n\u901a\u8fc7\u8bed\u53e5 d = dict(clsdict) \u6765\u5b8c\u6210\u8fd9\u4e2a\u6548\u679c\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5bf9\u4e8e\u5f88\u591a\u5e94\u7528\u7a0b\u5e8f\u800c\u5df2\uff0c\u80fd\u591f\u6355\u83b7\u7c7b\u5b9a\u4e49\u7684\u987a\u5e8f\u662f\u4e00\u4e2a\u770b\u4f3c\u4e0d\u8d77\u773c\u5374\u53c8\u975e\u5e38\u91cd\u8981\u7684\u7279\u6027\u3002\n\u4f8b\u5982\uff0c\u5728\u5bf9\u8c61\u5173\u7cfb\u6620\u5c04\u4e2d\uff0c\u6211\u4eec\u901a\u5e38\u4f1a\u770b\u5230\u4e0b\u9762\u8fd9\u79cd\u65b9\u5f0f\u5b9a\u4e49\u7684\u7c7b\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class Stock(Model):\n name = String()\n shares = Integer()\n price = Float()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5728\u6846\u67b6\u5e95\u5c42\uff0c\u6211\u4eec\u5fc5\u987b\u6355\u83b7\u5b9a\u4e49\u7684\u987a\u5e8f\u6765\u5c06\u5bf9\u8c61\u6620\u5c04\u5230\u5143\u7ec4\u6216\u6570\u636e\u5e93\u8868\u4e2d\u7684\u884c\uff08\u5c31\u7c7b\u4f3c\u4e8e\u4e0a\u9762\u4f8b\u5b50\u4e2d\u7684 as_csv() \u7684\u529f\u80fd\uff09\u3002\n\u8fd9\u8282\u6f14\u793a\u7684\u6280\u672f\u975e\u5e38\u7b80\u5355\uff0c\u5e76\u4e14\u901a\u5e38\u4f1a\u6bd4\u5176\u4ed6\u7c7b\u4f3c\u65b9\u6cd5\uff08\u901a\u5e38\u90fd\u8981\u5728\u63cf\u8ff0\u5668\u7c7b\u4e2d\u7ef4\u62a4\u4e00\u4e2a\u9690\u85cf\u7684\u8ba1\u6570\u5668\uff09\u8981\u7b80\u5355\u7684\u591a\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 9.15 \u5b9a\u4e49\u6709\u53ef\u9009\u53c2\u6570\u7684\u5143\u7c7b\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u95ee\u9898\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f60\u60f3\u5b9a\u4e49\u4e00\u4e2a\u5143\u7c7b\uff0c\u5141\u8bb8\u7c7b\u5b9a\u4e49\u65f6\u63d0\u4f9b\u53ef\u9009\u53c2\u6570\uff0c\u8fd9\u6837\u53ef\u4ee5\u63a7\u5236\u6216\u914d\u7f6e\u7c7b\u578b\u7684\u521b\u5efa\u8fc7\u7a0b\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u89e3\u51b3\u65b9\u6848\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5728\u5b9a\u4e49\u7c7b\u7684\u65f6\u5019\uff0cPython\u5141\u8bb8\u6211\u4eec\u4f7f\u7528 ``metaclass``\u5173\u952e\u5b57\u53c2\u6570\u6765\u6307\u5b9a\u7279\u5b9a\u7684\u5143\u7c7b\u3002\n\u4f8b\u5982\u4f7f\u7528\u62bd\u8c61\u57fa\u7c7b\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from abc import ABCMeta, abstractmethod\nclass IStream(metaclass=ABCMeta):\n @abstractmethod\n def read(self, maxsize=None):\n pass\n\n @abstractmethod\n def write(self, data):\n pass"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u7136\u800c\uff0c\u5728\u81ea\u5b9a\u4e49\u5143\u7c7b\u4e2d\u6211\u4eec\u8fd8\u53ef\u4ee5\u63d0\u4f9b\u5176\u4ed6\u7684\u5173\u952e\u5b57\u53c2\u6570\uff0c\u5982\u4e0b\u6240\u793a\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class Spam(metaclass=MyMeta, debug=True, synchronize=True):\n pass"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e3a\u4e86\u4f7f\u5143\u7c7b\u652f\u6301\u8fd9\u4e9b\u5173\u952e\u5b57\u53c2\u6570\uff0c\u4f60\u5fc5\u987b\u786e\u4fdd\u5728 __prepare__() , __new__() \u548c __init__() \u65b9\u6cd5\u4e2d\n\u90fd\u4f7f\u7528\u5f3a\u5236\u5173\u952e\u5b57\u53c2\u6570\u3002\u5c31\u50cf\u4e0b\u9762\u8fd9\u6837\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class MyMeta(type):\n # Optional\n @classmethod\n def __prepare__(cls, name, bases, *, debug=False, synchronize=False):\n # Custom processing\n pass\n return super().__prepare__(name, bases)\n\n # Required\n def __new__(cls, name, bases, ns, *, debug=False, synchronize=False):\n # Custom processing\n pass\n return super().__new__(cls, name, bases, ns)\n\n # Required\n def __init__(self, name, bases, ns, *, debug=False, synchronize=False):\n # Custom processing\n pass\n super().__init__(name, bases, ns)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u8ba8\u8bba\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u7ed9\u4e00\u4e2a\u5143\u7c7b\u6dfb\u52a0\u53ef\u9009\u5173\u952e\u5b57\u53c2\u6570\u9700\u8981\u4f60\u5b8c\u5168\u5f04\u61c2\u7c7b\u521b\u5efa\u7684\u6240\u6709\u6b65\u9aa4\uff0c\n\u56e0\u4e3a\u8fd9\u4e9b\u53c2\u6570\u4f1a\u88ab\u4f20\u9012\u7ed9\u6bcf\u4e00\u4e2a\u76f8\u5173\u7684\u65b9\u6cd5\u3002\n__prepare__() \u65b9\u6cd5\u5728\u6240\u6709\u7c7b\u5b9a\u4e49\u5f00\u59cb\u6267\u884c\u524d\u9996\u5148\u88ab\u8c03\u7528\uff0c\u7528\u6765\u521b\u5efa\u7c7b\u547d\u540d\u7a7a\u95f4\u3002\n\u901a\u5e38\u6765\u8bb2\uff0c\u8fd9\u4e2a\u65b9\u6cd5\u53ea\u662f\u7b80\u5355\u7684\u8fd4\u56de\u4e00\u4e2a\u5b57\u5178\u6216\u5176\u4ed6\u6620\u5c04\u5bf9\u8c61\u3002\n__new__() \u65b9\u6cd5\u88ab\u7528\u6765\u5b9e\u4f8b\u5316\u6700\u7ec8\u7684\u7c7b\u5bf9\u8c61\u3002\u5b83\u5728\u7c7b\u7684\u4e3b\u4f53\u88ab\u6267\u884c\u5b8c\u540e\u5f00\u59cb\u6267\u884c\u3002\n__init__() \u65b9\u6cd5\u6700\u540e\u88ab\u8c03\u7528\uff0c\u7528\u6765\u6267\u884c\u5176\u4ed6\u7684\u4e00\u4e9b\u521d\u59cb\u5316\u5de5\u4f5c\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5f53\u6211\u4eec\u6784\u9020\u5143\u7c7b\u7684\u65f6\u5019\uff0c\u901a\u5e38\u53ea\u9700\u8981\u5b9a\u4e49\u4e00\u4e2a __new__() \u6216 __init__() \u65b9\u6cd5\uff0c\u4f46\u4e0d\u662f\u4e24\u4e2a\u90fd\u5b9a\u4e49\u3002\n\u4f46\u662f\uff0c\u5982\u679c\u9700\u8981\u63a5\u53d7\u5176\u4ed6\u7684\u5173\u952e\u5b57\u53c2\u6570\u7684\u8bdd\uff0c\u8fd9\u4e24\u4e2a\u65b9\u6cd5\u5c31\u8981\u540c\u65f6\u63d0\u4f9b\uff0c\u5e76\u4e14\u90fd\u8981\u63d0\u4f9b\u5bf9\u5e94\u7684\u53c2\u6570\u7b7e\u540d\u3002\n\u9ed8\u8ba4\u7684 __prepare__() \u65b9\u6cd5\u63a5\u53d7\u4efb\u610f\u7684\u5173\u952e\u5b57\u53c2\u6570\uff0c\u4f46\u662f\u4f1a\u5ffd\u7565\u5b83\u4eec\uff0c\n\u6240\u4ee5\u53ea\u6709\u5f53\u8fd9\u4e9b\u989d\u5916\u7684\u53c2\u6570\u53ef\u80fd\u4f1a\u5f71\u54cd\u5230\u7c7b\u547d\u540d\u7a7a\u95f4\u7684\u521b\u5efa\u65f6\u4f60\u624d\u9700\u8981\u53bb\u5b9a\u4e49 __prepare__() \u65b9\u6cd5\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u901a\u8fc7\u4f7f\u7528\u5f3a\u5236\u5173\u952e\u5b57\u53c2\u6570\uff0c\u5728\u7c7b\u7684\u521b\u5efa\u8fc7\u7a0b\u4e2d\u6211\u4eec\u5fc5\u987b\u901a\u8fc7\u5173\u952e\u5b57\u6765\u6307\u5b9a\u8fd9\u4e9b\u53c2\u6570\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f7f\u7528\u5173\u952e\u5b57\u53c2\u6570\u914d\u7f6e\u4e00\u4e2a\u5143\u7c7b\u8fd8\u53ef\u4ee5\u89c6\u4f5c\u5bf9\u7c7b\u53d8\u91cf\u7684\u4e00\u79cd\u66ff\u4ee3\u65b9\u5f0f\u3002\u4f8b\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class Spam(metaclass=MyMeta):\n debug = True\n synchronize = True\n pass"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5c06\u8fd9\u4e9b\u5c5e\u6027\u5b9a\u4e49\u4e3a\u53c2\u6570\u7684\u597d\u5904\u5728\u4e8e\u5b83\u4eec\u4e0d\u4f1a\u6c61\u67d3\u7c7b\u7684\u540d\u79f0\u7a7a\u95f4\uff0c\n\u8fd9\u4e9b\u5c5e\u6027\u4ec5\u4ec5\u53ea\u4ece\u5c5e\u4e8e\u7c7b\u7684\u521b\u5efa\u9636\u6bb5\uff0c\u800c\u4e0d\u662f\u7c7b\u4e2d\u7684\u8bed\u53e5\u6267\u884c\u9636\u6bb5\u3002\n\u53e6\u5916\uff0c\u5b83\u4eec\u5728 __prepare__() \u65b9\u6cd5\u4e2d\u662f\u53ef\u4ee5\u88ab\u8bbf\u95ee\u7684\uff0c\u56e0\u4e3a\u8fd9\u4e2a\u65b9\u6cd5\u4f1a\u5728\u6240\u6709\u7c7b\u4e3b\u4f53\u6267\u884c\u524d\u88ab\u6267\u884c\u3002\n\u4f46\u662f\u7c7b\u53d8\u91cf\u53ea\u80fd\u5728\u5143\u7c7b\u7684 __new__() \u548c __init__() \u65b9\u6cd5\u4e2d\u53ef\u89c1\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 9.16 *args\u548c**kwargs\u7684\u5f3a\u5236\u53c2\u6570\u7b7e\u540d\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u95ee\u9898\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f60\u6709\u4e00\u4e2a\u51fd\u6570\u6216\u65b9\u6cd5\uff0c\u5b83\u4f7f\u7528*args\u548c**kwargs\u4f5c\u4e3a\u53c2\u6570\uff0c\u8fd9\u6837\u4f7f\u5f97\u5b83\u6bd4\u8f83\u901a\u7528\uff0c\n\u4f46\u6709\u65f6\u5019\u4f60\u60f3\u68c0\u67e5\u4f20\u9012\u8fdb\u6765\u7684\u53c2\u6570\u662f\u4e0d\u662f\u67d0\u4e2a\u4f60\u60f3\u8981\u7684\u7c7b\u578b\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u89e3\u51b3\u65b9\u6848\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5bf9\u4efb\u4f55\u6d89\u53ca\u5230\u64cd\u4f5c\u51fd\u6570\u8c03\u7528\u7b7e\u540d\u7684\u95ee\u9898\uff0c\u4f60\u90fd\u5e94\u8be5\u4f7f\u7528 inspect \u6a21\u5757\u4e2d\u7684\u7b7e\u540d\u7279\u6027\u3002\n\u6211\u4eec\u6700\u4e3b\u8981\u5173\u6ce8\u4e24\u4e2a\u7c7b\uff1aSignature \u548c Parameter \u3002\u4e0b\u9762\u662f\u4e00\u4e2a\u521b\u5efa\u51fd\u6570\u524d\u9762\u7684\u4ea4\u4e92\u4f8b\u5b50\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from inspect import Signature, Parameter\n# Make a signature for a func(x, y=42, *, z=None)\nparms = [ Parameter('x', Parameter.POSITIONAL_OR_KEYWORD),\n Parameter('y', Parameter.POSITIONAL_OR_KEYWORD, default=42),\n Parameter('z', Parameter.KEYWORD_ONLY, default=None) ]\nsig = Signature(parms)\nprint(sig)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e00\u65e6\u4f60\u6709\u4e86\u4e00\u4e2a\u7b7e\u540d\u5bf9\u8c61\uff0c\u4f60\u5c31\u53ef\u4ee5\u4f7f\u7528\u5b83\u7684 bind() \u65b9\u6cd5\u5f88\u5bb9\u6613\u7684\u5c06\u5b83\u7ed1\u5b9a\u5230 *args \u548c **kwargs \u4e0a\u53bb\u3002\n\u4e0b\u9762\u662f\u4e00\u4e2a\u7b80\u5355\u7684\u6f14\u793a\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def func(*args, **kwargs):\n bound_values = sig.bind(*args, **kwargs)\n for name, value in bound_values.arguments.items():\n print(name,value)\n# Try various examples\nfunc(1, 2, z=3)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"func(1)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"func(1, z=3)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"func(y=2, x=1)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"func(1, 2, 3, 4)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"func(y=2)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"func(1, y=2, x=3)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u53ef\u4ee5\u770b\u51fa\u6765\uff0c\u901a\u8fc7\u5c06\u7b7e\u540d\u548c\u4f20\u9012\u7684\u53c2\u6570\u7ed1\u5b9a\u8d77\u6765\uff0c\u53ef\u4ee5\u5f3a\u5236\u51fd\u6570\u8c03\u7528\u9075\u5faa\u7279\u5b9a\u7684\u89c4\u5219\uff0c\u6bd4\u5982\u5fc5\u586b\u3001\u9ed8\u8ba4\u3001\u91cd\u590d\u7b49\u7b49\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e0b\u9762\u662f\u4e00\u4e2a\u5f3a\u5236\u51fd\u6570\u7b7e\u540d\u66f4\u5177\u4f53\u7684\u4f8b\u5b50\u3002\u5728\u4ee3\u7801\u4e2d\uff0c\u6211\u4eec\u5728\u57fa\u7c7b\u4e2d\u5148\u5b9a\u4e49\u4e86\u4e00\u4e2a\u975e\u5e38\u901a\u7528\u7684 __init__() \u65b9\u6cd5\uff0c\n\u7136\u540e\u6211\u4eec\u5f3a\u5236\u6240\u6709\u7684\u5b50\u7c7b\u5fc5\u987b\u63d0\u4f9b\u4e00\u4e2a\u7279\u5b9a\u7684\u53c2\u6570\u7b7e\u540d\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from inspect import Signature, Parameter\n\ndef make_sig(*names):\n parms = [Parameter(name, Parameter.POSITIONAL_OR_KEYWORD)\n for name in names]\n return Signature(parms)\n\nclass Structure:\n __signature__ = make_sig()\n def __init__(self, *args, **kwargs):\n bound_values = self.__signature__.bind(*args, **kwargs)\n for name, value in bound_values.arguments.items():\n setattr(self, name, value)\n\n# Example use\nclass Stock(Structure):\n __signature__ = make_sig('name', 'shares', 'price')\n\nclass Point(Structure):\n __signature__ = make_sig('x', 'y')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e0b\u9762\u662f\u4f7f\u7528\u8fd9\u4e2a Stock \u7c7b\u7684\u793a\u4f8b\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import inspect\nprint(inspect.signature(Stock))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"s1 = Stock('ACME', 100, 490.1)\ns2 = Stock('ACME', 100)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"s3 = Stock('ACME', 100, 490.1, shares=50)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u8ba8\u8bba\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5728\u6211\u4eec\u9700\u8981\u6784\u5efa\u901a\u7528\u51fd\u6570\u5e93\u3001\u7f16\u5199\u88c5\u9970\u5668\u6216\u5b9e\u73b0\u4ee3\u7406\u7684\u65f6\u5019\uff0c\u5bf9\u4e8e *args \u548c **kwargs \u7684\u4f7f\u7528\u662f\u5f88\u666e\u904d\u7684\u3002\n\u4f46\u662f\uff0c\u8fd9\u6837\u7684\u51fd\u6570\u6709\u4e00\u4e2a\u7f3a\u70b9\u5c31\u662f\u5f53\u4f60\u60f3\u8981\u5b9e\u73b0\u81ea\u5df1\u7684\u53c2\u6570\u68c0\u9a8c\u65f6\uff0c\u4ee3\u7801\u5c31\u4f1a\u7b28\u62d9\u6df7\u4e71\u3002\u57288.11\u5c0f\u8282\u91cc\u9762\u6709\u8fd9\u6837\u4e00\u4e2a\u4f8b\u5b50\u3002\n\u8fd9\u65f6\u5019\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u4e00\u4e2a\u7b7e\u540d\u5bf9\u8c61\u6765\u7b80\u5316\u5b83\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5728\u6700\u540e\u7684\u4e00\u4e2a\u65b9\u6848\u5b9e\u4f8b\u4e2d\uff0c\u6211\u4eec\u8fd8\u53ef\u4ee5\u901a\u8fc7\u4f7f\u7528\u81ea\u5b9a\u4e49\u5143\u7c7b\u6765\u521b\u5efa\u7b7e\u540d\u5bf9\u8c61\u3002\u4e0b\u9762\u6f14\u793a\u600e\u6837\u6765\u5b9e\u73b0\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from inspect import Signature, Parameter\n\ndef make_sig(*names):\n parms = [Parameter(name, Parameter.POSITIONAL_OR_KEYWORD)\n for name in names]\n return Signature(parms)\n\nclass StructureMeta(type):\n def __new__(cls, clsname, bases, clsdict):\n clsdict['__signature__'] = make_sig(*clsdict.get('_fields',[]))\n return super().__new__(cls, clsname, bases, clsdict)\n\nclass Structure(metaclass=StructureMeta):\n _fields = []\n def __init__(self, *args, **kwargs):\n bound_values = self.__signature__.bind(*args, **kwargs)\n for name, value in bound_values.arguments.items():\n setattr(self, name, value)\n\n# Example\nclass Stock(Structure):\n _fields = ['name', 'shares', 'price']\n\nclass Point(Structure):\n _fields = ['x', 'y']"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5f53\u6211\u4eec\u81ea\u5b9a\u4e49\u7b7e\u540d\u7684\u65f6\u5019\uff0c\u5c06\u7b7e\u540d\u5b58\u50a8\u5728\u7279\u5b9a\u7684\u5c5e\u6027 __signature__ \u4e2d\u901a\u5e38\u662f\u5f88\u6709\u7528\u7684\u3002\n\u8fd9\u6837\u7684\u8bdd\uff0c\u5728\u4f7f\u7528 inspect \u6a21\u5757\u6267\u884c\u5185\u7701\u7684\u4ee3\u7801\u5c31\u80fd\u53d1\u73b0\u7b7e\u540d\u5e76\u5c06\u5b83\u4f5c\u4e3a\u8c03\u7528\u7ea6\u5b9a\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import inspect\nprint(inspect.signature(Stock))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"print(inspect.signature(Point))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 9.17 \u5728\u7c7b\u4e0a\u5f3a\u5236\u4f7f\u7528\u7f16\u7a0b\u89c4\u7ea6\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u95ee\u9898\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f60\u7684\u7a0b\u5e8f\u5305\u542b\u4e00\u4e2a\u5f88\u5927\u7684\u7c7b\u7ee7\u627f\u4f53\u7cfb\uff0c\u4f60\u5e0c\u671b\u5f3a\u5236\u6267\u884c\u67d0\u4e9b\u7f16\u7a0b\u89c4\u7ea6\uff08\u6216\u8005\u4ee3\u7801\u8bca\u65ad\uff09\u6765\u5e2e\u52a9\u7a0b\u5e8f\u5458\u4fdd\u6301\u6e05\u9192\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u89e3\u51b3\u65b9\u6848\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5982\u679c\u4f60\u60f3\u76d1\u63a7\u7c7b\u7684\u5b9a\u4e49\uff0c\u901a\u5e38\u53ef\u4ee5\u901a\u8fc7\u5b9a\u4e49\u4e00\u4e2a\u5143\u7c7b\u3002\u4e00\u4e2a\u57fa\u672c\u5143\u7c7b\u901a\u5e38\u662f\u7ee7\u627f\u81ea type \u5e76\u91cd\u5b9a\u4e49\u5b83\u7684 __new__() \u65b9\u6cd5\n\u6216\u8005\u662f __init__() \u65b9\u6cd5\u3002\u6bd4\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class MyMeta(type):\n def __new__(self, clsname, bases, clsdict):\n # clsname is name of class being defined\n # bases is tuple of base classes\n # clsdict is class dictionary\n return super().__new__(cls, clsname, bases, clsdict)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u53e6\u4e00\u79cd\u662f\uff0c\u5b9a\u4e49 __init__() \u65b9\u6cd5\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class MyMeta(type):\n def __init__(self, clsname, bases, clsdict):\n super().__init__(clsname, bases, clsdict)\n # clsname is name of class being defined\n # bases is tuple of base classes\n # clsdict is class dictionary"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e3a\u4e86\u4f7f\u7528\u8fd9\u4e2a\u5143\u7c7b\uff0c\u4f60\u901a\u5e38\u8981\u5c06\u5b83\u653e\u5230\u5230\u4e00\u4e2a\u9876\u7ea7\u7236\u7c7b\u5b9a\u4e49\u4e2d\uff0c\u7136\u540e\u5176\u4ed6\u7684\u7c7b\u7ee7\u627f\u8fd9\u4e2a\u9876\u7ea7\u7236\u7c7b\u3002\u4f8b\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class Root(metaclass=MyMeta):\n pass\n\nclass A(Root):\n pass\n\nclass B(Root):\n pass"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5143\u7c7b\u7684\u4e00\u4e2a\u5173\u952e\u7279\u70b9\u662f\u5b83\u5141\u8bb8\u4f60\u5728\u5b9a\u4e49\u7684\u65f6\u5019\u68c0\u67e5\u7c7b\u7684\u5185\u5bb9\u3002\u5728\u91cd\u65b0\u5b9a\u4e49 __init__() \u65b9\u6cd5\u4e2d\uff0c\n\u4f60\u53ef\u4ee5\u5f88\u8f7b\u677e\u7684\u68c0\u67e5\u7c7b\u5b57\u5178\u3001\u7236\u7c7b\u7b49\u7b49\u3002\u5e76\u4e14\uff0c\u4e00\u65e6\u67d0\u4e2a\u5143\u7c7b\u88ab\u6307\u5b9a\u7ed9\u4e86\u67d0\u4e2a\u7c7b\uff0c\u90a3\u4e48\u5c31\u4f1a\u88ab\u7ee7\u627f\u5230\u6240\u6709\u5b50\u7c7b\u4e2d\u53bb\u3002\n\u56e0\u6b64\uff0c\u4e00\u4e2a\u6846\u67b6\u7684\u6784\u5efa\u8005\u5c31\u80fd\u5728\u5927\u578b\u7684\u7ee7\u627f\u4f53\u7cfb\u4e2d\u901a\u8fc7\u7ed9\u4e00\u4e2a\u9876\u7ea7\u7236\u7c7b\u6307\u5b9a\u4e00\u4e2a\u5143\u7c7b\u53bb\u6355\u83b7\u6240\u6709\u4e0b\u9762\u5b50\u7c7b\u7684\u5b9a\u4e49\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f5c\u4e3a\u4e00\u4e2a\u5177\u4f53\u7684\u5e94\u7528\u4f8b\u5b50\uff0c\u4e0b\u9762\u5b9a\u4e49\u4e86\u4e00\u4e2a\u5143\u7c7b\uff0c\u5b83\u4f1a\u62d2\u7edd\u4efb\u4f55\u6709\u6df7\u5408\u5927\u5c0f\u5199\u540d\u5b57\u4f5c\u4e3a\u65b9\u6cd5\u7684\u7c7b\u5b9a\u4e49\uff08\u53ef\u80fd\u662f\u60f3\u6c14\u6b7bJava\u7a0b\u5e8f\u5458^_^\uff09\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class NoMixedCaseMeta(type):\n def __new__(cls, clsname, bases, clsdict):\n for name in clsdict:\n if name.lower() != name:\n raise TypeError('Bad attribute name: ' + name)\n return super().__new__(cls, clsname, bases, clsdict)\n\nclass Root(metaclass=NoMixedCaseMeta):\n pass\n\nclass A(Root):\n def foo_bar(self): # Ok\n pass\n\nclass B(Root):\n def fooBar(self): # TypeError\n pass"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f5c\u4e3a\u66f4\u9ad8\u7ea7\u548c\u5b9e\u7528\u7684\u4f8b\u5b50\uff0c\u4e0b\u9762\u6709\u4e00\u4e2a\u5143\u7c7b\uff0c\u5b83\u7528\u6765\u68c0\u6d4b\u91cd\u8f7d\u65b9\u6cd5\uff0c\u786e\u4fdd\u5b83\u7684\u8c03\u7528\u53c2\u6570\u8ddf\u7236\u7c7b\u4e2d\u539f\u59cb\u65b9\u6cd5\u6709\u7740\u76f8\u540c\u7684\u53c2\u6570\u7b7e\u540d\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from inspect import signature\nimport logging\n\nclass MatchSignaturesMeta(type):\n\n def __init__(self, clsname, bases, clsdict):\n super().__init__(clsname, bases, clsdict)\n sup = super(self, self)\n for name, value in clsdict.items():\n if name.startswith('_') or not callable(value):\n continue\n # Get the previous definition (if any) and compare the signatures\n prev_dfn = getattr(sup,name,None)\n if prev_dfn:\n prev_sig = signature(prev_dfn)\n val_sig = signature(value)\n if prev_sig != val_sig:\n logging.warning('Signature mismatch in %s. %s != %s',\n value.__qualname__, prev_sig, val_sig)\n\n# Example\nclass Root(metaclass=MatchSignaturesMeta):\n pass\n\nclass A(Root):\n def foo(self, x, y):\n pass\n\n def spam(self, x, *, z):\n pass\n\n# Class with redefined methods, but slightly different signatures\nclass B(A):\n def foo(self, a, b):\n pass\n\n def spam(self,x,z):\n pass"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5982\u679c\u4f60\u8fd0\u884c\u8fd9\u6bb5\u4ee3\u7801\uff0c\u5c31\u4f1a\u5f97\u5230\u4e0b\u9762\u8fd9\u6837\u7684\u8f93\u51fa\u7ed3\u679c\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"WARNING:root:Signature mismatch in B.spam. (self, x, *, z) != (self, x, z)\nWARNING:root:Signature mismatch in B.foo. (self, x, y) != (self, a, b)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u8fd9\u79cd\u8b66\u544a\u4fe1\u606f\u5bf9\u4e8e\u6355\u83b7\u4e00\u4e9b\u5fae\u5999\u7684\u7a0b\u5e8fbug\u662f\u5f88\u6709\u7528\u7684\u3002\u4f8b\u5982\uff0c\u5982\u679c\u67d0\u4e2a\u4ee3\u7801\u4f9d\u8d56\u4e8e\u4f20\u9012\u7ed9\u65b9\u6cd5\u7684\u5173\u952e\u5b57\u53c2\u6570\uff0c\n\u90a3\u4e48\u5f53\u5b50\u7c7b\u6539\u53d8\u53c2\u6570\u540d\u5b57\u7684\u65f6\u5019\u5c31\u4f1a\u8c03\u7528\u51fa\u9519\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u8ba8\u8bba\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5728\u5927\u578b\u9762\u5411\u5bf9\u8c61\u7684\u7a0b\u5e8f\u4e2d\uff0c\u901a\u5e38\u5c06\u7c7b\u7684\u5b9a\u4e49\u653e\u5728\u5143\u7c7b\u4e2d\u63a7\u5236\u662f\u5f88\u6709\u7528\u7684\u3002\n\u5143\u7c7b\u53ef\u4ee5\u76d1\u63a7\u7c7b\u7684\u5b9a\u4e49\uff0c\u8b66\u544a\u7f16\u7a0b\u4eba\u5458\u67d0\u4e9b\u6ca1\u6709\u6ce8\u610f\u5230\u7684\u53ef\u80fd\u51fa\u73b0\u7684\u95ee\u9898\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u6709\u4eba\u53ef\u80fd\u4f1a\u8bf4\uff0c\u50cf\u8fd9\u6837\u7684\u9519\u8bef\u53ef\u4ee5\u901a\u8fc7\u7a0b\u5e8f\u5206\u6790\u5de5\u5177\u6216IDE\u53bb\u505a\u4f1a\u66f4\u597d\u4e9b\u3002\u8bda\u7136\uff0c\u8fd9\u4e9b\u5de5\u5177\u662f\u5f88\u6709\u7528\u3002\n\u4f46\u662f\uff0c\u5982\u679c\u4f60\u5728\u6784\u5efa\u4e00\u4e2a\u6846\u67b6\u6216\u51fd\u6570\u5e93\u4f9b\u5176\u4ed6\u4eba\u4f7f\u7528\uff0c\u90a3\u4e48\u4f60\u6ca1\u529e\u6cd5\u53bb\u63a7\u5236\u4f7f\u7528\u8005\u8981\u4f7f\u7528\u4ec0\u4e48\u5de5\u5177\u3002\n\u56e0\u6b64\uff0c\u5bf9\u4e8e\u8fd9\u79cd\u7c7b\u578b\u7684\u7a0b\u5e8f\uff0c\u5982\u679c\u53ef\u4ee5\u5728\u5143\u7c7b\u4e2d\u505a\u68c0\u6d4b\u6216\u8bb8\u53ef\u4ee5\u5e26\u6765\u66f4\u597d\u7684\u7528\u6237\u4f53\u9a8c\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5728\u5143\u7c7b\u4e2d\u9009\u62e9\u91cd\u65b0\u5b9a\u4e49 __new__() \u65b9\u6cd5\u8fd8\u662f __init__() \u65b9\u6cd5\u53d6\u51b3\u4e8e\u4f60\u60f3\u600e\u6837\u4f7f\u7528\u7ed3\u679c\u7c7b\u3002\n__new__() \u65b9\u6cd5\u5728\u7c7b\u521b\u5efa\u4e4b\u524d\u88ab\u8c03\u7528\uff0c\u901a\u5e38\u7528\u4e8e\u901a\u8fc7\u67d0\u79cd\u65b9\u5f0f\uff08\u6bd4\u5982\u901a\u8fc7\u6539\u53d8\u7c7b\u5b57\u5178\u7684\u5185\u5bb9\uff09\u4fee\u6539\u7c7b\u7684\u5b9a\u4e49\u3002\n\u800c __init__() \u65b9\u6cd5\u662f\u5728\u7c7b\u88ab\u521b\u5efa\u4e4b\u540e\u88ab\u8c03\u7528\uff0c\u5f53\u4f60\u9700\u8981\u5b8c\u6574\u6784\u5efa\u7c7b\u5bf9\u8c61\u7684\u65f6\u5019\u4f1a\u5f88\u6709\u7528\u3002\n\u5728\u6700\u540e\u4e00\u4e2a\u4f8b\u5b50\u4e2d\uff0c\u8fd9\u662f\u5fc5\u8981\u7684\uff0c\u56e0\u4e3a\u5b83\u4f7f\u7528\u4e86 super() \u51fd\u6570\u6765\u641c\u7d22\u4e4b\u524d\u7684\u5b9a\u4e49\u3002\n\u5b83\u53ea\u80fd\u5728\u7c7b\u7684\u5b9e\u4f8b\u88ab\u521b\u5efa\u4e4b\u540e\uff0c\u5e76\u4e14\u76f8\u5e94\u7684\u65b9\u6cd5\u89e3\u6790\u987a\u5e8f\u4e5f\u5df2\u7ecf\u88ab\u8bbe\u7f6e\u597d\u4e86\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u6700\u540e\u4e00\u4e2a\u4f8b\u5b50\u8fd8\u6f14\u793a\u4e86Python\u7684\u51fd\u6570\u7b7e\u540d\u5bf9\u8c61\u7684\u4f7f\u7528\u3002\n\u5b9e\u9645\u4e0a\uff0c\u5143\u7c7b\u5c06\u6bcf\u4e2a\u53ef\u8c03\u7528\u5b9a\u4e49\u653e\u5728\u4e00\u4e2a\u7c7b\u4e2d\uff0c\u641c\u7d22\u524d\u4e00\u4e2a\u5b9a\u4e49\uff08\u5982\u679c\u6709\u7684\u8bdd\uff09\uff0c\n\u7136\u540e\u901a\u8fc7\u4f7f\u7528 inspect.signature() \u6765\u7b80\u5355\u7684\u6bd4\u8f83\u5b83\u4eec\u7684\u8c03\u7528\u7b7e\u540d\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u6700\u540e\u4e00\u70b9\uff0c\u4ee3\u7801\u4e2d\u6709\u4e00\u884c\u4f7f\u7528\u4e86 super(self, self) \u5e76\u4e0d\u662f\u6392\u7248\u9519\u8bef\u3002\n\u5f53\u4f7f\u7528\u5143\u7c7b\u7684\u65f6\u5019\uff0c\u6211\u4eec\u8981\u65f6\u523b\u8bb0\u4f4f\u4e00\u70b9\u5c31\u662f self \u5b9e\u9645\u4e0a\u662f\u4e00\u4e2a\u7c7b\u5bf9\u8c61\u3002\n\u56e0\u6b64\uff0c\u8fd9\u6761\u8bed\u53e5\u5176\u5b9e\u5c31\u662f\u7528\u6765\u5bfb\u627e\u4f4d\u4e8e\u7ee7\u627f\u4f53\u7cfb\u4e2d\u6784\u5efa self \u7236\u7c7b\u7684\u5b9a\u4e49\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 9.18 \u4ee5\u7f16\u7a0b\u65b9\u5f0f\u5b9a\u4e49\u7c7b\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u95ee\u9898\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f60\u5728\u5199\u4e00\u6bb5\u4ee3\u7801\uff0c\u6700\u7ec8\u9700\u8981\u521b\u5efa\u4e00\u4e2a\u65b0\u7684\u7c7b\u5bf9\u8c61\u3002\u4f60\u8003\u8651\u5c06\u7c7b\u7684\u5b9a\u4e49\u6e90\u4ee3\u7801\u4ee5\u5b57\u7b26\u4e32\u7684\u5f62\u5f0f\u53d1\u5e03\u51fa\u53bb\u3002\n\u5e76\u4e14\u4f7f\u7528\u51fd\u6570\u6bd4\u5982 exec() \u6765\u6267\u884c\u5b83\uff0c\u4f46\u662f\u4f60\u60f3\u5bfb\u627e\u4e00\u4e2a\u66f4\u52a0\u4f18\u96c5\u7684\u89e3\u51b3\u65b9\u6848\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u89e3\u51b3\u65b9\u6848\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f60\u53ef\u4ee5\u4f7f\u7528\u51fd\u6570 types.new_class() \u6765\u521d\u59cb\u5316\u65b0\u7684\u7c7b\u5bf9\u8c61\u3002\n\u4f60\u9700\u8981\u505a\u7684\u53ea\u662f\u63d0\u4f9b\u7c7b\u7684\u540d\u5b57\u3001\u7236\u7c7b\u5143\u7ec4\u3001\u5173\u952e\u5b57\u53c2\u6570\uff0c\u4ee5\u53ca\u4e00\u4e2a\u7528\u6210\u5458\u53d8\u91cf\u586b\u5145\u7c7b\u5b57\u5178\u7684\u56de\u8c03\u51fd\u6570\u3002\u4f8b\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# stock.py\n# Example of making a class manually from parts\n\n# Methods\ndef __init__(self, name, shares, price):\n self.name = name\n self.shares = shares\n self.price = price\ndef cost(self):\n return self.shares * self.price\n\ncls_dict = {\n '__init__' : __init__,\n 'cost' : cost,\n}\n\n# Make a class\nimport types\n\nStock = types.new_class('Stock', (), {}, lambda ns: ns.update(cls_dict))\nStock.__module__ = __name__"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u8fd9\u79cd\u65b9\u5f0f\u4f1a\u6784\u5efa\u4e00\u4e2a\u666e\u901a\u7684\u7c7b\u5bf9\u8c61\uff0c\u5e76\u4e14\u6309\u7167\u4f60\u7684\u671f\u671b\u5de5\u4f5c\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"s = Stock('ACME', 50, 91.1)\ns"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"s.cost()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u8fd9\u79cd\u65b9\u6cd5\u4e2d\uff0c\u4e00\u4e2a\u6bd4\u8f83\u96be\u7406\u89e3\u7684\u5730\u65b9\u662f\u5728\u8c03\u7528\u5b8c types.new_class() \u5bf9 Stock.__module__ \u7684\u8d4b\u503c\u3002\n\u6bcf\u6b21\u5f53\u4e00\u4e2a\u7c7b\u88ab\u5b9a\u4e49\u540e\uff0c\u5b83\u7684 __module__ \u5c5e\u6027\u5305\u542b\u5b9a\u4e49\u5b83\u7684\u6a21\u5757\u540d\u3002\n\u8fd9\u4e2a\u540d\u5b57\u7528\u4e8e\u751f\u6210 __repr__() \u65b9\u6cd5\u7684\u8f93\u51fa\u3002\u5b83\u540c\u6837\u4e5f\u88ab\u7528\u4e8e\u5f88\u591a\u5e93\uff0c\u6bd4\u5982 pickle \u3002\n\u56e0\u6b64\uff0c\u4e3a\u4e86\u8ba9\u4f60\u521b\u5efa\u7684\u7c7b\u662f\u201c\u6b63\u786e\u201d\u7684\uff0c\u4f60\u9700\u8981\u786e\u4fdd\u8fd9\u4e2a\u5c5e\u6027\u4e5f\u8bbe\u7f6e\u6b63\u786e\u4e86\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5982\u679c\u4f60\u60f3\u521b\u5efa\u7684\u7c7b\u9700\u8981\u4e00\u4e2a\u4e0d\u540c\u7684\u5143\u7c7b\uff0c\u53ef\u4ee5\u901a\u8fc7 types.new_class() \u7b2c\u4e09\u4e2a\u53c2\u6570\u4f20\u9012\u7ed9\u5b83\u3002\u4f8b\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import abc\nStock = types.new_class('Stock', (), {'metaclass': abc.ABCMeta},\n lambda ns: ns.update(cls_dict))\nStock.__module__ = __name__\nStock"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"type(Stock)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u7b2c\u4e09\u4e2a\u53c2\u6570\u8fd8\u53ef\u4ee5\u5305\u542b\u5176\u4ed6\u7684\u5173\u952e\u5b57\u53c2\u6570\u3002\u6bd4\u5982\uff0c\u4e00\u4e2a\u7c7b\u7684\u5b9a\u4e49\u5982\u4e0b\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class Spam(Base, debug=True, typecheck=False):\n pass"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u90a3\u4e48\u53ef\u4ee5\u5c06\u5176\u7ffb\u8bd1\u6210\u5982\u4e0b\u7684 new_class() \u8c03\u7528\u5f62\u5f0f\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"Spam = types.new_class('Spam', (Base,),\n {'debug': True, 'typecheck': False},\n lambda ns: ns.update(cls_dict))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"new_class() \u7b2c\u56db\u4e2a\u53c2\u6570\u6700\u795e\u79d8\uff0c\u5b83\u662f\u4e00\u4e2a\u7528\u6765\u63a5\u53d7\u7c7b\u547d\u540d\u7a7a\u95f4\u7684\u6620\u5c04\u5bf9\u8c61\u7684\u51fd\u6570\u3002\n\u901a\u5e38\u8fd9\u662f\u4e00\u4e2a\u666e\u901a\u7684\u5b57\u5178\uff0c\u4f46\u662f\u5b83\u5b9e\u9645\u4e0a\u662f __prepare__() \u65b9\u6cd5\u8fd4\u56de\u7684\u4efb\u610f\u5bf9\u8c61\uff0c\u8fd9\u4e2a\u57289.14\u5c0f\u8282\u5df2\u7ecf\u4ecb\u7ecd\u8fc7\u4e86\u3002\n\u8fd9\u4e2a\u51fd\u6570\u9700\u8981\u4f7f\u7528\u4e0a\u9762\u6f14\u793a\u7684 update() \u65b9\u6cd5\u7ed9\u547d\u540d\u7a7a\u95f4\u589e\u52a0\u5185\u5bb9\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u8ba8\u8bba\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5f88\u591a\u65f6\u5019\u5982\u679c\u80fd\u6784\u9020\u65b0\u7684\u7c7b\u5bf9\u8c61\u662f\u5f88\u6709\u7528\u7684\u3002\n\u6709\u4e2a\u5f88\u719f\u6089\u7684\u4f8b\u5b50\u662f\u8c03\u7528 collections.namedtuple() \u51fd\u6570\uff0c\u4f8b\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"Stock = collections.namedtuple('Stock', ['name', 'shares', 'price'])\nStock"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"namedtuple() \u4f7f\u7528 exec() \u800c\u4e0d\u662f\u4e0a\u9762\u4ecb\u7ecd\u7684\u6280\u672f\u3002\u4f46\u662f\uff0c\u4e0b\u9762\u901a\u8fc7\u4e00\u4e2a\u7b80\u5355\u7684\u53d8\u5316\uff0c\n\u6211\u4eec\u76f4\u63a5\u521b\u5efa\u4e00\u4e2a\u7c7b\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import operator\nimport types\nimport sys\n\ndef named_tuple(classname, fieldnames):\n # Populate a dictionary of field property accessors\n cls_dict = { name: property(operator.itemgetter(n))\n for n, name in enumerate(fieldnames) }\n\n # Make a __new__ function and add to the class dict\n def __new__(cls, *args):\n if len(args) != len(fieldnames):\n raise TypeError('Expected {} arguments'.format(len(fieldnames)))\n return tuple.__new__(cls, args)\n\n cls_dict['__new__'] = __new__\n\n # Make the class\n cls = types.new_class(classname, (tuple,), {},\n lambda ns: ns.update(cls_dict))\n\n # Set the module to that of the caller\n cls.__module__ = sys._getframe(1).f_globals['__name__']\n return cls"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u8fd9\u6bb5\u4ee3\u7801\u7684\u6700\u540e\u90e8\u5206\u4f7f\u7528\u4e86\u4e00\u4e2a\u6240\u8c13\u7684\u201d\u6846\u67b6\u9b54\u6cd5\u201d\uff0c\u901a\u8fc7\u8c03\u7528 sys._getframe() \u6765\u83b7\u53d6\u8c03\u7528\u8005\u7684\u6a21\u5757\u540d\u3002\n\u53e6\u5916\u4e00\u4e2a\u6846\u67b6\u9b54\u6cd5\u4f8b\u5b50\u57282.15\u5c0f\u8282\u4e2d\u6709\u4ecb\u7ecd\u8fc7\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e0b\u9762\u7684\u4f8b\u5b50\u6f14\u793a\u4e86\u524d\u9762\u7684\u4ee3\u7801\u662f\u5982\u4f55\u5de5\u4f5c\u7684\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"Point = named_tuple('Point', ['x', 'y'])\nPoint"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"p = Point(4, 5)\nlen(p)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"p.x"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"p.y"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"p.x = 2"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"print('%s %s' % p)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u8fd9\u9879\u6280\u672f\u4e00\u4e2a\u5f88\u91cd\u8981\u7684\u65b9\u9762\u662f\u5b83\u5bf9\u4e8e\u5143\u7c7b\u7684\u6b63\u786e\u4f7f\u7528\u3002\n\u4f60\u53ef\u80fd\u50cf\u901a\u8fc7\u76f4\u63a5\u5b9e\u4f8b\u5316\u4e00\u4e2a\u5143\u7c7b\u6765\u76f4\u63a5\u521b\u5efa\u4e00\u4e2a\u7c7b\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"Stock = type('Stock', (), cls_dict)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u8fd9\u79cd\u65b9\u6cd5\u7684\u95ee\u9898\u5728\u4e8e\u5b83\u5ffd\u7565\u4e86\u4e00\u4e9b\u5173\u952e\u6b65\u9aa4\uff0c\u6bd4\u5982\u5bf9\u4e8e\u5143\u7c7b\u4e2d __prepare__() \u65b9\u6cd5\u7684\u8c03\u7528\u3002\n\u901a\u8fc7\u4f7f\u7528 types.new_class() \uff0c\u4f60\u53ef\u4ee5\u4fdd\u8bc1\u6240\u6709\u7684\u5fc5\u8981\u521d\u59cb\u5316\u6b65\u9aa4\u90fd\u80fd\u5f97\u5230\u6267\u884c\u3002\n\u6bd4\u5982\uff0ctypes.new_class() \u7b2c\u56db\u4e2a\u53c2\u6570\u7684\u56de\u8c03\u51fd\u6570\u63a5\u53d7 __prepare__() \u65b9\u6cd5\u8fd4\u56de\u7684\u6620\u5c04\u5bf9\u8c61\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5982\u679c\u4f60\u4ec5\u4ec5\u53ea\u662f\u60f3\u6267\u884c\u51c6\u5907\u6b65\u9aa4\uff0c\u53ef\u4ee5\u4f7f\u7528 types.prepare_class() \u3002\u4f8b\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import types\nmetaclass, kwargs, ns = types.prepare_class('Stock', (), {'metaclass': type})"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5b83\u4f1a\u67e5\u627e\u5408\u9002\u7684\u5143\u7c7b\u5e76\u8c03\u7528\u5b83\u7684 __prepare__() \u65b9\u6cd5\u3002\n\u7136\u540e\u8fd9\u4e2a\u5143\u7c7b\u4fdd\u5b58\u5b83\u7684\u5173\u952e\u5b57\u53c2\u6570\uff0c\u51c6\u5907\u547d\u540d\u7a7a\u95f4\u540e\u88ab\u8fd4\u56de\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u66f4\u591a\u4fe1\u606f, \u8bf7\u53c2\u8003 PEP 3115 ,\n\u4ee5\u53ca Python documentation ."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 9.19 \u5728\u5b9a\u4e49\u7684\u65f6\u5019\u521d\u59cb\u5316\u7c7b\u7684\u6210\u5458\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u95ee\u9898\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f60\u60f3\u5728\u7c7b\u88ab\u5b9a\u4e49\u7684\u65f6\u5019\u5c31\u521d\u59cb\u5316\u4e00\u90e8\u5206\u7c7b\u7684\u6210\u5458\uff0c\u800c\u4e0d\u662f\u8981\u7b49\u5230\u5b9e\u4f8b\u88ab\u521b\u5efa\u540e\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u89e3\u51b3\u65b9\u6848\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5728\u7c7b\u5b9a\u4e49\u65f6\u5c31\u6267\u884c\u521d\u59cb\u5316\u6216\u8bbe\u7f6e\u64cd\u4f5c\u662f\u5143\u7c7b\u7684\u4e00\u4e2a\u5178\u578b\u5e94\u7528\u573a\u666f\u3002\u672c\u8d28\u4e0a\u8bb2\uff0c\u4e00\u4e2a\u5143\u7c7b\u4f1a\u5728\u5b9a\u4e49\u65f6\u88ab\u89e6\u53d1\uff0c\n\u8fd9\u65f6\u5019\u4f60\u53ef\u4ee5\u6267\u884c\u4e00\u4e9b\u989d\u5916\u7684\u64cd\u4f5c\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e0b\u9762\u662f\u4e00\u4e2a\u4f8b\u5b50\uff0c\u5229\u7528\u8fd9\u4e2a\u601d\u8def\u6765\u521b\u5efa\u7c7b\u4f3c\u4e8e collections \u6a21\u5757\u4e2d\u7684\u547d\u540d\u5143\u7ec4\u7684\u7c7b\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import operator\n\nclass StructTupleMeta(type):\n def __init__(cls, *args, **kwargs):\n super().__init__(*args, **kwargs)\n for n, name in enumerate(cls._fields):\n setattr(cls, name, property(operator.itemgetter(n)))\n\nclass StructTuple(tuple, metaclass=StructTupleMeta):\n _fields = []\n def __new__(cls, *args):\n if len(args) != len(cls._fields):\n raise ValueError('{} arguments required'.format(len(cls._fields)))\n return super().__new__(cls,args)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u8fd9\u6bb5\u4ee3\u7801\u53ef\u4ee5\u7528\u6765\u5b9a\u4e49\u7b80\u5355\u7684\u57fa\u4e8e\u5143\u7ec4\u7684\u6570\u636e\u7ed3\u6784\uff0c\u5982\u4e0b\u6240\u793a\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class Stock(StructTuple):\n _fields = ['name', 'shares', 'price']\n\nclass Point(StructTuple):\n _fields = ['x', 'y']"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e0b\u9762\u6f14\u793a\u5b83\u5982\u4f55\u5de5\u4f5c\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"s = Stock('ACME', 50, 91.1)\ns"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"s[0]"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"s.name"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"s.shares * s.price"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"s.shares = 23"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u8ba8\u8bba\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u8fd9\u4e00\u5c0f\u8282\u4e2d\uff0c\u7c7b StructTupleMeta \u83b7\u53d6\u5230\u7c7b\u5c5e\u6027 _fields \u4e2d\u7684\u5c5e\u6027\u540d\u5b57\u5217\u8868\uff0c\n\u7136\u540e\u5c06\u5b83\u4eec\u8f6c\u6362\u6210\u76f8\u5e94\u7684\u53ef\u8bbf\u95ee\u7279\u5b9a\u5143\u7ec4\u69fd\u7684\u65b9\u6cd5\u3002\u51fd\u6570 operator.itemgetter() \u521b\u5efa\u4e00\u4e2a\u8bbf\u95ee\u5668\u51fd\u6570\uff0c\n\u7136\u540e property() \u51fd\u6570\u5c06\u5176\u8f6c\u6362\u6210\u4e00\u4e2a\u5c5e\u6027\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u672c\u8282\u6700\u96be\u61c2\u7684\u90e8\u5206\u662f\u77e5\u9053\u4e0d\u540c\u7684\u521d\u59cb\u5316\u6b65\u9aa4\u662f\u4ec0\u4e48\u65f6\u5019\u53d1\u751f\u7684\u3002\nStructTupleMeta \u4e2d\u7684 __init__() \u65b9\u6cd5\u53ea\u5728\u6bcf\u4e2a\u7c7b\u88ab\u5b9a\u4e49\u65f6\u88ab\u8c03\u7528\u4e00\u6b21\u3002\ncls \u53c2\u6570\u5c31\u662f\u90a3\u4e2a\u88ab\u5b9a\u4e49\u7684\u7c7b\u3002\u5b9e\u9645\u4e0a\uff0c\u4e0a\u8ff0\u4ee3\u7801\u4f7f\u7528\u4e86 _fields \u7c7b\u53d8\u91cf\u6765\u4fdd\u5b58\u65b0\u7684\u88ab\u5b9a\u4e49\u7684\u7c7b\uff0c\n\u7136\u540e\u7ed9\u5b83\u518d\u6dfb\u52a0\u4e00\u70b9\u65b0\u7684\u4e1c\u897f\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"StructTuple \u7c7b\u4f5c\u4e3a\u4e00\u4e2a\u666e\u901a\u7684\u57fa\u7c7b\uff0c\u4f9b\u5176\u4ed6\u4f7f\u7528\u8005\u6765\u7ee7\u627f\u3002\n\u8fd9\u4e2a\u7c7b\u4e2d\u7684 __new__() \u65b9\u6cd5\u7528\u6765\u6784\u9020\u65b0\u7684\u5b9e\u4f8b\u3002\n\u8fd9\u91cc\u4f7f\u7528 __new__() \u5e76\u4e0d\u662f\u5f88\u5e38\u89c1\uff0c\u4e3b\u8981\u662f\u56e0\u4e3a\u6211\u4eec\u8981\u4fee\u6539\u5143\u7ec4\u7684\u8c03\u7528\u7b7e\u540d\uff0c\n\u4f7f\u5f97\u6211\u4eec\u53ef\u4ee5\u50cf\u666e\u901a\u7684\u5b9e\u4f8b\u8c03\u7528\u90a3\u6837\u521b\u5efa\u5b9e\u4f8b\u3002\u5c31\u50cf\u4e0b\u9762\u8fd9\u6837\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"s = Stock('ACME', 50, 91.1) # OK\ns = Stock(('ACME', 50, 91.1)) # Error"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u8ddf __init__() \u4e0d\u540c\u7684\u662f\uff0c__new__() \u65b9\u6cd5\u5728\u5b9e\u4f8b\u88ab\u521b\u5efa\u4e4b\u524d\u88ab\u89e6\u53d1\u3002\n\u7531\u4e8e\u5143\u7ec4\u662f\u4e0d\u53ef\u4fee\u6539\u7684\uff0c\u6240\u4ee5\u4e00\u65e6\u5b83\u4eec\u88ab\u521b\u5efa\u4e86\u5c31\u4e0d\u53ef\u80fd\u5bf9\u5b83\u505a\u4efb\u4f55\u6539\u53d8\u3002\u800c __init__() \u4f1a\u5728\u5b9e\u4f8b\u521b\u5efa\u7684\u6700\u540e\u88ab\u89e6\u53d1\uff0c\n\u8fd9\u6837\u7684\u8bdd\u6211\u4eec\u5c31\u53ef\u4ee5\u505a\u6211\u4eec\u60f3\u505a\u7684\u4e86\u3002\u8fd9\u4e5f\u662f\u4e3a\u4ec0\u4e48 __new__() \u65b9\u6cd5\u5df2\u7ecf\u88ab\u5b9a\u4e49\u4e86\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5c3d\u7ba1\u672c\u8282\u5f88\u77ed\uff0c\u8fd8\u662f\u9700\u8981\u4f60\u80fd\u4ed4\u7ec6\u7814\u8bfb\uff0c\u6df1\u5165\u601d\u8003Python\u7c7b\u662f\u5982\u4f55\u88ab\u5b9a\u4e49\u7684\uff0c\u5b9e\u4f8b\u662f\u5982\u4f55\u88ab\u521b\u5efa\u7684\uff0c\n\u8fd8\u6709\u5c31\u662f\u5143\u7c7b\u548c\u7c7b\u7684\u5404\u4e2a\u4e0d\u540c\u7684\u65b9\u6cd5\u7a76\u7adf\u5728\u4ec0\u4e48\u65f6\u5019\u88ab\u8c03\u7528\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"PEP 422\n\u63d0\u4f9b\u4e86\u4e00\u4e2a\u89e3\u51b3\u672c\u8282\u95ee\u9898\u7684\u53e6\u5916\u4e00\u79cd\u65b9\u6cd5\u3002\n\u4f46\u662f\uff0c\u622a\u6b62\u5230\u6211\u5199\u8fd9\u672c\u4e66\u7684\u65f6\u5019\uff0c\u5b83\u8fd8\u6ca1\u88ab\u91c7\u7eb3\u548c\u63a5\u53d7\u3002\n\u5c3d\u7ba1\u5982\u6b64\uff0c\u5982\u679c\u4f60\u4f7f\u7528\u7684\u662fPython 3.3\u6216\u66f4\u9ad8\u7684\u7248\u672c\uff0c\u90a3\u4e48\u8fd8\u662f\u503c\u5f97\u53bb\u770b\u4e00\u4e0b\u7684\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 9.20 \u5229\u7528\u51fd\u6570\u6ce8\u89e3\u5b9e\u73b0\u65b9\u6cd5\u91cd\u8f7d\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u95ee\u9898\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f60\u5df2\u7ecf\u5b66\u8fc7\u600e\u6837\u4f7f\u7528\u51fd\u6570\u53c2\u6570\u6ce8\u89e3\uff0c\u90a3\u4e48\u4f60\u53ef\u80fd\u4f1a\u60f3\u5229\u7528\u5b83\u6765\u5b9e\u73b0\u57fa\u4e8e\u7c7b\u578b\u7684\u65b9\u6cd5\u91cd\u8f7d\u3002\n\u4f46\u662f\u4f60\u4e0d\u786e\u5b9a\u5e94\u8be5\u600e\u6837\u53bb\u5b9e\u73b0\uff08\u6216\u8005\u5230\u5e95\u884c\u5f97\u901a\u4e0d\uff09\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u89e3\u51b3\u65b9\u6848\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u672c\u5c0f\u8282\u7684\u6280\u672f\u662f\u57fa\u4e8e\u4e00\u4e2a\u7b80\u5355\u7684\u6280\u672f\uff0c\u90a3\u5c31\u662fPython\u5141\u8bb8\u53c2\u6570\u6ce8\u89e3\uff0c\u4ee3\u7801\u53ef\u4ee5\u50cf\u4e0b\u9762\u8fd9\u6837\u5199\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class Spam:\n def bar(self, x:int, y:int):\n print('Bar 1:', x, y)\n\n def bar(self, s:str, n:int = 0):\n print('Bar 2:', s, n)\n\ns = Spam()\ns.bar(2, 3) # Prints Bar 1: 2 3\ns.bar('hello') # Prints Bar 2: hello 0"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e0b\u9762\u662f\u6211\u4eec\u7b2c\u4e00\u6b65\u7684\u5c1d\u8bd5\uff0c\u4f7f\u7528\u5230\u4e86\u4e00\u4e2a\u5143\u7c7b\u548c\u63cf\u8ff0\u5668\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# multiple.py\nimport inspect\nimport types\n\nclass MultiMethod:\n '''\n Represents a single multimethod.\n '''\n def __init__(self, name):\n self._methods = {}\n self.__name__ = name\n\n def register(self, meth):\n '''\n Register a new method as a multimethod\n '''\n sig = inspect.signature(meth)\n\n # Build a type signature from the method's annotations\n types = []\n for name, parm in sig.parameters.items():\n if name == 'self':\n continue\n if parm.annotation is inspect.Parameter.empty:\n raise TypeError(\n 'Argument {} must be annotated with a type'.format(name)\n )\n if not isinstance(parm.annotation, type):\n raise TypeError(\n 'Argument {} annotation must be a type'.format(name)\n )\n if parm.default is not inspect.Parameter.empty:\n self._methods[tuple(types)] = meth\n types.append(parm.annotation)\n\n self._methods[tuple(types)] = meth\n\n def __call__(self, *args):\n '''\n Call a method based on type signature of the arguments\n '''\n types = tuple(type(arg) for arg in args[1:])\n meth = self._methods.get(types, None)\n if meth:\n return meth(*args)\n else:\n raise TypeError('No matching method for types {}'.format(types))\n\n def __get__(self, instance, cls):\n '''\n Descriptor method needed to make calls work in a class\n '''\n if instance is not None:\n return types.MethodType(self, instance)\n else:\n return self\n\nclass MultiDict(dict):\n '''\n Special dictionary to build multimethods in a metaclass\n '''\n def __setitem__(self, key, value):\n if key in self:\n # If key already exists, it must be a multimethod or callable\n current_value = self[key]\n if isinstance(current_value, MultiMethod):\n current_value.register(value)\n else:\n mvalue = MultiMethod(key)\n mvalue.register(current_value)\n mvalue.register(value)\n super().__setitem__(key, mvalue)\n else:\n super().__setitem__(key, value)\n\nclass MultipleMeta(type):\n '''\n Metaclass that allows multiple dispatch of methods\n '''\n def __new__(cls, clsname, bases, clsdict):\n return type.__new__(cls, clsname, bases, dict(clsdict))\n\n @classmethod\n def __prepare__(cls, clsname, bases):\n return MultiDict()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e3a\u4e86\u4f7f\u7528\u8fd9\u4e2a\u7c7b\uff0c\u4f60\u53ef\u4ee5\u50cf\u4e0b\u9762\u8fd9\u6837\u5199\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class Spam(metaclass=MultipleMeta):\n def bar(self, x:int, y:int):\n print('Bar 1:', x, y)\n\n def bar(self, s:str, n:int = 0):\n print('Bar 2:', s, n)\n\n# Example: overloaded __init__\nimport time\n\nclass Date(metaclass=MultipleMeta):\n def __init__(self, year: int, month:int, day:int):\n self.year = year\n self.month = month\n self.day = day\n\n def __init__(self):\n t = time.localtime()\n self.__init__(t.tm_year, t.tm_mon, t.tm_mday)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e0b\u9762\u662f\u4e00\u4e2a\u4ea4\u4e92\u793a\u4f8b\u6765\u9a8c\u8bc1\u5b83\u80fd\u6b63\u786e\u7684\u5de5\u4f5c\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"s = Spam()\ns.bar(2, 3)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"s.bar('hello')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"s.bar('hello', 5)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"s.bar(2, 'hello')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Overloaded __init__\nd = Date(2012, 12, 21)\n# Get today's date\ne = Date()\ne.year"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"e.month"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"e.day"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u8ba8\u8bba\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5766\u767d\u6765\u8bb2\uff0c\u76f8\u5bf9\u4e8e\u901a\u5e38\u7684\u4ee3\u7801\u800c\u5df2\u672c\u8282\u4f7f\u7528\u5230\u4e86\u5f88\u591a\u7684\u9b54\u6cd5\u4ee3\u7801\u3002\n\u4f46\u662f\uff0c\u5b83\u5374\u80fd\u8ba9\u6211\u4eec\u6df1\u5165\u7406\u89e3\u5143\u7c7b\u548c\u63cf\u8ff0\u5668\u7684\u5e95\u5c42\u5de5\u4f5c\u539f\u7406\uff0c\n\u5e76\u80fd\u52a0\u6df1\u5bf9\u8fd9\u4e9b\u6982\u5ff5\u7684\u5370\u8c61\u3002\u56e0\u6b64\uff0c\u5c31\u7b97\u4f60\u5e76\u4e0d\u4f1a\u7acb\u5373\u53bb\u5e94\u7528\u672c\u8282\u7684\u6280\u672f\uff0c\n\u5b83\u7684\u4e00\u4e9b\u5e95\u5c42\u601d\u60f3\u5374\u4f1a\u5f71\u54cd\u5230\u5176\u5b83\u6d89\u53ca\u5230\u5143\u7c7b\u3001\u63cf\u8ff0\u5668\u548c\u51fd\u6570\u6ce8\u89e3\u7684\u7f16\u7a0b\u6280\u672f\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u672c\u8282\u7684\u5b9e\u73b0\u4e2d\u7684\u4e3b\u8981\u601d\u8def\u5176\u5b9e\u662f\u5f88\u7b80\u5355\u7684\u3002MutipleMeta \u5143\u7c7b\u4f7f\u7528\u5b83\u7684 __prepare__() \u65b9\u6cd5\n\u6765\u63d0\u4f9b\u4e00\u4e2a\u4f5c\u4e3a MultiDict \u5b9e\u4f8b\u7684\u81ea\u5b9a\u4e49\u5b57\u5178\u3002\u8fd9\u4e2a\u8ddf\u666e\u901a\u5b57\u5178\u4e0d\u4e00\u6837\u7684\u662f\uff0c\nMultiDict \u4f1a\u5728\u5143\u7d20\u88ab\u8bbe\u7f6e\u7684\u65f6\u5019\u68c0\u67e5\u662f\u5426\u5df2\u7ecf\u5b58\u5728\uff0c\u5982\u679c\u5b58\u5728\u7684\u8bdd\uff0c\u91cd\u590d\u7684\u5143\u7d20\u4f1a\u5728 MultiMethod\n\u5b9e\u4f8b\u4e2d\u5408\u5e76\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"MultiMethod \u5b9e\u4f8b\u901a\u8fc7\u6784\u5efa\u4ece\u7c7b\u578b\u7b7e\u540d\u5230\u51fd\u6570\u7684\u6620\u5c04\u6765\u6536\u96c6\u65b9\u6cd5\u3002\n\u5728\u8fd9\u4e2a\u6784\u5efa\u8fc7\u7a0b\u4e2d\uff0c\u51fd\u6570\u6ce8\u89e3\u88ab\u7528\u6765\u6536\u96c6\u8fd9\u4e9b\u7b7e\u540d\u7136\u540e\u6784\u5efa\u8fd9\u4e2a\u6620\u5c04\u3002\n\u8fd9\u4e2a\u8fc7\u7a0b\u5728 MultiMethod.register() \u65b9\u6cd5\u4e2d\u5b9e\u73b0\u3002\n\u8fd9\u79cd\u6620\u5c04\u7684\u4e00\u4e2a\u5173\u952e\u7279\u70b9\u662f\u5bf9\u4e8e\u591a\u4e2a\u65b9\u6cd5\uff0c\u6240\u6709\u53c2\u6570\u7c7b\u578b\u90fd\u5fc5\u987b\u8981\u6307\u5b9a\uff0c\u5426\u5219\u5c31\u4f1a\u62a5\u9519\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e3a\u4e86\u8ba9 MultiMethod \u5b9e\u4f8b\u6a21\u62df\u4e00\u4e2a\u8c03\u7528\uff0c\u5b83\u7684 __call__() \u65b9\u6cd5\u88ab\u5b9e\u73b0\u4e86\u3002\n\u8fd9\u4e2a\u65b9\u6cd5\u4ece\u6240\u6709\u6392\u9664 slef \u7684\u53c2\u6570\u4e2d\u6784\u5efa\u4e00\u4e2a\u7c7b\u578b\u5143\u7ec4\uff0c\u5728\u5185\u90e8map\u4e2d\u67e5\u627e\u8fd9\u4e2a\u65b9\u6cd5\uff0c\n\u7136\u540e\u8c03\u7528\u76f8\u5e94\u7684\u65b9\u6cd5\u3002\u4e3a\u4e86\u80fd\u8ba9 MultiMethod \u5b9e\u4f8b\u5728\u7c7b\u5b9a\u4e49\u65f6\u6b63\u786e\u64cd\u4f5c\uff0c__get__() \u662f\u5fc5\u987b\u5f97\u5b9e\u73b0\u7684\u3002\n\u5b83\u88ab\u7528\u6765\u6784\u5efa\u6b63\u786e\u7684\u7ed1\u5b9a\u65b9\u6cd5\u3002\u6bd4\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"b = s.bar\nb"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"b.__self__"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"b.__func__"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"b(2, 3)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"b('hello')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e0d\u8fc7\u672c\u8282\u7684\u5b9e\u73b0\u8fd8\u6709\u4e00\u4e9b\u9650\u5236\uff0c\u5176\u4e2d\u4e00\u4e2a\u662f\u5b83\u4e0d\u80fd\u4f7f\u7528\u5173\u952e\u5b57\u53c2\u6570\u3002\u4f8b\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"s.bar(x=2, y=3)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"s.bar(s='hello')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e5f\u8bb8\u6709\u5176\u4ed6\u7684\u65b9\u6cd5\u80fd\u6dfb\u52a0\u8fd9\u79cd\u652f\u6301\uff0c\u4f46\u662f\u5b83\u9700\u8981\u4e00\u4e2a\u5b8c\u5168\u4e0d\u540c\u7684\u65b9\u6cd5\u6620\u5c04\u65b9\u5f0f\u3002\n\u95ee\u9898\u5728\u4e8e\u5173\u952e\u5b57\u53c2\u6570\u7684\u51fa\u73b0\u662f\u6ca1\u6709\u987a\u5e8f\u7684\u3002\u5f53\u5b83\u8ddf\u4f4d\u7f6e\u53c2\u6570\u6df7\u5408\u4f7f\u7528\u65f6\uff0c\n\u90a3\u4f60\u7684\u53c2\u6570\u5c31\u4f1a\u53d8\u5f97\u6bd4\u8f83\u6df7\u4e71\u4e86\uff0c\u8fd9\u65f6\u5019\u4f60\u4e0d\u5f97\u4e0d\u5728 __call__() \u65b9\u6cd5\u4e2d\u5148\u53bb\u505a\u4e2a\u6392\u5e8f\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u540c\u6837\u5bf9\u4e8e\u7ee7\u627f\u4e5f\u662f\u6709\u9650\u5236\u7684\uff0c\u4f8b\u5982\uff0c\u7c7b\u4f3c\u4e0b\u9762\u8fd9\u79cd\u4ee3\u7801\u5c31\u4e0d\u80fd\u6b63\u5e38\u5de5\u4f5c\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class A:\n pass\n\nclass B(A):\n pass\n\nclass C:\n pass\n\nclass Spam(metaclass=MultipleMeta):\n def foo(self, x:A):\n print('Foo 1:', x)\n\n def foo(self, x:C):\n print('Foo 2:', x)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u539f\u56e0\u662f\u56e0\u4e3a x:A \u6ce8\u89e3\u4e0d\u80fd\u6210\u529f\u5339\u914d\u5b50\u7c7b\u5b9e\u4f8b\uff08\u6bd4\u5982B\u7684\u5b9e\u4f8b\uff09\uff0c\u5982\u4e0b\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"s = Spam()\na = A()\ns.foo(a)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"c = C()\ns.foo(c)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"b = B()\ns.foo(b)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f5c\u4e3a\u4f7f\u7528\u5143\u7c7b\u548c\u6ce8\u89e3\u7684\u4e00\u79cd\u66ff\u4ee3\u65b9\u6848\uff0c\u53ef\u4ee5\u901a\u8fc7\u63cf\u8ff0\u5668\u6765\u5b9e\u73b0\u7c7b\u4f3c\u7684\u6548\u679c\u3002\u4f8b\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import types\n\nclass multimethod:\n def __init__(self, func):\n self._methods = {}\n self.__name__ = func.__name__\n self._default = func\n\n def match(self, *types):\n def register(func):\n ndefaults = len(func.__defaults__) if func.__defaults__ else 0\n for n in range(ndefaults+1):\n self._methods[types[:len(types) - n]] = func\n return self\n return register\n\n def __call__(self, *args):\n types = tuple(type(arg) for arg in args[1:])\n meth = self._methods.get(types, None)\n if meth:\n return meth(*args)\n else:\n return self._default(*args)\n\n def __get__(self, instance, cls):\n if instance is not None:\n return types.MethodType(self, instance)\n else:\n return self"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e3a\u4e86\u4f7f\u7528\u63cf\u8ff0\u5668\u7248\u672c\uff0c\u4f60\u9700\u8981\u50cf\u4e0b\u9762\u8fd9\u6837\u5199\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class Spam:\n @multimethod\n def bar(self, *args):\n # Default method called if no match\n raise TypeError('No matching method for bar')\n\n @bar.match(int, int)\n def bar(self, x, y):\n print('Bar 1:', x, y)\n\n @bar.match(str, int)\n def bar(self, s, n = 0):\n print('Bar 2:', s, n)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u63cf\u8ff0\u5668\u65b9\u6848\u540c\u6837\u4e5f\u6709\u524d\u9762\u63d0\u5230\u7684\u9650\u5236\uff08\u4e0d\u652f\u6301\u5173\u952e\u5b57\u53c2\u6570\u548c\u7ee7\u627f\uff09\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u6240\u6709\u4e8b\u7269\u90fd\u662f\u5e73\u7b49\u7684\uff0c\u6709\u597d\u6709\u574f\uff0c\u4e5f\u8bb8\u6700\u597d\u7684\u529e\u6cd5\u5c31\u662f\u5728\u666e\u901a\u4ee3\u7801\u4e2d\u907f\u514d\u4f7f\u7528\u65b9\u6cd5\u91cd\u8f7d\u3002\n\u4e0d\u8fc7\u6709\u4e9b\u7279\u6b8a\u60c5\u51b5\u4e0b\u8fd8\u662f\u6709\u610f\u4e49\u7684\uff0c\u6bd4\u5982\u57fa\u4e8e\u6a21\u5f0f\u5339\u914d\u7684\u65b9\u6cd5\u91cd\u8f7d\u7a0b\u5e8f\u4e2d\u3002\n\u4e3e\u4e2a\u4f8b\u5b50\uff0c8.21\u5c0f\u8282\u4e2d\u7684\u8bbf\u95ee\u8005\u6a21\u5f0f\u53ef\u4ee5\u4fee\u6539\u4e3a\u4e00\u4e2a\u4f7f\u7528\u65b9\u6cd5\u91cd\u8f7d\u7684\u7c7b\u3002\n\u4f46\u662f\uff0c\u9664\u4e86\u8fd9\u4e2a\u4ee5\u5916\uff0c\u901a\u5e38\u4e0d\u5e94\u8be5\u4f7f\u7528\u65b9\u6cd5\u91cd\u8f7d\uff08\u5c31\u7b80\u5355\u7684\u4f7f\u7528\u4e0d\u540c\u540d\u79f0\u7684\u65b9\u6cd5\u5c31\u884c\u4e86\uff09\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5728Python\u793e\u533a\u5bf9\u4e8e\u5b9e\u73b0\u65b9\u6cd5\u91cd\u8f7d\u7684\u8ba8\u8bba\u5df2\u7ecf\u7531\u6765\u5df2\u4e45\u3002\n\u5bf9\u4e8e\u5f15\u53d1\u8fd9\u4e2a\u4e89\u8bba\u7684\u539f\u56e0\uff0c\u53ef\u4ee5\u53c2\u8003\u4e0bGuido van Rossum\u7684\u8fd9\u7bc7\u535a\u5ba2\uff1a\nFive-Minute Multimethods in Python"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 9.21 \u907f\u514d\u91cd\u590d\u7684\u5c5e\u6027\u65b9\u6cd5\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u95ee\u9898\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f60\u5728\u7c7b\u4e2d\u9700\u8981\u91cd\u590d\u7684\u5b9a\u4e49\u4e00\u4e9b\u6267\u884c\u76f8\u540c\u903b\u8f91\u7684\u5c5e\u6027\u65b9\u6cd5\uff0c\u6bd4\u5982\u8fdb\u884c\u7c7b\u578b\u68c0\u67e5\uff0c\u600e\u6837\u53bb\u7b80\u5316\u8fd9\u4e9b\u91cd\u590d\u4ee3\u7801\u5462\uff1f"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u89e3\u51b3\u65b9\u6848\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u8003\u8651\u4e0b\u4e00\u4e2a\u7b80\u5355\u7684\u7c7b\uff0c\u5b83\u7684\u5c5e\u6027\u7531\u5c5e\u6027\u65b9\u6cd5\u5305\u88c5\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class Person:\n def __init__(self, name ,age):\n self.name = name\n self.age = age\n\n @property\n def name(self):\n return self._name\n\n @name.setter\n def name(self, value):\n if not isinstance(value, str):\n raise TypeError('name must be a string')\n self._name = value\n\n @property\n def age(self):\n return self._age\n\n @age.setter\n def age(self, value):\n if not isinstance(value, int):\n raise TypeError('age must be an int')\n self._age = value"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u53ef\u4ee5\u770b\u5230\uff0c\u4e3a\u4e86\u5b9e\u73b0\u5c5e\u6027\u503c\u7684\u7c7b\u578b\u68c0\u67e5\u6211\u4eec\u5199\u4e86\u5f88\u591a\u7684\u91cd\u590d\u4ee3\u7801\u3002\n\u53ea\u8981\u4f60\u4ee5\u540e\u770b\u5230\u7c7b\u4f3c\u8fd9\u6837\u7684\u4ee3\u7801\uff0c\u4f60\u90fd\u5e94\u8be5\u60f3\u529e\u6cd5\u53bb\u7b80\u5316\u5b83\u3002\n\u4e00\u4e2a\u53ef\u884c\u7684\u65b9\u6cd5\u662f\u521b\u5efa\u4e00\u4e2a\u51fd\u6570\u7528\u6765\u5b9a\u4e49\u5c5e\u6027\u5e76\u8fd4\u56de\u5b83\u3002\u4f8b\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def typed_property(name, expected_type):\n storage_name = '_' + name\n\n @property\n def prop(self):\n return getattr(self, storage_name)\n\n @prop.setter\n def prop(self, value):\n if not isinstance(value, expected_type):\n raise TypeError('{} must be a {}'.format(name, expected_type))\n setattr(self, storage_name, value)\n\n return prop\n\n# Example use\nclass Person:\n name = typed_property('name', str)\n age = typed_property('age', int)\n\n def __init__(self, name, age):\n self.name = name\n self.age = age"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u8ba8\u8bba\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u672c\u8282\u6211\u4eec\u6f14\u793a\u5185\u90e8\u51fd\u6570\u6216\u8005\u95ed\u5305\u7684\u4e00\u4e2a\u91cd\u8981\u7279\u6027\uff0c\u5b83\u4eec\u5f88\u50cf\u4e00\u4e2a\u5b8f\u3002\u4f8b\u5b50\u4e2d\u7684\u51fd\u6570 typed_property()\n\u770b\u4e0a\u53bb\u6709\u70b9\u96be\u7406\u89e3\uff0c\u5176\u5b9e\u5b83\u6240\u505a\u7684\u4ec5\u4ec5\u5c31\u662f\u4e3a\u4f60\u751f\u6210\u5c5e\u6027\u5e76\u8fd4\u56de\u8fd9\u4e2a\u5c5e\u6027\u5bf9\u8c61\u3002\n\u56e0\u6b64\uff0c\u5f53\u5728\u4e00\u4e2a\u7c7b\u4e2d\u4f7f\u7528\u5b83\u7684\u65f6\u5019\uff0c\u6548\u679c\u8ddf\u5c06\u5b83\u91cc\u9762\u7684\u4ee3\u7801\u653e\u5230\u7c7b\u5b9a\u4e49\u4e2d\u53bb\u662f\u4e00\u6837\u7684\u3002\n\u5c3d\u7ba1\u5c5e\u6027\u7684 getter \u548c setter \u65b9\u6cd5\u8bbf\u95ee\u4e86\u672c\u5730\u53d8\u91cf\u5982 name , expected_type\n\u4ee5\u53ca storate_name \uff0c\u8fd9\u4e2a\u5f88\u6b63\u5e38\uff0c\u8fd9\u4e9b\u53d8\u91cf\u7684\u503c\u4f1a\u4fdd\u5b58\u5728\u95ed\u5305\u5f53\u4e2d\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u6211\u4eec\u8fd8\u53ef\u4ee5\u4f7f\u7528 functools.partial() \u6765\u7a0d\u7a0d\u6539\u53d8\u4e0b\u8fd9\u4e2a\u4f8b\u5b50\uff0c\u5f88\u6709\u8da3\u3002\u4f8b\u5982\uff0c\u4f60\u53ef\u4ee5\u50cf\u4e0b\u9762\u8fd9\u6837\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from functools import partial\n\nString = partial(typed_property, expected_type=str)\nInteger = partial(typed_property, expected_type=int)\n\n# Example:\nclass Person:\n name = String('name')\n age = Integer('age')\n\n def __init__(self, name, age):\n self.name = name\n self.age = age"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5176\u5b9e\u4f60\u53ef\u4ee5\u53d1\u73b0\uff0c\u8fd9\u91cc\u7684\u4ee3\u7801\u8ddf8.13\u5c0f\u8282\u4e2d\u7684\u7c7b\u578b\u7cfb\u7edf\u63cf\u8ff0\u5668\u4ee3\u7801\u6709\u4e9b\u76f8\u4f3c\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 9.22 \u5b9a\u4e49\u4e0a\u4e0b\u6587\u7ba1\u7406\u5668\u7684\u7b80\u5355\u65b9\u6cd5\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u95ee\u9898\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f60\u60f3\u81ea\u5df1\u53bb\u5b9e\u73b0\u4e00\u4e2a\u65b0\u7684\u4e0a\u4e0b\u6587\u7ba1\u7406\u5668\uff0c\u4ee5\u4fbf\u4f7f\u7528with\u8bed\u53e5\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u89e3\u51b3\u65b9\u6848\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5b9e\u73b0\u4e00\u4e2a\u65b0\u7684\u4e0a\u4e0b\u6587\u7ba1\u7406\u5668\u7684\u6700\u7b80\u5355\u7684\u65b9\u6cd5\u5c31\u662f\u4f7f\u7528 contexlib \u6a21\u5757\u4e2d\u7684 @contextmanager \u88c5\u9970\u5668\u3002\n\u4e0b\u9762\u662f\u4e00\u4e2a\u5b9e\u73b0\u4e86\u4ee3\u7801\u5757\u8ba1\u65f6\u529f\u80fd\u7684\u4e0a\u4e0b\u6587\u7ba1\u7406\u5668\u4f8b\u5b50\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import time\nfrom contextlib import contextmanager\n\n@contextmanager\ndef timethis(label):\n start = time.time()\n try:\n yield\n finally:\n end = time.time()\n print('{}: {}'.format(label, end - start))\n\n# Example use\nwith timethis('counting'):\n n = 10000000\n while n > 0:\n n -= 1"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5728\u51fd\u6570 timethis() \u4e2d\uff0cyield \u4e4b\u524d\u7684\u4ee3\u7801\u4f1a\u5728\u4e0a\u4e0b\u6587\u7ba1\u7406\u5668\u4e2d\u4f5c\u4e3a __enter__() \u65b9\u6cd5\u6267\u884c\uff0c\n\u6240\u6709\u5728 yield \u4e4b\u540e\u7684\u4ee3\u7801\u4f1a\u4f5c\u4e3a __exit__() \u65b9\u6cd5\u6267\u884c\u3002\n\u5982\u679c\u51fa\u73b0\u4e86\u5f02\u5e38\uff0c\u5f02\u5e38\u4f1a\u5728yield\u8bed\u53e5\u90a3\u91cc\u629b\u51fa\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e0b\u9762\u662f\u4e00\u4e2a\u66f4\u52a0\u9ad8\u7ea7\u4e00\u70b9\u7684\u4e0a\u4e0b\u6587\u7ba1\u7406\u5668\uff0c\u5b9e\u73b0\u4e86\u5217\u8868\u5bf9\u8c61\u4e0a\u7684\u67d0\u79cd\u4e8b\u52a1\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"@contextmanager\ndef list_transaction(orig_list):\n working = list(orig_list)\n yield working\n orig_list[:] = working"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u8fd9\u6bb5\u4ee3\u7801\u7684\u4f5c\u7528\u662f\u4efb\u4f55\u5bf9\u5217\u8868\u7684\u4fee\u6539\u53ea\u6709\u5f53\u6240\u6709\u4ee3\u7801\u8fd0\u884c\u5b8c\u6210\u5e76\u4e14\u4e0d\u51fa\u73b0\u5f02\u5e38\u7684\u60c5\u51b5\u4e0b\u624d\u4f1a\u751f\u6548\u3002\n\u4e0b\u9762\u6211\u4eec\u6765\u6f14\u793a\u4e00\u4e0b\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"items = [1, 2, 3]\nwith list_transaction(items) as working:\n working.append(4)\n working.append(5)\nitems"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"with list_transaction(items) as working:\n working.append(6)\n working.append(7)\n raise RuntimeError('oops')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"items"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u8ba8\u8bba\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u901a\u5e38\u60c5\u51b5\u4e0b\uff0c\u5982\u679c\u8981\u5199\u4e00\u4e2a\u4e0a\u4e0b\u6587\u7ba1\u7406\u5668\uff0c\u4f60\u9700\u8981\u5b9a\u4e49\u4e00\u4e2a\u7c7b\uff0c\u91cc\u9762\u5305\u542b\u4e00\u4e2a __enter__() \u548c\u4e00\u4e2a\n__exit__() \u65b9\u6cd5\uff0c\u5982\u4e0b\u6240\u793a\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import time\n\nclass timethis:\n def __init__(self, label):\n self.label = label\n\n def __enter__(self):\n self.start = time.time()\n\n def __exit__(self, exc_ty, exc_val, exc_tb):\n end = time.time()\n print('{}: {}'.format(self.label, end - self.start))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5c3d\u7ba1\u8fd9\u4e2a\u4e5f\u4e0d\u96be\u5199\uff0c\u4f46\u662f\u76f8\u6bd4\u8f83\u5199\u4e00\u4e2a\u7b80\u5355\u7684\u4f7f\u7528 @contextmanager \u6ce8\u89e3\u7684\u51fd\u6570\u800c\u8a00\u8fd8\u662f\u7a0d\u663e\u4e4f\u5473\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"@contextmanager \u5e94\u8be5\u4ec5\u4ec5\u7528\u6765\u5199\u81ea\u5305\u542b\u7684\u4e0a\u4e0b\u6587\u7ba1\u7406\u51fd\u6570\u3002\n\u5982\u679c\u4f60\u6709\u4e00\u4e9b\u5bf9\u8c61(\u6bd4\u5982\u4e00\u4e2a\u6587\u4ef6\u3001\u7f51\u7edc\u8fde\u63a5\u6216\u9501)\uff0c\u9700\u8981\u652f\u6301 with \u8bed\u53e5\uff0c\u90a3\u4e48\u4f60\u5c31\u9700\u8981\u5355\u72ec\u5b9e\u73b0\n__enter__() \u65b9\u6cd5\u548c __exit__() \u65b9\u6cd5\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 9.23 \u5728\u5c40\u90e8\u53d8\u91cf\u57df\u4e2d\u6267\u884c\u4ee3\u7801\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u95ee\u9898\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f60\u60f3\u5728\u4f7f\u7528\u8303\u56f4\u5185\u6267\u884c\u67d0\u4e2a\u4ee3\u7801\u7247\u6bb5\uff0c\u5e76\u4e14\u5e0c\u671b\u5728\u6267\u884c\u540e\u6240\u6709\u7684\u7ed3\u679c\u90fd\u4e0d\u53ef\u89c1\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u89e3\u51b3\u65b9\u6848\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e3a\u4e86\u7406\u89e3\u8fd9\u4e2a\u95ee\u9898\uff0c\u5148\u8bd5\u8bd5\u4e00\u4e2a\u7b80\u5355\u573a\u666f\u3002\u9996\u5148\uff0c\u5728\u5168\u5c40\u547d\u540d\u7a7a\u95f4\u5185\u6267\u884c\u4e00\u4e2a\u4ee3\u7801\u7247\u6bb5\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"a = 13\nexec('b = a + 1')\nprint(b)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u7136\u540e\uff0c\u518d\u5728\u4e00\u4e2a\u51fd\u6570\u4e2d\u6267\u884c\u540c\u6837\u7684\u4ee3\u7801\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def test():\n a = 13\n exec('b = a + 1')\n print(b)\ntest()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u53ef\u4ee5\u770b\u51fa\uff0c\u6700\u540e\u629b\u51fa\u4e86\u4e00\u4e2aNameError\u5f02\u5e38\uff0c\u5c31\u8ddf\u5728 exec() \u8bed\u53e5\u4ece\u6ca1\u6267\u884c\u8fc7\u4e00\u6837\u3002\n\u8981\u662f\u4f60\u60f3\u5728\u540e\u9762\u7684\u8ba1\u7b97\u4e2d\u4f7f\u7528\u5230 exec() \u6267\u884c\u7ed3\u679c\u7684\u8bdd\u5c31\u4f1a\u6709\u95ee\u9898\u4e86\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e3a\u4e86\u4fee\u6b63\u8fd9\u6837\u7684\u9519\u8bef\uff0c\u4f60\u9700\u8981\u5728\u8c03\u7528 exec() \u4e4b\u524d\u4f7f\u7528 locals() \u51fd\u6570\u6765\u5f97\u5230\u4e00\u4e2a\u5c40\u90e8\u53d8\u91cf\u5b57\u5178\u3002\n\u4e4b\u540e\u4f60\u5c31\u80fd\u4ece\u5c40\u90e8\u5b57\u5178\u4e2d\u83b7\u53d6\u4fee\u6539\u8fc7\u540e\u7684\u53d8\u91cf\u503c\u4e86\u3002\u4f8b\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def test():\n a = 13\n loc = locals()\n exec('b = a + 1')\n b = loc['b']\n print(b)\ntest()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u8ba8\u8bba\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5b9e\u9645\u4e0a\u5bf9\u4e8e exec() \u7684\u6b63\u786e\u4f7f\u7528\u662f\u6bd4\u8f83\u96be\u7684\u3002\u5927\u591a\u6570\u60c5\u51b5\u4e0b\u5f53\u4f60\u8981\u8003\u8651\u4f7f\u7528 exec() \u7684\u65f6\u5019\uff0c\n\u8fd8\u6709\u53e6\u5916\u66f4\u597d\u7684\u89e3\u51b3\u65b9\u6848\uff08\u6bd4\u5982\u88c5\u9970\u5668\u3001\u95ed\u5305\u3001\u5143\u7c7b\u7b49\u7b49\uff09\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u7136\u800c\uff0c\u5982\u679c\u4f60\u4ecd\u7136\u8981\u4f7f\u7528 exec() \uff0c\u672c\u8282\u5217\u51fa\u4e86\u4e00\u4e9b\u5982\u4f55\u6b63\u786e\u4f7f\u7528\u5b83\u7684\u65b9\u6cd5\u3002\n\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0cexec() \u4f1a\u5728\u8c03\u7528\u8005\u5c40\u90e8\u548c\u5168\u5c40\u8303\u56f4\u5185\u6267\u884c\u4ee3\u7801\u3002\u7136\u800c\uff0c\u5728\u51fd\u6570\u91cc\u9762\uff0c\n\u4f20\u9012\u7ed9 exec() \u7684\u5c40\u90e8\u8303\u56f4\u662f\u62f7\u8d1d\u5b9e\u9645\u5c40\u90e8\u53d8\u91cf\u7ec4\u6210\u7684\u4e00\u4e2a\u5b57\u5178\u3002\n\u56e0\u6b64\uff0c\u5982\u679c exec() \u5982\u679c\u6267\u884c\u4e86\u4fee\u6539\u64cd\u4f5c\uff0c\u8fd9\u79cd\u4fee\u6539\u540e\u7684\u7ed3\u679c\u5bf9\u5b9e\u9645\u5c40\u90e8\u53d8\u91cf\u503c\u662f\u6ca1\u6709\u5f71\u54cd\u7684\u3002\n\u4e0b\u9762\u662f\u53e6\u5916\u4e00\u4e2a\u6f14\u793a\u5b83\u7684\u4f8b\u5b50\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def test1():\n x = 0\n exec('x += 1')\n print(x)\ntest1()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e0a\u9762\u4ee3\u7801\u91cc\uff0c\u5f53\u4f60\u8c03\u7528 locals() \u83b7\u53d6\u5c40\u90e8\u53d8\u91cf\u65f6\uff0c\u4f60\u83b7\u5f97\u7684\u662f\u4f20\u9012\u7ed9 exec() \u7684\u5c40\u90e8\u53d8\u91cf\u7684\u4e00\u4e2a\u62f7\u8d1d\u3002\n\u901a\u8fc7\u5728\u4ee3\u7801\u6267\u884c\u540e\u5ba1\u67e5\u8fd9\u4e2a\u5b57\u5178\u7684\u503c\uff0c\u90a3\u5c31\u80fd\u83b7\u53d6\u4fee\u6539\u540e\u7684\u503c\u4e86\u3002\u4e0b\u9762\u662f\u4e00\u4e2a\u6f14\u793a\u4f8b\u5b50\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def test2():\n x = 0\n loc = locals()\n print('before:', loc)\n exec('x += 1')\n print('after:', loc)\n print('x =', x)\ntest2()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4ed4\u7ec6\u89c2\u5bdf\u6700\u540e\u4e00\u6b65\u7684\u8f93\u51fa\uff0c\u9664\u975e\u4f60\u5c06 loc \u4e2d\u88ab\u4fee\u6539\u540e\u7684\u503c\u624b\u52a8\u8d4b\u503c\u7ed9x\uff0c\u5426\u5219x\u53d8\u91cf\u503c\u662f\u4e0d\u4f1a\u53d8\u7684\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5728\u4f7f\u7528 locals() \u7684\u65f6\u5019\uff0c\u4f60\u9700\u8981\u6ce8\u610f\u64cd\u4f5c\u987a\u5e8f\u3002\u6bcf\u6b21\u5b83\u88ab\u8c03\u7528\u7684\u65f6\u5019\uff0c\nlocals() \u4f1a\u83b7\u53d6\u5c40\u90e8\u53d8\u91cf\u503c\u4e2d\u7684\u503c\u5e76\u8986\u76d6\u5b57\u5178\u4e2d\u76f8\u5e94\u7684\u53d8\u91cf\u3002\n\u8bf7\u6ce8\u610f\u89c2\u5bdf\u4e0b\u4e0b\u9762\u8fd9\u4e2a\u8bd5\u9a8c\u7684\u8f93\u51fa\u7ed3\u679c\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def test3():\n x = 0\n loc = locals()\n print(loc)\n exec('x += 1')\n print(loc)\n locals()\n print(loc)\ntest3()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u6ce8\u610f\u6700\u540e\u4e00\u6b21\u8c03\u7528 locals() \u7684\u65f6\u5019x\u7684\u503c\u662f\u5982\u4f55\u88ab\u8986\u76d6\u6389\u7684\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f5c\u4e3a locals() \u7684\u4e00\u4e2a\u66ff\u4ee3\u65b9\u6848\uff0c\u4f60\u53ef\u4ee5\u4f7f\u7528\u4f60\u81ea\u5df1\u7684\u5b57\u5178\uff0c\u5e76\u5c06\u5b83\u4f20\u9012\u7ed9 exec() \u3002\u4f8b\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def test4():\n a = 13\n loc = { 'a' : a }\n glb = { }\n exec('b = a + 1', glb, loc)\n b = loc['b']\n print(b)\ntest4()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5927\u90e8\u5206\u60c5\u51b5\u4e0b\uff0c\u8fd9\u79cd\u65b9\u5f0f\u662f\u4f7f\u7528 exec() \u7684\u6700\u4f73\u5b9e\u8df5\u3002\n\u4f60\u53ea\u9700\u8981\u4fdd\u8bc1\u5168\u5c40\u548c\u5c40\u90e8\u5b57\u5178\u5728\u540e\u9762\u4ee3\u7801\u8bbf\u95ee\u65f6\u5df2\u7ecf\u88ab\u521d\u59cb\u5316\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u8fd8\u6709\u4e00\u70b9\uff0c\u5728\u4f7f\u7528 exec() \u4e4b\u524d\uff0c\u4f60\u53ef\u80fd\u9700\u8981\u95ee\u4e0b\u81ea\u5df1\u662f\u5426\u6709\u5176\u4ed6\u66f4\u597d\u7684\u66ff\u4ee3\u65b9\u6848\u3002\n\u5927\u591a\u6570\u60c5\u51b5\u4e0b\u5f53\u4f60\u8981\u8003\u8651\u4f7f\u7528 exec() \u7684\u65f6\u5019\uff0c\n\u8fd8\u6709\u53e6\u5916\u66f4\u597d\u7684\u89e3\u51b3\u65b9\u6848\uff0c\u6bd4\u5982\u88c5\u9970\u5668\u3001\u95ed\u5305\u3001\u5143\u7c7b\uff0c\u6216\u5176\u4ed6\u4e00\u4e9b\u5143\u7f16\u7a0b\u7279\u6027\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 9.24 \u89e3\u6790\u4e0e\u5206\u6790Python\u6e90\u7801\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u95ee\u9898\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f60\u60f3\u5199\u89e3\u6790\u5e76\u5206\u6790Python\u6e90\u4ee3\u7801\u7684\u7a0b\u5e8f\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u89e3\u51b3\u65b9\u6848\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5927\u90e8\u5206\u7a0b\u5e8f\u5458\u77e5\u9053Python\u80fd\u591f\u8ba1\u7b97\u6216\u6267\u884c\u5b57\u7b26\u4e32\u5f62\u5f0f\u7684\u6e90\u4ee3\u7801\u3002\u4f8b\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"x = 42\neval('2 + 3*4 + x')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"exec('for i in range(10): print(i)')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5c3d\u7ba1\u5982\u6b64\uff0cast \u6a21\u5757\u80fd\u88ab\u7528\u6765\u5c06Python\u6e90\u7801\u7f16\u8bd1\u6210\u4e00\u4e2a\u53ef\u88ab\u5206\u6790\u7684\u62bd\u8c61\u8bed\u6cd5\u6811\uff08AST\uff09\u3002\u4f8b\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import ast\nex = ast.parse('2 + 3*4 + x', mode='eval')\nex"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"ast.dump(ex)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"top = ast.parse('for i in range(10): print(i)', mode='exec')\ntop"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"ast.dump(top)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5206\u6790\u6e90\u7801\u6811\u9700\u8981\u4f60\u81ea\u5df1\u66f4\u591a\u7684\u5b66\u4e60\uff0c\u5b83\u662f\u7531\u4e00\u7cfb\u5217AST\u8282\u70b9\u7ec4\u6210\u7684\u3002\n\u5206\u6790\u8fd9\u4e9b\u8282\u70b9\u6700\u7b80\u5355\u7684\u65b9\u6cd5\u5c31\u662f\u5b9a\u4e49\u4e00\u4e2a\u8bbf\u95ee\u8005\u7c7b\uff0c\u5b9e\u73b0\u5f88\u591a visit_NodeName() \u65b9\u6cd5\uff0c\nNodeName() \u5339\u914d\u90a3\u4e9b\u4f60\u611f\u5174\u8da3\u7684\u8282\u70b9\u3002\u4e0b\u9762\u662f\u8fd9\u6837\u4e00\u4e2a\u7c7b\uff0c\u8bb0\u5f55\u4e86\u54ea\u4e9b\u540d\u5b57\u88ab\u52a0\u8f7d\u3001\u5b58\u50a8\u548c\u5220\u9664\u7684\u4fe1\u606f\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import ast\n\nclass CodeAnalyzer(ast.NodeVisitor):\n def __init__(self):\n self.loaded = set()\n self.stored = set()\n self.deleted = set()\n\n def visit_Name(self, node):\n if isinstance(node.ctx, ast.Load):\n self.loaded.add(node.id)\n elif isinstance(node.ctx, ast.Store):\n self.stored.add(node.id)\n elif isinstance(node.ctx, ast.Del):\n self.deleted.add(node.id)\n\n# Sample usage\nif __name__ == '__main__':\n # Some Python code\n code = '''\n for i in range(10):\n print(i)\n del i\n '''\n\n # Parse into an AST\n top = ast.parse(code, mode='exec')\n\n # Feed the AST to analyze name usage\n c = CodeAnalyzer()\n c.visit(top)\n print('Loaded:', c.loaded)\n print('Stored:', c.stored)\n print('Deleted:', c.deleted)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5982\u679c\u4f60\u8fd0\u884c\u8fd9\u4e2a\u7a0b\u5e8f\uff0c\u4f60\u4f1a\u5f97\u5230\u4e0b\u9762\u8fd9\u6837\u7684\u8f93\u51fa\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"Loaded: {'i', 'range', 'print'}\nStored: {'i'}\nDeleted: {'i'}"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u6700\u540e\uff0cAST\u53ef\u4ee5\u901a\u8fc7 compile() \u51fd\u6570\u6765\u7f16\u8bd1\u5e76\u6267\u884c\u3002\u4f8b\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"exec(compile(top,'<stdin>', 'exec'))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u8ba8\u8bba\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5f53\u4f60\u80fd\u591f\u5206\u6790\u6e90\u4ee3\u7801\u5e76\u4ece\u4e2d\u83b7\u53d6\u4fe1\u606f\u7684\u65f6\u5019\uff0c\u4f60\u5c31\u80fd\u5199\u5f88\u591a\u4ee3\u7801\u5206\u6790\u3001\u4f18\u5316\u6216\u9a8c\u8bc1\u5de5\u5177\u4e86\u3002\n\u4f8b\u5982\uff0c\u76f8\u6bd4\u76f2\u76ee\u7684\u4f20\u9012\u4e00\u4e9b\u4ee3\u7801\u7247\u6bb5\u5230\u7c7b\u4f3c exec() \u51fd\u6570\u4e2d\uff0c\u4f60\u53ef\u4ee5\u5148\u5c06\u5b83\u8f6c\u6362\u6210\u4e00\u4e2aAST\uff0c\n\u7136\u540e\u89c2\u5bdf\u5b83\u7684\u7ec6\u8282\u770b\u5b83\u5230\u5e95\u662f\u600e\u6837\u505a\u7684\u3002\n\u4f60\u8fd8\u53ef\u4ee5\u5199\u4e00\u4e9b\u5de5\u5177\u6765\u67e5\u770b\u67d0\u4e2a\u6a21\u5757\u7684\u5168\u90e8\u6e90\u7801\uff0c\u5e76\u4e14\u5728\u6b64\u57fa\u7840\u4e0a\u6267\u884c\u67d0\u4e9b\u9759\u6001\u5206\u6790\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u9700\u8981\u6ce8\u610f\u7684\u662f\uff0c\u5982\u679c\u4f60\u77e5\u9053\u81ea\u5df1\u5728\u5e72\u5565\uff0c\u4f60\u8fd8\u80fd\u591f\u91cd\u5199AST\u6765\u8868\u793a\u65b0\u7684\u4ee3\u7801\u3002\n\u4e0b\u9762\u662f\u4e00\u4e2a\u88c5\u9970\u5668\u4f8b\u5b50\uff0c\u53ef\u4ee5\u901a\u8fc7\u91cd\u65b0\u89e3\u6790\u51fd\u6570\u4f53\u6e90\u7801\u3001\n\u91cd\u5199AST\u5e76\u91cd\u65b0\u521b\u5efa\u51fd\u6570\u4ee3\u7801\u5bf9\u8c61\u6765\u5c06\u5168\u5c40\u8bbf\u95ee\u53d8\u91cf\u964d\u4e3a\u51fd\u6570\u4f53\u4f5c\u7528\u8303\u56f4\uff0c"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# namelower.py\nimport ast\nimport inspect\n\n# Node visitor that lowers globally accessed names into\n# the function body as local variables.\nclass NameLower(ast.NodeVisitor):\n def __init__(self, lowered_names):\n self.lowered_names = lowered_names\n\n def visit_FunctionDef(self, node):\n # Compile some assignments to lower the constants\n code = '__globals = globals()\\n'\n code += '\\n'.join(\"{0} = __globals['{0}']\".format(name)\n for name in self.lowered_names)\n code_ast = ast.parse(code, mode='exec')\n\n # Inject new statements into the function body\n node.body[:0] = code_ast.body\n\n # Save the function object\n self.func = node\n\n# Decorator that turns global names into locals\ndef lower_names(*namelist):\n def lower(func):\n srclines = inspect.getsource(func).splitlines()\n # Skip source lines prior to the @lower_names decorator\n for n, line in enumerate(srclines):\n if '@lower_names' in line:\n break\n\n src = '\\n'.join(srclines[n+1:])\n # Hack to deal with indented code\n if src.startswith((' ','\\t')):\n src = 'if 1:\\n' + src\n top = ast.parse(src, mode='exec')\n\n # Transform the AST\n cl = NameLower(namelist)\n cl.visit(top)\n\n # Execute the modified AST\n temp = {}\n exec(compile(top,'','exec'), temp, temp)\n\n # Pull out the modified code object\n func.__code__ = temp[func.__name__].__code__\n return func\n return lower"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4e3a\u4e86\u4f7f\u7528\u8fd9\u4e2a\u4ee3\u7801\uff0c\u4f60\u53ef\u4ee5\u50cf\u4e0b\u9762\u8fd9\u6837\u5199\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"INCR = 1\n@lower_names('INCR')\ndef countdown(n):\n while n > 0:\n n -= INCR"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u88c5\u9970\u5668\u4f1a\u5c06 countdown() \u51fd\u6570\u91cd\u5199\u4e3a\u7c7b\u4f3c\u4e0b\u9762\u8fd9\u6837\u5b50\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def countdown(n):\n __globals = globals()\n INCR = __globals['INCR']\n while n > 0:\n n -= INCR"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5728\u6027\u80fd\u6d4b\u8bd5\u4e2d\uff0c\u5b83\u4f1a\u8ba9\u51fd\u6570\u8fd0\u884c\u5feb20%"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u73b0\u5728\uff0c\u4f60\u662f\u4e0d\u662f\u60f3\u4e3a\u4f60\u6240\u6709\u7684\u51fd\u6570\u90fd\u52a0\u4e0a\u8fd9\u4e2a\u88c5\u9970\u5668\u5462\uff1f\u6216\u8bb8\u4e0d\u4f1a\u3002\n\u4f46\u662f\uff0c\u8fd9\u5374\u662f\u5bf9\u4e8e\u4e00\u4e9b\u9ad8\u7ea7\u6280\u672f\u6bd4\u5982AST\u64cd\u4f5c\u3001\u6e90\u7801\u64cd\u4f5c\u7b49\u7b49\u7684\u4e00\u4e2a\u5f88\u597d\u7684\u6f14\u793a\u8bf4\u660e"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u672c\u8282\u53d7\u53e6\u5916\u4e00\u4e2a\u5728 ActiveState \u4e2d\u5904\u7406Python\u5b57\u8282\u7801\u7684\u7ae0\u8282\u7684\u542f\u793a\u3002\n\u4f7f\u7528AST\u662f\u4e00\u4e2a\u66f4\u52a0\u9ad8\u7ea7\u70b9\u7684\u6280\u672f\uff0c\u5e76\u4e14\u4e5f\u66f4\u7b80\u5355\u4e9b\u3002\u53c2\u8003\u4e0b\u9762\u4e00\u8282\u83b7\u5f97\u5b57\u8282\u7801\u7684\u66f4\u591a\u4fe1\u606f\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## 9.25 \u62c6\u89e3Python\u5b57\u8282\u7801\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u95ee\u9898\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f60\u60f3\u901a\u8fc7\u5c06\u4f60\u7684\u4ee3\u7801\u53cd\u7f16\u8bd1\u6210\u4f4e\u7ea7\u7684\u5b57\u8282\u7801\u6765\u67e5\u770b\u5b83\u5e95\u5c42\u7684\u5de5\u4f5c\u673a\u5236\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u89e3\u51b3\u65b9\u6848\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"dis \u6a21\u5757\u53ef\u4ee5\u88ab\u7528\u6765\u8f93\u51fa\u4efb\u4f55Python\u51fd\u6570\u7684\u53cd\u7f16\u8bd1\u7ed3\u679c\u3002\u4f8b\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def countdown(n):\nwhile n > 0:\n print('T-minus', n)\n n -= 1\nprint('Blastoff!')\nimport dis\ndis.dis(countdown)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"### \u8ba8\u8bba\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5f53\u4f60\u60f3\u8981\u77e5\u9053\u4f60\u7684\u7a0b\u5e8f\u5e95\u5c42\u7684\u8fd0\u884c\u673a\u5236\u7684\u65f6\u5019\uff0cdis \u6a21\u5757\u662f\u5f88\u6709\u7528\u7684\u3002\u6bd4\u5982\u5982\u679c\u4f60\u60f3\u8bd5\u7740\u7406\u89e3\u6027\u80fd\u7279\u5f81\u3002\n\u88ab dis() \u51fd\u6570\u89e3\u6790\u7684\u539f\u59cb\u5b57\u8282\u7801\u5982\u4e0b\u6240\u793a\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"countdown.__code__.co_code"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5982\u679c\u4f60\u60f3\u81ea\u5df1\u89e3\u91ca\u8fd9\u6bb5\u4ee3\u7801\uff0c\u4f60\u9700\u8981\u4f7f\u7528\u4e00\u4e9b\u5728 opcode \u6a21\u5757\u4e2d\u5b9a\u4e49\u7684\u5e38\u91cf\u3002\u4f8b\u5982\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"c = countdown.__code__.co_code\nimport opcode\nopcode.opname[c[0]]\nopcode.opname[c[0]]"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"opcode.opname[c[3]]"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u5947\u602a\u7684\u662f\uff0c\u5728 dis \u6a21\u5757\u4e2d\u5e76\u6ca1\u6709\u51fd\u6570\u8ba9\u4f60\u4ee5\u7f16\u7a0b\u65b9\u5f0f\u5f88\u5bb9\u6613\u7684\u6765\u5904\u7406\u5b57\u8282\u7801\u3002\n\u4e0d\u8fc7\uff0c\u4e0b\u9762\u7684\u751f\u6210\u5668\u51fd\u6570\u53ef\u4ee5\u5c06\u539f\u59cb\u5b57\u8282\u7801\u5e8f\u5217\u8f6c\u6362\u6210 opcodes \u548c\u53c2\u6570\u3002"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import opcode\n\ndef generate_opcodes(codebytes):\n extended_arg = 0\n i = 0\n n = len(codebytes)\n while i < n:\n op = codebytes[i]\n i += 1\n if op >= opcode.HAVE_ARGUMENT:\n oparg = codebytes[i] + codebytes[i+1]*256 + extended_arg\n extended_arg = 0\n i += 2\n if op == opcode.EXTENDED_ARG:\n extended_arg = oparg * 65536\n continue\n else:\n oparg = None\n yield (op, oparg)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f7f\u7528\u65b9\u6cd5\u5982\u4e0b\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"for op, oparg in generate_opcodes(countdown.__code__.co_code):\n print(op, opcode.opname[op], oparg)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u8fd9\u79cd\u65b9\u5f0f\u5f88\u5c11\u6709\u4eba\u77e5\u9053\uff0c\u4f60\u53ef\u4ee5\u5229\u7528\u5b83\u66ff\u6362\u4efb\u4f55\u4f60\u60f3\u8981\u66ff\u6362\u7684\u51fd\u6570\u7684\u539f\u59cb\u5b57\u8282\u7801\u3002\n\u4e0b\u9762\u6211\u4eec\u7528\u4e00\u4e2a\u793a\u4f8b\u6765\u6f14\u793a\u6574\u4e2a\u8fc7\u7a0b\uff1a"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def add(x, y):\n return x + y\nc = add.__code__\nc"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"c.co_code"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Make a completely new code object with bogus byte code\nimport types\nnewbytecode = b'xxxxxxx'\nnc = types.CodeType(c.co_argcount, c.co_kwonlyargcount,\n c.co_nlocals, c.co_stacksize, c.co_flags, newbytecode, c.co_consts,\n c.co_names, c.co_varnames, c.co_filename, c.co_name,\n c.co_firstlineno, c.co_lnotab)\nnc"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"add.__code__ = nc\nadd(2,3)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\u4f60\u53ef\u4ee5\u50cf\u8fd9\u6837\u800d\u5927\u62db\u8ba9\u89e3\u91ca\u5668\u5954\u6e83\u3002\u4f46\u662f\uff0c\u5bf9\u4e8e\u7f16\u5199\u66f4\u9ad8\u7ea7\u4f18\u5316\u548c\u5143\u7f16\u7a0b\u5de5\u5177\u7684\u7a0b\u5e8f\u5458\u6765\u8bb2\uff0c\n\u4ed6\u4eec\u53ef\u80fd\u771f\u7684\u9700\u8981\u91cd\u5199\u5b57\u8282\u7801\u3002\u672c\u8282\u6700\u540e\u7684\u90e8\u5206\u6f14\u793a\u4e86\u8fd9\u4e2a\u662f\u600e\u6837\u505a\u5230\u7684\u3002\u4f60\u8fd8\u53ef\u4ee5\u53c2\u8003\u53e6\u5916\u4e00\u4e2a\u7c7b\u4f3c\u7684\u4f8b\u5b50\uff1a\nthis code on ActiveState"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"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.7.1"
|
|
},
|
|
"toc": {
|
|
"base_numbering": 1,
|
|
"nav_menu": {},
|
|
"number_sections": true,
|
|
"sideBar": true,
|
|
"skip_h1_title": true,
|
|
"title_cell": "Table of Contents",
|
|
"title_sidebar": "Contents",
|
|
"toc_cell": false,
|
|
"toc_position": {},
|
|
"toc_section_display": true,
|
|
"toc_window_display": true
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 2
|
|
} |