[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fU_sfIr5j-_fdY6IkP3wcbq7kdg3wbBgi1FWVoTmb3wo":3,"$fJU-4tot_gC5fDkujNeoE-cGsdMy5V_KcdUXLuAnTFgw":16,"$f-tn7IIQUvDtBPANgV_3lCVuFiuKu4P9P2Coqe_j3Aeg":423},{"slug":4,"title":5,"description":6,"content":7,"content_html":8,"pub_date":9,"tags":10,"draft":15},"python-functional-programming","Python 函数式编程：map\u002Ffilter\u002Freduce 之外","Python 不是纯函数式语言，但 functools、itertools、偏函数、闭包这些工具用好了能让代码简洁一个量级。","# Python 函数式编程：map\u002Ffilter\u002Freduce 之外\n\nPython 不是纯函数式语言，但 `functools`、`itertools`、偏函数、闭包这些工具用好了能让代码简洁一个量级。\n\n---\n\n## 一等函数：函数是对象\n\n```python\n# 函数可以赋值给变量\ndef square(x):\n    return x ** 2\n\nfn = square\nprint(fn(5))   # 25\n\n# 函数可以存进列表\noperations = [abs, str, type]\nfor op in operations:\n    print(op(-42))   # 42 \u002F -42 \u002F \u003Cclass int>\n\n# 函数可以作为参数传递\ndef apply(func, value):\n    return func(value)\n\nprint(apply(square, 4))    # 16\n\n# 函数可以作为返回值\ndef multiplier(n):\n    def multiply(x):\n        return x * n\n    return multiply\n\ndouble = multiplier(2)\ntriple = multiplier(3)\nprint(double(5))   # 10\nprint(triple(5))   # 15\n```\n\n---\n\n## 高阶函数\n\n### map \u002F filter\n```python\nnums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n\n# map：惰性，返回迭代器\nsquares = list(map(lambda x: x**2, nums))\n# 等价于推导式（更 Pythonic）\nsquares = [x**2 for x in nums]\n\n# filter：惰性\nevens = list(filter(lambda x: x % 2 == 0, nums))\n# 等价于\nevens = [x for x in nums if x % 2 == 0]\n```\n\n### sorted \u002F max \u002F min 的 key 参数\n```python\nwords = [\"banana\", \"apple\", \"cherry\", \"date\"]\n\n# 按长度排序\nsorted(words, key=len)              # ['date', 'apple', 'banana', 'cherry']\n\n# 按最后一个字母排序\nsorted(words, key=lambda w: w[-1])\n\n# 多条件排序：先按长度，再按字母\nsorted(words, key=lambda w: (len(w), w))\n\n# 对象列表排序\npeople = [{\"name\": \"Alice\", \"age\": 30}, {\"name\": \"Bob\", \"age\": 25}]\nsorted(people, key=lambda p: p[\"age\"])\n\n# 用 operator 模块替代 lambda（性能更好）\nfrom operator import itemgetter, attrgetter\nsorted(people, key=itemgetter(\"age\"))\n\noldest = max(people, key=itemgetter(\"age\"))\n```\n\n---\n\n## reduce：折叠操作\n\n```python\nfrom functools import reduce\n\nnums = [1, 2, 3, 4, 5]\n\n# sum \u002F product\ntotal = reduce(lambda acc, x: acc + x, nums, 0)   # 15\nproduct = reduce(lambda acc, x: acc * x, nums, 1)  # 120\n\n# 用 reduce 展平嵌套列表\nnested = [[1,2], [3,4], [5,6]]\nflat = reduce(lambda acc, x: acc + x, nested, [])  # [1,2,3,4,5,6]\n\n# 大多数 reduce 场景有更好替代\nsum(nums)                            # 用内置 sum\nimport math; math.prod(nums)        # 用 math.prod（Python 3.8+）\n[x for sub in nested for x in sub]  # 用推导式展平\n```\n\n**reduce 适合的场景**：自定义折叠逻辑，不能用简单内置函数表达时。\n\n---\n\n## lambda 的边界\n\n```python\n# 合理使用 lambda：简单的 key 函数\nnums.sort(key=lambda x: -x)\npairs.sort(key=lambda p: p[1])\n\n# 滥用 lambda：逻辑复杂时，给函数一个名字更清晰\ndef normalize(s: str) -> str:\n    return s.strip().lower().replace(\"-\", \"_\")\n\n# lambda 无法包含语句，只能是表达式\n# 用三元表达式替代 if-else：\nfn = lambda x: x if x > 0 else -x\n```\n\n---\n\n## 闭包\n\n### 基础\n```python\ndef make_counter(start=0):\n    count = start  # 被内层函数\"捕获\"的自由变量\n\n    def counter():\n        nonlocal count   # 声明修改外层变量\n        count += 1\n        return count\n\n    return counter\n\nc1 = make_counter()\nc2 = make_counter(10)\n\nprint(c1())  # 1\nprint(c1())  # 2\nprint(c2())  # 11（独立的闭包）\n```\n\n### Late Binding 陷阱\n```python\n# 经典 bug：循环中的闭包\nfns = [lambda: i for i in range(5)]\nprint([f() for f in fns])   # [4, 4, 4, 4, 4]  全是 4！\n\n# 原因：lambda 捕获的是变量 i 的引用，不是值\n# 所有 lambda 共享同一个 i，循环结束时 i=4\n\n# 修复方法1：默认参数（在定义时绑定值）\nfns = [lambda i=i: i for i in range(5)]\nprint([f() for f in fns])   # [0, 1, 2, 3, 4]\n\n# 修复方法2：工厂函数\ndef make_fn(i):\n    return lambda: i\n\nfns = [make_fn(i) for i in range(5)]\n```\n\n### 闭包作工厂函数\n```python\ndef make_validator(min_val, max_val):\n    def validate(x):\n        if not (min_val \u003C= x \u003C= max_val):\n            raise ValueError(f\"{x} not in [{min_val}, {max_val}]\")\n        return x\n    return validate\n\ncheck_age = make_validator(0, 150)\ncheck_score = make_validator(0, 100)\n```\n\n---\n\n## 装饰器\n\n### 基础装饰器\n```python\nimport functools\n\ndef my_decorator(func):\n    @functools.wraps(func)   # 保留原函数的 __name__、__doc__ 等元数据\n    def wrapper(*args, **kwargs):\n        print(f\"Calling {func.__name__}\")\n        result = func(*args, **kwargs)\n        print(f\"{func.__name__} returned {result!r}\")\n        return result\n    return wrapper\n\n@my_decorator\ndef add(a, b):\n    return a + b\n\nadd(1, 2)\n# Calling add\n# add returned 3\n```\n\n### 计时器装饰器\n```python\nimport time, functools\n\ndef timer(func):\n    @functools.wraps(func)\n    def wrapper(*args, **kwargs):\n        start = time.perf_counter()\n        result = func(*args, **kwargs)\n        elapsed = time.perf_counter() - start\n        print(f\"{func.__name__} took {elapsed:.4f}s\")\n        return result\n    return wrapper\n\n@timer\ndef slow_function():\n    time.sleep(0.1)\n```\n\n### 重试装饰器（带参数）\n```python\ndef retry(times=3, exceptions=(Exception,), delay=0.5):\n    def decorator(func):\n        @functools.wraps(func)\n        def wrapper(*args, **kwargs):\n            for attempt in range(1, times + 1):\n                try:\n                    return func(*args, **kwargs)\n                except exceptions as e:\n                    if attempt == times:\n                        raise\n                    print(f\"Attempt {attempt} failed: {e}. Retrying...\")\n                    time.sleep(delay)\n        return wrapper\n    return decorator\n\n@retry(times=3, exceptions=(ConnectionError,), delay=1)\ndef fetch_data(url):\n    pass\n```\n\n### lru_cache：缓存装饰器\n```python\nfrom functools import lru_cache\n\n@lru_cache(maxsize=128)\ndef fibonacci(n):\n    if n \u003C 2: return n\n    return fibonacci(n-1) + fibonacci(n-2)\n\nfibonacci(100)   # 瞬间完成\nfibonacci.cache_info()  # CacheInfo(hits=..., misses=..., maxsize=128, currsize=...)\n```\n\n---\n\n## functools 模块\n\n```python\nfrom functools import partial, lru_cache, cache, cached_property\n\n# partial：偏函数（固定部分参数）\ndef power(base, exp):\n    return base ** exp\n\nsquare = partial(power, exp=2)\ncube = partial(power, exp=3)\nprint(square(5))  # 25\nprint(cube(3))    # 27\n\n# 实际场景：固定序列化参数\nimport json\ndumps_compact = partial(json.dumps, separators=(\",\", \":\"), ensure_ascii=False)\ndumps_pretty = partial(json.dumps, indent=2, ensure_ascii=False)\n\n# cache（Python 3.9+）：无界缓存，等同于 lru_cache(maxsize=None)\n@cache\ndef fib(n):\n    return n if n \u003C 2 else fib(n-1) + fib(n-2)\n\n# cached_property：类属性的惰性计算缓存\nclass DataSet:\n    def __init__(self, data):\n        self._data = data\n\n    @cached_property\n    def stats(self):\n        print(\"Computing stats (expensive)...\")\n        return {\"mean\": sum(self._data)\u002Flen(self._data), \"n\": len(self._data)}\n\nds = DataSet(list(range(1000)))\nprint(ds.stats)  # 计算一次\nprint(ds.stats)  # 直接从缓存返回\n```\n\n---\n\n## itertools：迭代器工具箱\n\n```python\nimport itertools\n\n# chain：连接多个迭代器\nlist(itertools.chain([1,2], [3,4], [5]))        # [1,2,3,4,5]\nlist(itertools.chain.from_iterable([[1,2],[3]])) # [1,2,3]\n\n# islice：切片（适用于任意迭代器）\nlist(itertools.islice(range(100), 5, 10))  # [5, 6, 7, 8, 9]\n\n# groupby：按 key 分组（需要先排序）\ndata = [(\"a\", 1), (\"b\", 2), (\"a\", 3), (\"b\", 4)]\ndata.sort(key=lambda x: x[0])\nfor key, group in itertools.groupby(data, key=lambda x: x[0]):\n    print(key, list(group))\n\n# product：笛卡尔积\nlist(itertools.product([1,2], [\"a\",\"b\"]))\n# [(1,'a'), (1,'b'), (2,'a'), (2,'b')]\n\n# combinations 和 permutations\nlist(itertools.combinations([1,2,3], 2))   # [(1,2),(1,3),(2,3)]\nlist(itertools.permutations([1,2,3], 2))   # 6个结果\n\n# accumulate：累积运算\nimport operator\nlist(itertools.accumulate([1,2,3,4,5]))               # [1,3,6,10,15]\nlist(itertools.accumulate([1,2,3,4,5], operator.mul)) # [1,2,6,24,120]\nlist(itertools.accumulate([3,1,4,1,5,9], max))        # [3,3,4,4,5,9]\n\n# takewhile \u002F dropwhile\nlist(itertools.takewhile(lambda x: x \u003C 5, [1,2,3,5,6]))  # [1,2,3]\nlist(itertools.dropwhile(lambda x: x \u003C 5, [1,2,3,5,6]))  # [5,6]\n```\n\n---\n\n## operator 模块：替代简单 lambda\n\n```python\nfrom operator import itemgetter, attrgetter, methodcaller\n\n# itemgetter：替代 lambda x: x[key]\ndata = [{\"name\": \"Alice\", \"age\": 30}, {\"name\": \"Bob\", \"age\": 25}]\nsorted(data, key=itemgetter(\"age\"))\n\n# 多 key 排序\nsorted(data, key=itemgetter(\"name\", \"age\"))\n\n# attrgetter：替代 lambda x: x.attr\nfrom datetime import datetime\ndates = [datetime(2024,1,3), datetime(2024,1,1), datetime(2024,1,2)]\nsorted(dates, key=attrgetter(\"day\"))\n\n# methodcaller：替代 lambda x: x.method(args)\nfrom operator import methodcaller\nwords = [\"hello\", \"WORLD\", \"Python\"]\nlist(map(methodcaller(\"lower\"), words))   # ['hello', 'world', 'python']\n```\n\n---\n\n## 生成器与 yield from\n\n```python\n# 生成器函数：遇到 yield 暂停，保留状态\ndef fibonacci():\n    a, b = 0, 1\n    while True:\n        yield a\n        a, b = b, a + b\n\ngen = fibonacci()\nprint([next(gen) for _ in range(10)])  # [0,1,1,2,3,5,8,13,21,34]\n\n# yield from：委托给子生成器\ndef flatten(nested):\n    for item in nested:\n        if isinstance(item, list):\n            yield from flatten(item)  # 递归委托\n        else:\n            yield item\n\nlist(flatten([1, [2, [3, 4]], [5, 6]]))  # [1, 2, 3, 4, 5, 6]\n\n# 生成器 vs 列表：内存对比\nimport sys\nlst = [x**2 for x in range(1000000)]\ngen = (x**2 for x in range(1000000))\nprint(sys.getsizeof(lst))  # ~8 MB\nprint(sys.getsizeof(gen))  # ~104 bytes！\n\n# 惰性管道\ndef read_lines(path):\n    with open(path) as f:\n        yield from f\n\ndef grep(pattern, lines):\n    import re\n    return (line for line in lines if re.search(pattern, line))\n\ndef trim(lines):\n    return (line.strip() for line in lines)\n\n# pipeline = trim(grep(r\"ERROR\", read_lines(\"\u002Fvar\u002Flog\u002Fapp.log\")))\n# 整个管道是惰性的，不会一次性读入内存\n```\n\n---\n\n## 不可变数据原则\n\n```python\n# 避免副作用：不修改传入的参数\n\n# 有副作用（bad）\ndef add_item_bad(lst, item):\n    lst.append(item)     # 修改了外部传入的列表！\n    return lst\n\n# 无副作用（good）\ndef add_item_good(lst, item):\n    return lst + [item]  # 返回新列表\n\n# 对于复杂对象，用 copy\nimport copy\ndef process(data):\n    data = copy.deepcopy(data)\n    data[\"processed\"] = True\n    return data\n\n# 函数式管道\nfrom functools import reduce\n\ndef pipeline(*funcs):\n    return reduce(lambda f, g: lambda x: g(f(x)), funcs)\n\nnormalize = pipeline(\n    str.strip,\n    str.lower,\n    lambda s: s.replace(\"-\", \"_\"),\n    lambda s: s.replace(\" \", \"_\"),\n)\n\nprint(normalize(\"  Hello World  \"))  # hello_world\n```\n","\u003Ch1>Python 函数式编程：map\u002Ffilter\u002Freduce 之外\u003C\u002Fh1>\n\u003Cp>Python 不是纯函数式语言，但 \u003Ccode>functools\u003C\u002Fcode>、\u003Ccode>itertools\u003C\u002Fcode>、偏函数、闭包这些工具用好了能让代码简洁一个量级。\u003C\u002Fp>\n\u003Chr>\n\u003Ch2 id=\"一等函数-函数是对象\">一等函数：函数是对象\u003C\u002Fh2>\n\u003Cpre>\u003Ccode class=\"language-python\"># 函数可以赋值给变量\ndef square(x):\n    return x ** 2\n\nfn = square\nprint(fn(5))   # 25\n\n# 函数可以存进列表\noperations = [abs, str, type]\nfor op in operations:\n    print(op(-42))   # 42 \u002F -42 \u002F &lt;class int&gt;\n\n# 函数可以作为参数传递\ndef apply(func, value):\n    return func(value)\n\nprint(apply(square, 4))    # 16\n\n# 函数可以作为返回值\ndef multiplier(n):\n    def multiply(x):\n        return x * n\n    return multiply\n\ndouble = multiplier(2)\ntriple = multiplier(3)\nprint(double(5))   # 10\nprint(triple(5))   # 15\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Chr>\n\u003Ch2 id=\"高阶函数\">高阶函数\u003C\u002Fh2>\n\u003Ch3 id=\"map-filter\">map \u002F filter\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-python\">nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n\n# map：惰性，返回迭代器\nsquares = list(map(lambda x: x**2, nums))\n# 等价于推导式（更 Pythonic）\nsquares = [x**2 for x in nums]\n\n# filter：惰性\nevens = list(filter(lambda x: x % 2 == 0, nums))\n# 等价于\nevens = [x for x in nums if x % 2 == 0]\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3 id=\"sorted-max-min-的-key-参数\">sorted \u002F max \u002F min 的 key 参数\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-python\">words = [&quot;banana&quot;, &quot;apple&quot;, &quot;cherry&quot;, &quot;date&quot;]\n\n# 按长度排序\nsorted(words, key=len)              # ['date', 'apple', 'banana', 'cherry']\n\n# 按最后一个字母排序\nsorted(words, key=lambda w: w[-1])\n\n# 多条件排序：先按长度，再按字母\nsorted(words, key=lambda w: (len(w), w))\n\n# 对象列表排序\npeople = [{&quot;name&quot;: &quot;Alice&quot;, &quot;age&quot;: 30}, {&quot;name&quot;: &quot;Bob&quot;, &quot;age&quot;: 25}]\nsorted(people, key=lambda p: p[&quot;age&quot;])\n\n# 用 operator 模块替代 lambda（性能更好）\nfrom operator import itemgetter, attrgetter\nsorted(people, key=itemgetter(&quot;age&quot;))\n\noldest = max(people, key=itemgetter(&quot;age&quot;))\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Chr>\n\u003Ch2 id=\"reduce-折叠操作\">reduce：折叠操作\u003C\u002Fh2>\n\u003Cpre>\u003Ccode class=\"language-python\">from functools import reduce\n\nnums = [1, 2, 3, 4, 5]\n\n# sum \u002F product\ntotal = reduce(lambda acc, x: acc + x, nums, 0)   # 15\nproduct = reduce(lambda acc, x: acc * x, nums, 1)  # 120\n\n# 用 reduce 展平嵌套列表\nnested = [[1,2], [3,4], [5,6]]\nflat = reduce(lambda acc, x: acc + x, nested, [])  # [1,2,3,4,5,6]\n\n# 大多数 reduce 场景有更好替代\nsum(nums)                            # 用内置 sum\nimport math; math.prod(nums)        # 用 math.prod（Python 3.8+）\n[x for sub in nested for x in sub]  # 用推导式展平\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>\u003Cstrong>reduce 适合的场景\u003C\u002Fstrong>：自定义折叠逻辑，不能用简单内置函数表达时。\u003C\u002Fp>\n\u003Chr>\n\u003Ch2 id=\"lambda-的边界\">lambda 的边界\u003C\u002Fh2>\n\u003Cpre>\u003Ccode class=\"language-python\"># 合理使用 lambda：简单的 key 函数\nnums.sort(key=lambda x: -x)\npairs.sort(key=lambda p: p[1])\n\n# 滥用 lambda：逻辑复杂时，给函数一个名字更清晰\ndef normalize(s: str) -&gt; str:\n    return s.strip().lower().replace(&quot;-&quot;, &quot;_&quot;)\n\n# lambda 无法包含语句，只能是表达式\n# 用三元表达式替代 if-else：\nfn = lambda x: x if x &gt; 0 else -x\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Chr>\n\u003Ch2 id=\"闭包\">闭包\u003C\u002Fh2>\n\u003Ch3 id=\"基础\">基础\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-python\">def make_counter(start=0):\n    count = start  # 被内层函数&quot;捕获&quot;的自由变量\n\n    def counter():\n        nonlocal count   # 声明修改外层变量\n        count += 1\n        return count\n\n    return counter\n\nc1 = make_counter()\nc2 = make_counter(10)\n\nprint(c1())  # 1\nprint(c1())  # 2\nprint(c2())  # 11（独立的闭包）\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3 id=\"late-binding-陷阱\">Late Binding 陷阱\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-python\"># 经典 bug：循环中的闭包\nfns = [lambda: i for i in range(5)]\nprint([f() for f in fns])   # [4, 4, 4, 4, 4]  全是 4！\n\n# 原因：lambda 捕获的是变量 i 的引用，不是值\n# 所有 lambda 共享同一个 i，循环结束时 i=4\n\n# 修复方法1：默认参数（在定义时绑定值）\nfns = [lambda i=i: i for i in range(5)]\nprint([f() for f in fns])   # [0, 1, 2, 3, 4]\n\n# 修复方法2：工厂函数\ndef make_fn(i):\n    return lambda: i\n\nfns = [make_fn(i) for i in range(5)]\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3 id=\"闭包作工厂函数\">闭包作工厂函数\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-python\">def make_validator(min_val, max_val):\n    def validate(x):\n        if not (min_val &lt;= x &lt;= max_val):\n            raise ValueError(f&quot;{x} not in [{min_val}, {max_val}]&quot;)\n        return x\n    return validate\n\ncheck_age = make_validator(0, 150)\ncheck_score = make_validator(0, 100)\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Chr>\n\u003Ch2 id=\"装饰器\">装饰器\u003C\u002Fh2>\n\u003Ch3 id=\"基础装饰器\">基础装饰器\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-python\">import functools\n\ndef my_decorator(func):\n    @functools.wraps(func)   # 保留原函数的 __name__、__doc__ 等元数据\n    def wrapper(*args, **kwargs):\n        print(f&quot;Calling {func.__name__}&quot;)\n        result = func(*args, **kwargs)\n        print(f&quot;{func.__name__} returned {result!r}&quot;)\n        return result\n    return wrapper\n\n@my_decorator\ndef add(a, b):\n    return a + b\n\nadd(1, 2)\n# Calling add\n# add returned 3\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3 id=\"计时器装饰器\">计时器装饰器\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-python\">import time, functools\n\ndef timer(func):\n    @functools.wraps(func)\n    def wrapper(*args, **kwargs):\n        start = time.perf_counter()\n        result = func(*args, **kwargs)\n        elapsed = time.perf_counter() - start\n        print(f&quot;{func.__name__} took {elapsed:.4f}s&quot;)\n        return result\n    return wrapper\n\n@timer\ndef slow_function():\n    time.sleep(0.1)\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3 id=\"重试装饰器-带参数\">重试装饰器（带参数）\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-python\">def retry(times=3, exceptions=(Exception,), delay=0.5):\n    def decorator(func):\n        @functools.wraps(func)\n        def wrapper(*args, **kwargs):\n            for attempt in range(1, times + 1):\n                try:\n                    return func(*args, **kwargs)\n                except exceptions as e:\n                    if attempt == times:\n                        raise\n                    print(f&quot;Attempt {attempt} failed: {e}. Retrying...&quot;)\n                    time.sleep(delay)\n        return wrapper\n    return decorator\n\n@retry(times=3, exceptions=(ConnectionError,), delay=1)\ndef fetch_data(url):\n    pass\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3 id=\"lru_cache-缓存装饰器\">lru_cache：缓存装饰器\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-python\">from functools import lru_cache\n\n@lru_cache(maxsize=128)\ndef fibonacci(n):\n    if n &lt; 2: return n\n    return fibonacci(n-1) + fibonacci(n-2)\n\nfibonacci(100)   # 瞬间完成\nfibonacci.cache_info()  # CacheInfo(hits=..., misses=..., maxsize=128, currsize=...)\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Chr>\n\u003Ch2 id=\"functools-模块\">functools 模块\u003C\u002Fh2>\n\u003Cpre>\u003Ccode class=\"language-python\">from functools import partial, lru_cache, cache, cached_property\n\n# partial：偏函数（固定部分参数）\ndef power(base, exp):\n    return base ** exp\n\nsquare = partial(power, exp=2)\ncube = partial(power, exp=3)\nprint(square(5))  # 25\nprint(cube(3))    # 27\n\n# 实际场景：固定序列化参数\nimport json\ndumps_compact = partial(json.dumps, separators=(&quot;,&quot;, &quot;:&quot;), ensure_ascii=False)\ndumps_pretty = partial(json.dumps, indent=2, ensure_ascii=False)\n\n# cache（Python 3.9+）：无界缓存，等同于 lru_cache(maxsize=None)\n@cache\ndef fib(n):\n    return n if n &lt; 2 else fib(n-1) + fib(n-2)\n\n# cached_property：类属性的惰性计算缓存\nclass DataSet:\n    def __init__(self, data):\n        self._data = data\n\n    @cached_property\n    def stats(self):\n        print(&quot;Computing stats (expensive)...&quot;)\n        return {&quot;mean&quot;: sum(self._data)\u002Flen(self._data), &quot;n&quot;: len(self._data)}\n\nds = DataSet(list(range(1000)))\nprint(ds.stats)  # 计算一次\nprint(ds.stats)  # 直接从缓存返回\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Chr>\n\u003Ch2 id=\"itertools-迭代器工具箱\">itertools：迭代器工具箱\u003C\u002Fh2>\n\u003Cpre>\u003Ccode class=\"language-python\">import itertools\n\n# chain：连接多个迭代器\nlist(itertools.chain([1,2], [3,4], [5]))        # [1,2,3,4,5]\nlist(itertools.chain.from_iterable([[1,2],[3]])) # [1,2,3]\n\n# islice：切片（适用于任意迭代器）\nlist(itertools.islice(range(100), 5, 10))  # [5, 6, 7, 8, 9]\n\n# groupby：按 key 分组（需要先排序）\ndata = [(&quot;a&quot;, 1), (&quot;b&quot;, 2), (&quot;a&quot;, 3), (&quot;b&quot;, 4)]\ndata.sort(key=lambda x: x[0])\nfor key, group in itertools.groupby(data, key=lambda x: x[0]):\n    print(key, list(group))\n\n# product：笛卡尔积\nlist(itertools.product([1,2], [&quot;a&quot;,&quot;b&quot;]))\n# [(1,'a'), (1,'b'), (2,'a'), (2,'b')]\n\n# combinations 和 permutations\nlist(itertools.combinations([1,2,3], 2))   # [(1,2),(1,3),(2,3)]\nlist(itertools.permutations([1,2,3], 2))   # 6个结果\n\n# accumulate：累积运算\nimport operator\nlist(itertools.accumulate([1,2,3,4,5]))               # [1,3,6,10,15]\nlist(itertools.accumulate([1,2,3,4,5], operator.mul)) # [1,2,6,24,120]\nlist(itertools.accumulate([3,1,4,1,5,9], max))        # [3,3,4,4,5,9]\n\n# takewhile \u002F dropwhile\nlist(itertools.takewhile(lambda x: x &lt; 5, [1,2,3,5,6]))  # [1,2,3]\nlist(itertools.dropwhile(lambda x: x &lt; 5, [1,2,3,5,6]))  # [5,6]\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Chr>\n\u003Ch2 id=\"operator-模块-替代简单-lambda\">operator 模块：替代简单 lambda\u003C\u002Fh2>\n\u003Cpre>\u003Ccode class=\"language-python\">from operator import itemgetter, attrgetter, methodcaller\n\n# itemgetter：替代 lambda x: x[key]\ndata = [{&quot;name&quot;: &quot;Alice&quot;, &quot;age&quot;: 30}, {&quot;name&quot;: &quot;Bob&quot;, &quot;age&quot;: 25}]\nsorted(data, key=itemgetter(&quot;age&quot;))\n\n# 多 key 排序\nsorted(data, key=itemgetter(&quot;name&quot;, &quot;age&quot;))\n\n# attrgetter：替代 lambda x: x.attr\nfrom datetime import datetime\ndates = [datetime(2024,1,3), datetime(2024,1,1), datetime(2024,1,2)]\nsorted(dates, key=attrgetter(&quot;day&quot;))\n\n# methodcaller：替代 lambda x: x.method(args)\nfrom operator import methodcaller\nwords = [&quot;hello&quot;, &quot;WORLD&quot;, &quot;Python&quot;]\nlist(map(methodcaller(&quot;lower&quot;), words))   # ['hello', 'world', 'python']\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Chr>\n\u003Ch2 id=\"生成器与-yield-from\">生成器与 yield from\u003C\u002Fh2>\n\u003Cpre>\u003Ccode class=\"language-python\"># 生成器函数：遇到 yield 暂停，保留状态\ndef fibonacci():\n    a, b = 0, 1\n    while True:\n        yield a\n        a, b = b, a + b\n\ngen = fibonacci()\nprint([next(gen) for _ in range(10)])  # [0,1,1,2,3,5,8,13,21,34]\n\n# yield from：委托给子生成器\ndef flatten(nested):\n    for item in nested:\n        if isinstance(item, list):\n            yield from flatten(item)  # 递归委托\n        else:\n            yield item\n\nlist(flatten([1, [2, [3, 4]], [5, 6]]))  # [1, 2, 3, 4, 5, 6]\n\n# 生成器 vs 列表：内存对比\nimport sys\nlst = [x**2 for x in range(1000000)]\ngen = (x**2 for x in range(1000000))\nprint(sys.getsizeof(lst))  # ~8 MB\nprint(sys.getsizeof(gen))  # ~104 bytes！\n\n# 惰性管道\ndef read_lines(path):\n    with open(path) as f:\n        yield from f\n\ndef grep(pattern, lines):\n    import re\n    return (line for line in lines if re.search(pattern, line))\n\ndef trim(lines):\n    return (line.strip() for line in lines)\n\n# pipeline = trim(grep(r&quot;ERROR&quot;, read_lines(&quot;\u002Fvar\u002Flog\u002Fapp.log&quot;)))\n# 整个管道是惰性的，不会一次性读入内存\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Chr>\n\u003Ch2 id=\"不可变数据原则\">不可变数据原则\u003C\u002Fh2>\n\u003Cpre>\u003Ccode class=\"language-python\"># 避免副作用：不修改传入的参数\n\n# 有副作用（bad）\ndef add_item_bad(lst, item):\n    lst.append(item)     # 修改了外部传入的列表！\n    return lst\n\n# 无副作用（good）\ndef add_item_good(lst, item):\n    return lst + [item]  # 返回新列表\n\n# 对于复杂对象，用 copy\nimport copy\ndef process(data):\n    data = copy.deepcopy(data)\n    data[&quot;processed&quot;] = True\n    return data\n\n# 函数式管道\nfrom functools import reduce\n\ndef pipeline(*funcs):\n    return reduce(lambda f, g: lambda x: g(f(x)), funcs)\n\nnormalize = pipeline(\n    str.strip,\n    str.lower,\n    lambda s: s.replace(&quot;-&quot;, &quot;_&quot;),\n    lambda s: s.replace(&quot; &quot;, &quot;_&quot;),\n)\n\nprint(normalize(&quot;  Hello World  &quot;))  # hello_world\n\u003C\u002Fcode>\u003C\u002Fpre>\n","2026-05-03",[11,12,13,14],"python","函数式","闭包","装饰器",false,[17,30,41,53,62,69,76,83,90,97,107,116,119,128,136,144,153,162,171,181,188,198,204,211,217,226,233,240,248,258,267,276,286,296,306,314,324,335,345,354,362,368,376,384,392,400,408,415],{"slug":18,"title":19,"description":20,"pub_date":21,"tags":22,"draft":15,"word_count":29},"ide-skills-guide","Agent Skills 完全指南：21 款第三方 Skill 深度评测与使用心得","全面评测 21 款第三方 Agent Skills，涵盖 Vue 生态、前端设计、构建工具、实用工具四大分类。从安装配置到实际使用场景，带你了解每个 Skill 的功能特点、最佳实践与使用心得。","2026-06-15",[23,24,25,26,27,28],"agent","skills","AI","效率工具","前端","Vue",4169,{"slug":31,"title":32,"description":33,"pub_date":34,"tags":35,"draft":15,"word_count":40},"linux-kernel-skeleton-struct-funcptr-container_of","Linux 内核骨架：struct、函数指针与 container_of","读懂 Linux 内核源码的三件套：巨大的 struct 组合代替继承、函数指针表实现虚派发、container_of 宏从嵌入成员找回完整对象。","2026-05-09",[36,37,38,39],"linux","kernel","C","container_of",1369,{"slug":42,"title":43,"description":44,"pub_date":45,"tags":46,"draft":15,"word_count":52},"astro-complete-guide-2025","Astro 5 深度剖析：Islands 架构原理、构建优化与 Cloudflare Workers 边缘部署","从编译器视角解析 Astro 5 的 Islands 架构实现原理，Content Layer API 的 Vite 插件机制，Server Islands 的流式渲染，以及如何在 Cloudflare Workers + D1 边缘环境下榨干性能。","2026-05-08",[47,48,49,50,51],"astro","frontend","cloudflare","performance","architecture",3663,{"slug":54,"title":55,"description":56,"pub_date":9,"tags":57,"draft":15,"word_count":61},"llm-prompt-engineering","Prompt Engineering 实战：让 LLM 真正听话的技巧","System prompt 怎么写、Few-shot 怎么设计、Chain-of-Thought 原理，以及常见失败模式和调试方法。",[58,59,60],"ai","llm","工程实践",1723,{"slug":63,"title":64,"description":65,"pub_date":9,"tags":66,"draft":15,"word_count":68},"rag-system-design","RAG 系统设计：从 naive 到 production-ready","Retrieval-Augmented Generation 不只是「向量数据库 + LLM」，分块策略、召回质量、重排序、缓存才是工程核心。",[58,67,59,60],"rag",1613,{"slug":70,"title":71,"description":72,"pub_date":9,"tags":73,"draft":15,"word_count":75},"git-advanced-workflow","Git 进阶工作流：rebase、cherry-pick、bisect 的正确使用","merge 会了，但 rebase 总搞错？bisect 找 bug 提交？interactive rebase 整理历史？这篇一次说清楚。",[74,60],"git",1396,{"slug":77,"title":78,"description":79,"pub_date":9,"tags":80,"draft":15,"word_count":82},"docker-practical-guide","Docker 实战：从会用到用好","会 docker run 不够，Dockerfile 最佳实践、多阶段构建、Compose 编排、镜像瘦身才是日常真正需要的。",[81,36,60],"docker",1268,{"slug":84,"title":85,"description":86,"pub_date":9,"tags":87,"draft":15,"word_count":89},"anthropics-skills-guide","anthropics\u002Fskills：Anthropic 官方 Agent Skills 仓库解析","Anthropic 官方开源的 Agent Skills 标准仓库，127k stars，解析 SKILL.md 规范、17 个示例 skill 的设计模式，以及如何在 Claude Code \u002F Claude.ai \u002F API 中使用",[58,88,23,24],"Claude",2090,{"slug":91,"title":92,"description":93,"pub_date":9,"tags":94,"draft":15,"word_count":96},"karpathy-claude-code-guidelines","Karpathy 的 LLM 编码批评与 CLAUDE.md 最佳实践","基于 Andrej Karpathy 对 LLM 编程助手的观察，forrestchang 提炼出一个 CLAUDE.md 文件，4 条原则解决 AI 编码的典型失控问题：乱猜假设、过度设计、乱改代码、目标不清",[58,88,95,60],"Claude Code",2699,{"slug":98,"title":99,"description":100,"pub_date":9,"tags":101,"draft":15,"word_count":106},"typescript-advanced-patterns","TypeScript 高级模式：让类型系统为你工作","基础 TS 会了但类型总是 any？条件类型、映射类型、模板字面量类型、infer 关键字才是 TS 的真正威力。",[102,103,104,105],"typescript","类型系统","前端工程","高级模式",1419,{"slug":108,"title":109,"description":110,"pub_date":9,"tags":111,"draft":15,"word_count":115},"linux-performance-tuning","Linux 性能调优实战：从 top 到 perf 的完整工具链","遇到性能问题不知道从哪下手？这篇建立系统化的排查思路，从 CPU\u002F内存\u002FIO\u002F网络逐层分析。",[36,112,113,114],"性能","运维","系统编程",1524,{"slug":4,"title":5,"description":6,"pub_date":9,"tags":117,"draft":15,"word_count":118},[11,12,13,14],1867,{"slug":120,"title":121,"description":122,"pub_date":9,"tags":123,"draft":15,"word_count":127},"python-oop-guide","Python 面向对象：__init__ 之外你需要知道的","Python OOP 不只是 class + __init__，魔术方法、描述符、元类才是真正的武器。",[11,124,125,126],"OOP","面向对象","魔术方法",1792,{"slug":129,"title":130,"description":131,"pub_date":9,"tags":132,"draft":15,"word_count":135},"python-data-structures","Python 内置数据结构深度解析","list、dict、set、tuple 不只是数据容器，搞懂它们的底层实现和时间复杂度，才能写出高性能 Python。",[11,133,112,134],"数据结构","算法",1517,{"slug":137,"title":138,"description":139,"pub_date":9,"tags":140,"draft":15,"word_count":143},"python-basics-quick-start","Python 快速上手：写给有编程基础的人","已经会其他语言，想快速掌握 Python 的语法特性和思维方式，这篇是捷径。",[11,141,142],"入门","基础",1607,{"slug":145,"title":146,"description":147,"pub_date":9,"tags":148,"draft":15,"word_count":152},"python-dataclass-pydantic","Python dataclass vs Pydantic：数据类选型指南","dataclass 是标准库的轻量选择，Pydantic v2 是带验证的重武器，什么时候用哪个，这篇说清楚。",[11,149,150,151],"dataclass","pydantic","数据验证",1323,{"slug":154,"title":155,"description":156,"pub_date":9,"tags":157,"draft":15,"word_count":161},"python-asyncio-practical","Python asyncio 实战：从回调地狱到协程优雅","asyncio 是 Python 异步编程的核心，搞懂 event loop、Task、gather 这些概念才能写出真正高效的异步代码。",[11,158,159,160],"asyncio","并发","网络编程",1258,{"slug":163,"title":164,"description":165,"pub_date":9,"tags":166,"draft":15,"word_count":170},"python-type-hints-guide","Python 类型注解完全指南：从入门到实践","Python 3.5+ 引入类型注解，配合 mypy\u002Fpyright 让 Python 也能享受静态类型检查的好处。",[11,167,168,169],"typescript-style","type-hints","工具链",1102,{"slug":172,"title":173,"description":174,"pub_date":175,"tags":176,"draft":15,"word_count":180},"pwa-install-update-button","PWA 踩坑：为什么安装按钮从来不出现","从 beforeinstallprompt 到 Service Worker waiting，把 PWA 的安装与更新提示真正做对","2026-05-02",[177,178,179],"pwa","javascript","web",1683,{"slug":182,"title":183,"description":184,"pub_date":185,"tags":186,"draft":15,"word_count":187},"openclaw-vs-hermes-agent","OpenClaw vs Hermes Agent：两个本地优先 Agent 的设计差异","OpenClaw（Novita AI）和 Hermes Agent（Nous Research）都是本地运行的个人 AI Agent，但在记忆系统、技能学习、运行环境和模型生态上走了不同的路。深入对比两种架构的核心差异。","2026-05-01",[58,23,59],1679,{"slug":189,"title":190,"description":191,"pub_date":185,"tags":192,"draft":15,"word_count":197},"cpp-random-design-patterns","C++ 设计模式实战：RAII、观察者、工厂","用现代 C++（C++17\u002F20）实现三种高频设计模式：RAII 资源管理、观察者模式事件系统、工厂模式插件架构。每种模式给出问题场景、实现代码和真实工程案例。",[193,194,195,196],"cpp","设计模式","c++17","工程",2613,{"slug":199,"title":200,"description":201,"pub_date":185,"tags":202,"draft":15,"word_count":203},"data-structures-fundamentals","数据结构基础：从数组到红黑树","系统梳理常用数据结构的核心原理、时间复杂度和适用场景。数组、链表、栈、队列、哈希表、二叉树、堆、图，每种结构附实现要点和 C++ 代码片段。",[133,134,193,142],3004,{"slug":205,"title":206,"description":207,"pub_date":208,"tags":209,"draft":15,"word_count":210},"ai-agent-what-is","什么是 AI Agent？从 LLM 到自主执行","LLM 本身是无状态问答机，Agent 是什么让它’动’起来的？本文深入解析 Agent 的四个核心能力、ReAct 框架、工具调用原理，以及主流框架横向对比。","2026-04-30",[58,23,59],2116,{"slug":212,"title":213,"description":214,"pub_date":208,"tags":215,"draft":15,"word_count":216},"ai-agent-memory","AI Agent 的记忆系统：从上下文窗口到长期记忆","深入拆解 AI Agent 的四种记忆类型、上下文窗口压缩策略、RAG 向量检索原理，以及三种典型失败模式和工程选型建议。",[58,23,67],2052,{"slug":218,"title":219,"description":220,"pub_date":208,"tags":221,"draft":15,"word_count":225},"network-proxy-vpn-guide","代理与翻墙技术原理：从 HTTP 代理到现代协议","深入解析代理与 VPN 的本质区别，梳理从 SOCKS5 到 Shadowsocks、V2Ray\u002FXray、Hysteria2 的协议演进，以及机场订阅的技术本质。",[222,223,224],"网络","代理","协议",2148,{"slug":227,"title":228,"description":229,"pub_date":208,"tags":230,"draft":15,"word_count":143},"algorithm-binary-search","二分查找：永远写不对？记住这个模板","彻底搞清楚二分查找的边界问题：闭区间和左闭右开两套模板、三道经典 LeetCode 题目完整 C++ 实现，以及二分答案的进阶思路。",[134,231,232,193],"二分查找","leetcode",{"slug":234,"title":235,"description":236,"pub_date":208,"tags":237,"draft":15,"word_count":239},"algorithm-sliding-window","滑动窗口算法：从暴力到 O(n) 的思维跃迁","系统讲解滑动窗口算法的核心模板、适用题型，配合三道经典 LeetCode 题目的完整 C++ 实现，彻底理解双指针收缩思路。",[134,238,232,193],"滑动窗口",1943,{"slug":241,"title":242,"description":243,"pub_date":208,"tags":244,"draft":15,"word_count":247},"network-clash-config","Clash \u002F Mihomo 配置详解：规则、策略组与分流","深入解析 Clash\u002FMihomo 的核心配置结构，包括代理节点、策略组类型、规则优先级、DNS fake-ip 模式，以及一份实用的完整配置模板。",[222,245,223,246],"clash","配置",1292,{"slug":249,"title":250,"description":251,"pub_date":252,"tags":253,"draft":15,"word_count":257},"hid-hotplug","HID 设备热插拔检测：从 udev 到 node-hid","在 Linux 上用 node-hid + usb 库实现可靠的 USB HID 设备热插拔检测，踩坑记录","2026-04-28",[193,254,36,255,256],"hid","nodejs","electron",2039,{"slug":259,"title":260,"description":261,"pub_date":262,"tags":263,"draft":15,"word_count":266},"electron-ipc-types","Electron IPC 类型安全：从 any 到完全类型化","用 TypeScript 泛型封装 Electron IPC，彻底消灭 any，preload 契约集中管理","2026-04-25",[256,102,264,265],"ipc","vue",1446,{"slug":268,"title":269,"description":270,"pub_date":271,"tags":272,"draft":15,"word_count":275},"element-plus-popover-hide","手动关闭多个 el-popover（不用 v-model:visible）","通过 ref + Reflect.get 调用 hide() 方法手动关闭 Element Plus Popover，解释 Vue3 Proxy 导致无法直接调用实例方法的原因。","2024-10-25",[265,273,274],"element-plus","vue3",1321,{"slug":277,"title":278,"description":279,"pub_date":280,"tags":281,"draft":15,"word_count":285},"vite-vue3-ts-elementplus-pinia","用 Vite+（vp）从零搭建 Vue3 + TypeScript + Element Plus + Pinia + Vue Router","使用 Vite+ 统一工具链（vp）一条命令搭建 Vue3 全家桶，涵盖按需导入、Pinia store、路由配置，以及常见坑的解决方案。","2024-08-27",[265,282,102,273,283,284],"vite","pinia","vite-plus",1960,{"slug":287,"title":288,"description":289,"pub_date":290,"tags":291,"draft":15,"word_count":295},"cef-lnk2038-iterator-debug-level","CEF LNK2038：解决 _ITERATOR_DEBUG_LEVEL 不匹配错误","分析 CEF（Chromium Embedded Framework）集成时出现的 LNK2038 _ITERATOR_DEBUG_LEVEL 链接错误，从根本原因到解决方案的完整指南。","2024-05-07",[193,292,293,294],"CEF","Visual Studio","链接错误",1509,{"slug":297,"title":298,"description":299,"pub_date":300,"tags":301,"draft":15,"word_count":305},"npm-electron-install-fix","彻底解决 npm 安装 Electron 失败的问题","分析 npm install electron 失败的根本原因（下载二进制超时\u002F被墙），通过国内镜像（npmmirror）彻底解决，并介绍多种备选方案和常见错误排查。","2024-03-01",[256,302,303,304],"npm","前端工具链","国内镜像",1494,{"slug":307,"title":308,"description":309,"pub_date":310,"tags":311,"draft":15,"word_count":313},"git-out-of-memory","解决 git 报错：Fatal: Out of memory, malloc failed","分析 git 大仓库操作时出现 Out of memory malloc failed 的根本原因，通过调整 pack.windowMemory、http.postBuffer 和 git repack 彻底解决。","2024-01-31",[74,36,312],"工具",2244,{"slug":315,"title":316,"description":317,"pub_date":318,"tags":319,"draft":15,"word_count":323},"vmware-tools-install","在 VMware 虚拟机中安装 open-vm-tools 完整指南","详解 VMware Tools 的作用、open-vm-tools 与官方 VMware Tools 的区别，以及在 Ubuntu 虚拟机中安装并生效的完整步骤和常见问题排查。","2023-11-21",[320,36,321,322],"VMware","Ubuntu","虚拟机",2523,{"slug":325,"title":326,"description":327,"pub_date":328,"tags":329,"draft":15,"word_count":334},"load-balancing-algorithms","负载均衡算法完全指南：从轮询到一致性哈希","系统梳理静态与动态负载均衡算法，涵盖轮询、随机、权重、IP Hash、一致性 Hash、最少连接、最快响应等，并对比 Nginx、Dubbo、Spring Cloud LoadBalancer 的实现差异。","2023-11-15",[330,331,332,333],"分布式","负载均衡","Nginx","微服务",1764,{"slug":336,"title":337,"description":338,"pub_date":339,"tags":340,"draft":15,"word_count":344},"win-cw2a-ca2w","ATL 字符串转换：CW2A 与 CA2W 完全指南","详解 ATL 宏 CW2A\u002FCA2W 在 Unicode 与 ANSI 之间的字符串转换用法、头文件依赖、USES_CONVERSION 宏的作用与常见陷阱。","2023-06-09",[193,341,342,343],"windows","ATL","字符串",1665,{"slug":346,"title":347,"description":348,"pub_date":339,"tags":349,"draft":15,"word_count":353},"csharp-sendmessage-cpp","C# 通过 SendMessage 向 C++ 窗口发送消息与字符串","使用 P\u002FInvoke 调用 user32.dll 的 SendMessage，从 C# 发送自定义 WM_USER 消息及字符串指针给 C++ 原生窗口，并在 C++ 侧正确接收和转换。",[350,193,341,351,352],"C#","互操作","PInvoke",1554,{"slug":355,"title":356,"description":357,"pub_date":358,"tags":359,"draft":15,"word_count":361},"win-postmessage-vector","Windows PostMessage 跨线程传递 std::vector 指针","通过 PostMessage 在 Windows 消息队列中传递 std::vector 指针，使用 reinterpret_cast 将指针装入 LPARAM，并在接收方正确释放内存。","2023-05-26",[193,341,360],"WinAPI",1823,{"slug":363,"title":364,"description":365,"pub_date":358,"tags":366,"draft":15,"word_count":367},"exe-dll-single-package","将 EXE 和 DLL 打包成单一可执行文件","介绍两种将 exe 和依赖 dll 打包成单文件的方案：Enigma Virtual Box 和 WinRAR 自解压，适合发布 Windows 桌面程序时简化分发流程。",[341,193,312],1619,{"slug":369,"title":370,"description":371,"pub_date":358,"tags":372,"draft":15,"word_count":375},"cpp-random-mt19937","C++ 现代随机数生成：用 mt19937 彻底告别 rand()","深入讲解为什么 rand() 不够用，以及如何用 C++11 的 \u003Crandom> 库正确生成高质量随机数，涵盖 mt19937、各种分布和线程安全。",[193,373,374],"c++11","random",1549,{"slug":377,"title":378,"description":379,"pub_date":380,"tags":381,"draft":15,"word_count":383},"win-startup-registry","C++ 实现程序开机自启动：注册表方式详解","通过操作 Windows 注册表 Run 键实现程序开机自启动，包括 HKCU 与 HKLM 区别、完整封装代码、工作目录问题和 UAC 权限处理。","2022-12-26",[341,193,382],"registry",1201,{"slug":385,"title":386,"description":387,"pub_date":388,"tags":389,"draft":15,"word_count":391},"mfc-cstring-wparam","MFC 中 CString 与 WPARAM 之间的转换","详解 MFC 消息传递中 CString 无法直接强转为 WPARAM 的原因，以及两种正确的转换方案，并介绍结构体指针传递的正确姿势。","2022-11-25",[390,193,341],"mfc",1546,{"slug":393,"title":394,"description":395,"pub_date":396,"tags":397,"draft":15,"word_count":399},"duilib-static-build","正确编译 Duilib 静态库：避免 ATL 依赖和链接错误","详解如何用 DuiLib_Static.vcxproj 编译 Duilib 静态库，解决 VARIANT 未定义、Unicode 配置不匹配和 ATL 依赖等常见问题。","2022-08-24",[193,398,341,390],"duilib",2639,{"slug":401,"title":402,"description":403,"pub_date":404,"tags":405,"draft":15,"word_count":407},"mfc-dpi-adaptive","MFC 界面自适应不同分辨率","MFC 对话框程序实现控件和字体随分辨率自动缩放的完整方案，附 DPI Awareness 配置说明","2022-08-17",[390,193,341,406],"dpi",1414,{"slug":409,"title":410,"description":411,"pub_date":412,"tags":413,"draft":15,"word_count":414},"mfc-drag-window","MFC 无标题栏窗口客户区拖动：三种方法对比","MFC 对话框去掉标题栏后如何实现拖动移动窗口，三种方案完整实现与适用场景分析","2022-08-16",[390,193,341],1633,{"slug":416,"title":417,"description":418,"pub_date":419,"tags":420,"draft":15,"word_count":422},"algorithm-number-complement","整数的补数：位运算掩码解法","LeetCode 476 题，用掩码 XOR 实现整数补数，附 C++\u002FPython\u002FJava 三种实现及补数与补码的区别","2021-03-08",[134,421,232],"位运算",1374,[]]