[{"data":1,"prerenderedAt":1423},["ShallowReactive",2],{"/2026/python_essay":3,"surround-/2026/python_essay":1417},{"id":4,"title":5,"body":6,"categories":1395,"date":1397,"description":1398,"draft":1399,"extension":1400,"image":1401,"meta":1402,"navigation":1403,"path":1404,"readingTime":1405,"recommend":1410,"references":1410,"seo":1411,"sitemap":1412,"stem":1413,"tags":1414,"type":1410,"updated":1397,"url":1410,"__hash__":1416},"content/posts/2026/python_essay.md","python_essay",{"type":7,"value":8,"toc":1364},"minimark",[9,19,24,27,31,38,41,52,55,61,65,68,71,74,80,90,108,111,118,124,139,142,148,159,174,199,204,223,226,240,245,259,263,284,287,301,311,314,321,326,375,380,427,441,445,448,465,468,482,499,508,539,560,563,577,582,588,606,609,615,618,629,635,638,644,650,656,659,665,668,671,677,680,683,714,720,723,783,789,792,798,801,807,810,818,828,838,842,861,867,877,883,895,901,905,920,946,949,951,957,960,966,973,979,982,990,993,999,1009,1012,1015,1021,1031,1042,1045,1057,1062,1077,1080,1085,1091,1106,1108,1155,1161,1166,1189,1192,1223,1226,1229,1234,1237,1251,1254,1259,1262,1270,1273,1279,1282,1288,1291,1293,1299,1302,1305,1311,1314,1319,1322,1327,1338,1342,1344,1350,1353,1361],[10,11,12,13],"p",{},"文章大部分参考：",[14,15,16],"a",{"href":16,"rel":17},"https://www.nowcoder.com/discuss/426117497918660608",[18],"nofollow",[20,21,23],"h3",{"id":22},"什么是python","什么是Python？",[10,25,26],{},"Python是一种编程语言，",[20,28,30],{"id":29},"赋值深拷贝浅拷贝","赋值、深拷贝、浅拷贝",[10,32,33,37],{},[34,35,36],"strong",{},"赋值","：对象的赋值就是简单的引用。\n赋值操作不会开辟新的空间，只是复制了对象的引用",[10,39,40],{},"如:",[42,43,49],"pre",{"className":44,"code":46,"language":47,"meta":48},[45],"language-python","a = [1, 2, 3]\nb = a\n","python","",[50,51,46],"code",{"__ignoreMap":48},[10,53,54],{},"此时a和b完全相同，修改a即相当于对b进行修改",[10,56,57,60],{},[34,58,59],{},"拷贝","本质上是在说“新变量”和“原变量”是不是共享同一块内存数据",[62,63,64],"h4",{"id":64},"浅拷贝",[10,66,67],{},"浅拷贝有三种形式：切片操作、工厂函数、copy模块中的copy函数",[10,69,70],{},"只复制第一层对象，里面嵌套的子对象依然共享。也就是说只复制第一层，更深层的数据依然共享。",[10,72,73],{},"例：",[42,75,78],{"className":76,"code":77,"language":47,"meta":48},[45],"import copy\n\na = [[1,2],[3,4]]\nb = copy.copy(a)\n",[50,79,77],{"__ignoreMap":48},[10,81,82,83,86,87],{},"此时",[50,84,85],{"code":85},"a is b","，将得到",[50,88,89],{"code":89},"False",[10,91,92,93,95,96,99,100,103,104,107],{},"外层列表已经复制了，但",[50,94,14],{"code":14},"和",[50,97,98],{"code":98},"b","不是同一个对象\n但判断",[50,101,102],{"code":102},"a[0] is b[0]","将得到",[50,105,106],{"code":106},"True","\n这说明：内层列表还是同一个对象，并没有真正复制",[62,109,110],{"id":110},"深拷贝",[10,112,113,114,117],{},"深拷贝，是指重新分配一块内存，创建一个新的对象，并且将原对象中的元素，以递归的方式，通过创建新的子对象拷贝到新对象中。因此，",[34,115,116],{},"新对象和原对象没有任何关联","。",[42,119,122],{"className":120,"code":121,"language":47,"meta":48},[45],"import copy\n\na = [[1,2],[3,4]]\nb = copy.deepcopy(a)\n",[50,123,121],{"__ignoreMap":48},[10,125,126,127,129,130,132,133,135,136,138],{},"现在",[50,128,85],{"code":85},"是",[50,131,89],{"code":89},",且",[50,134,102],{"code":102},"也是",[50,137,89],{"code":89},"\n说明：内层列表也复制了，完全独立",[20,140,141],{"id":141},"解释型语言和编译型语言",[10,143,144,147],{},[34,145,146],{},"编译型语言","：",[10,149,150,151,154,155,158],{},"通过专门的编译器，把所有源代码",[34,152,153],{},"一次转换","为特定平台的",[34,156,157],{},"可执行文件","，然后再运行。一次编译，多次运行。如C、C++",[10,160,161,162,165,166,169,170,173],{},"优点：一次编译，多次运行；",[34,163,164],{},"脱离编译环境，并且运行效率高","。\n缺点：依靠",[34,167,168],{},"编译器","、",[34,171,172],{},"跨平台性差","、可移植性差。",[175,176,177,189],"ul",{},[178,179,180,181,184,185,188],"li",{},"编译时根据",[34,182,183],{},"对应的运行环境","生成机器码，不同的操作系统之间移植就会有问题，需要根据运行的",[34,186,187],{},"操作系统","环境编译不同的可执行文件。",[178,190,191,192,195,196,117],{},"编译之后如果需要",[34,193,194],{},"修改","就需要整个模块",[34,197,198],{},"重新编译",[10,200,201,147],{},[34,202,203],{},"解释型语言",[10,205,206,207,210,211,214,215,218,219,222],{},"由专门的",[34,208,209],{},"解释器","，根据需要将",[34,212,213],{},"部分源代码","临时转换成特定平台的",[34,216,217],{},"机器码","，然后执行。",[34,220,221],{},"边解释边执行","。比如Python, PHP.",[10,224,225],{},"优点：",[175,227,228,235],{},[178,229,230,231,234],{},"跨平台性好，通过",[34,232,233],{},"不同的解释器","，将相同的源代码解释成不同平台下的机器码。\n缺点：",[178,236,237,117],{},[34,238,239],{},"一边执行一边转换，效率不高",[10,241,242,147],{},[34,243,244],{},"混合型语言",[10,246,247,248,251,252,255,256,117],{},"如Java， C#。兼具执行效率和跨平台性，不直接编译成机器码，需要",[34,249,250],{},"先编译成中间码","（java是编译成字节码），需要",[34,253,254],{},"中间语言运行库","类似java虚拟机(JVM)，",[34,257,258],{},"边解释边运行",[20,260,262],{"id":261},"is和-的区别","is和== 的区别",[10,264,265,129,268,271,272,275,276,279,280,283],{},[50,266,267],{"code":267},"==",[34,269,270],{},"比较操作符","，只是判断对象的",[34,273,274],{},"值","(value)是否一致，而",[50,277,278],{"code":278},"is","判断的是对象之间的身份(内存地址)是否一致。对象的身份可以通过",[50,281,282],{"code":282},"id()","方法来查看",[20,285,286],{"id":286},"os和sys的区别",[10,288,289,292,293,296,297,300],{},[50,290,291],{"code":291},"os","模块是Python标准库中提供的",[34,294,295],{},"与操作系统","交互的模块，提供了",[34,298,299],{},"访问操作系统底层的接口","，里面有很多操作系统的函数。",[10,302,303,306,307,310],{},[50,304,305],{"code":305},"sys","模块负责程序与",[34,308,309],{},"Python解释器","的交互。",[20,312,313],{"id":313},"可变对象和不可变对象",[10,315,316,317,320],{},"在Python中，",[34,318,319],{},"一切皆有对象","，对象必有的三个属性：地址、类型、值",[10,322,323],{},[34,324,325],{},"可变对象",[175,327,328,342,354,357],{},[178,329,330,331,334,335,338,339],{},"当对象的",[34,332,333],{},"值发生变化","，但",[34,336,337],{},"内存地址没有改变","时，则说明是",[34,340,341],{},"可变类型",[178,343,344,345,169,348,169,351],{},"python里的可变对象有：",[34,346,347],{},"列表",[34,349,350],{},"字典",[34,352,353],{},"集合",[178,355,356],{},"引用可变对象时，会创建新的内存地址，当可变对象值发生改变时，原内存地址不会改变",[178,358,359,362,363,366,367,370,371,374],{},[34,360,361],{},"引用传递","主函数向调用函数",[34,364,365],{},"传递的参数","是可变类型时，实际上是将",[34,368,369],{},"实参的引用","传入了调用函数，对引用的操作等于其",[34,372,373],{},"指定的对象","进行操作",[10,376,377],{},[34,378,379],{},"不可变对象",[175,381,382,390,402,417],{},[178,383,330,384,386,387],{},[34,385,333],{},"，但内存地址也发生改变时，则说明是",[34,388,389],{},"不可变类型",[178,391,392,393,169,396,169,399],{},"python里的不可变对象有：",[34,394,395],{},"元组",[34,397,398],{},"字符串",[34,400,401],{},"数值",[178,403,404,405,408,409,412,413,416],{},"python在引用不可变对象时，会寻找",[34,406,407],{},"该对象是否被创建过","，若该对象",[34,410,411],{},"已创建","，则变量会",[34,414,415],{},"直接引用该对象","，不会再申请新的内存空间。",[178,418,419,422,423,426],{},[34,420,421],{},"值传递","主函数向调用函数传递的参数是不可变类型时，实际上只是将",[34,424,425],{},"实参的拷贝","(即临时副本)传递给了被调用函数，并不是实参本身，这样被调函数不能直接修改主调函数中变量的值",[428,429,430],"blockquote",{},[10,431,432,433,436,437,440],{},"注意：如果直接将",[34,434,435],{},"list2 = list1","，那么list1和list2的",[34,438,439],{},"地址会是相同","的。只是换了不同的名称而已。",[20,442,444],{"id":443},"arg和-kwarg作用","* arg和** kwarg作用",[10,446,447],{},"允许在调用函数的时候传入多个实参",[10,449,450,453,454,457,458,461,462],{},[50,451,452],{"code":452},"*arg","会把位置参数转化为",[50,455,456],{"code":456},"tuple",",",[50,459,460],{"code":460},"**kwarg","会把关键字参数转化为",[50,463,464],{"code":464},"dict",[20,466,467],{"id":467},"with如何使用",[10,469,470,473,474,477,478,481],{},[50,471,472],{"code":472},"with","所求值的对象必须有一个",[50,475,476],{"code":476},"enter()","方法，一个",[50,479,480],{"code":480},"exit()","方法",[10,483,484,485,488,489,492,493,496,497,481],{},"with后面的语句被求值后，返回对象的",[50,486,487],{"code":487},"__enter__()","方法被调用，这个方法的",[34,490,491],{},"返回值","将被赋值给",[50,494,495],{"code":495},"as","后面的变量。当with后面的代码块全部被执行完之后，将调用前面返回对象的",[50,498,480],{"code":480},[20,500,502,95,505],{"id":501},"__new__和__init__",[50,503,504],{"code":504},"__new__",[50,506,507],{"code":507},"__init__",[10,509,510,512,513,516,517,519,520,523,524,129,526,529,530,523,533,535,536,117],{},[50,511,507],{"code":507}," 为",[34,514,515],{},"初始化","方法，",[50,518,504],{"code":504},"方法是真正的",[34,521,522],{},"构造函数","。\n",[50,525,504],{"code":504},[34,527,528],{},"实例创建时","被调用，它的任务是创建并返回该实例，是",[34,531,532],{},"静态方法",[50,534,507],{"code":507},"是实例创建之后调用的，然后",[34,537,538],{},"设置对象属性的一些初始值",[10,540,541,543,544,546,547,549,550,552,553,556,557,559],{},[50,542,504],{"code":504},"方法在",[50,545,507],{"code":507},"方法之前被调用，并且",[50,548,504],{"code":504},"方法的返回值将传递给",[50,551,507],{"code":507},"方法作为",[34,554,555],{},"第一个参数","，最后",[50,558,507],{"code":507},"给这个实例设置一些参数",[20,561,562],{"id":562},"装饰器",[10,564,565,566,569,570,573,574,117],{},"Python的装饰器本质上是一个",[34,567,568],{},"嵌套函数","，它接受",[34,571,572],{},"被装饰的函数","(func)作为参数，并",[34,575,576],{},"返回一个包装过的函数",[428,578,579],{},[10,580,581],{},"本质上是一个“接受函数并返回新函数“的函数",[10,583,584,585],{},"作用：",[34,586,587],{},"不修改原函数代码的情况下，给函数额外加功能",[10,589,590,591,169,594,597,598,601,602,605],{},"Python装饰器广泛应用于",[34,592,593],{},"缓存",[34,595,596],{},"权限校验","(如django中的@login_required和@permission_required装饰器)、",[34,599,600],{},"性能测试","(比如统计一段程序的运行时间)和",[34,603,604],{},"插入日志","等应用场景",[10,607,608],{},"比如有个函数：",[42,610,613],{"className":611,"code":612,"language":47,"meta":48},[45],"def func():\n    print(\"我是原函数\")\n",[50,614,612],{"__ignoreMap":48},[10,616,617],{},"现在想：",[175,619,620,623,626],{},[178,621,622],{},"调用前打印“开始”",[178,624,625],{},"调用后打印“结束”\n但：",[178,627,628],{},"不想改 func 内部代码\n于是：",[42,630,633],{"className":631,"code":632,"language":47,"meta":48},[45],"def decorator(fn):\n    def wrapper():\n        print(\"开始\")\n        fn()\n        print(\"结束\")\n    return wrapper\n",[50,634,632],{"__ignoreMap":48},[10,636,637],{},"使用：",[42,639,642],{"className":640,"code":641,"language":47,"meta":48},[45],"func = decorator(func)\nfunc()\n",[50,643,641],{"__ignoreMap":48},[10,645,646,649],{},[34,647,648],{},"@语法糖","：\n为了写着方便：",[42,651,654],{"className":652,"code":653,"language":47,"meta":48},[45],"@decorator\ndef func():\n    print(\"hello\")\n",[50,655,653],{"__ignoreMap":48},[10,657,658],{},"等价于：",[42,660,663],{"className":661,"code":662,"language":47,"meta":48},[45],"def func():\n    print(\"hello\")\n\nfunc = decorator(func)\n",[50,664,662],{"__ignoreMap":48},[20,666,667],{"id":667},"迭代器和生成器",[62,669,670],{"id":670},"可迭代对象",[10,672,673,674],{},"python中一个非常强大的功能，它可以访问容器(字符串、列表、元祖、集合、字典、range)。\n迭代是通过for循环遍历对象中的每一个元素，将元素取出来的过程。所以：",[34,675,676],{},"容器都是可迭代对象",[10,678,679],{},"可迭代对象除了包含常见的序列，还包括迭代器",[62,681,682],{"id":682},"迭代器",[175,684,685,692,702,711],{},[178,686,687,688,691],{},"迭代器是一个可以",[34,689,690],{},"记住遍历的位置","的对象",[178,693,694,695,698,699,117],{},"迭代器对象从集合的",[34,696,697],{},"第一个元素","开始访问，直到所有的元素被访问完结束。迭代器",[34,700,701],{},"只能往前不会后退",[178,703,704,705,95,708],{},"迭代器有两个基本方法：",[50,706,707],{"code":707},"iter()",[50,709,710],{"code":710},"next()",[178,712,713],{},"字符串，列表或元组对象都可用于创建迭代器",[42,715,718],{"className":716,"code":717,"language":47,"meta":48},[45],"list=[1,2,3,4]\nit = iter(list)\nprint(next(it))\n",[50,719,717],{"__ignoreMap":48},[62,721,722],{"id":722},"生成器",[175,724,725,734,740,756,766],{},[178,726,727,728,731,732],{},"在python中，使用了",[50,729,730],{"code":730},"yield","的函数被称为",[34,733,722],{},[178,735,736,737,739],{},"跟普通函数不同的是，生成器是一个返回",[34,738,682],{},"的函数，只能用于迭代操作。",[178,741,742,743,745,746,749,750,752,753],{},"在调用生成器运行的过程中，每次遇到",[50,744,730],{"code":730},"时函数会",[34,747,748],{},"暂停并保存当前所有的运行信息","，返回",[50,751,730],{"code":730},"的值，并在",[34,754,755],{},"下一次执行next()方法时从当前位置继续运行",[178,757,758,759,762,763],{},"在",[34,760,761],{},"调用","生成器函数时，函数体并不执行，只返回一个",[34,764,765],{},"生成器对象",[178,767,768,769,771,772,775,776,779,780],{},"在对",[34,770,765],{},"使用",[34,773,774],{},"next方法","或者",[34,777,778],{},"遍历","的时候，",[34,781,782],{},"生成器函数体才真正执行",[42,784,787],{"className":785,"code":786,"language":47,"meta":48},[45],"def gen():\n    print(\"开始\")\n    yield 1\n\n    print(\"继续\")\n    yield 2\n\n    print(\"结束\")\n    yield 3\n",[50,788,786],{"__ignoreMap":48},[10,790,791],{},"执行:",[42,793,796],{"className":794,"code":795,"language":47,"meta":48},[45],"g = gen()\n\nprint(next(g))\nprint(next(g))\nprint(next(g))\n",[50,797,795],{"__ignoreMap":48},[10,799,800],{},"输出：",[42,802,805],{"className":803,"code":804,"language":47,"meta":48},[45],"开始\n1\n\n继续\n2\n\n结束\n3\n",[50,806,804],{"__ignoreMap":48},[10,808,809],{},"yield：",[42,811,816],{"className":812,"code":814,"language":815,"meta":48},[813],"language-txt","return + 记住返回位置\n","txt",[50,817,814],{"__ignoreMap":48},[10,819,820,821,824,825,827],{},"普通",[50,822,823],{"code":823},"return","：\n返回后函数直接结束\n",[50,826,730],{"code":730},":",[175,829,830,832,835],{},[178,831,491],{},[178,833,834],{},"函数没有结束",[178,836,837],{},"下次还能从原位置继续",[20,839,841],{"id":840},"filter-map-reduce","filter map reduce",[10,843,844,847,848,851,852,854,855,857,858],{},[50,845,846],{"code":846},"filter","函数用于",[34,849,850],{},"过滤序列","，接收一个函数和一个序列，把函数作用于序列的每个元素上，然后根据返回值是",[50,853,106],{"code":106},"还是",[50,856,89],{"code":89},"决定",[34,859,860],{},"保留还是丢弃该元素",[42,862,865],{"className":863,"code":864,"language":47,"meta":48},[45],"mylist = list(range(10))\nlist(filter(lambda x: x % 2 == 1, mylist))\n[1, 3, 5, 7, 9]\n",[50,866,864],{"__ignoreMap":48},[10,868,869,872,873,876],{},[34,870,871],{},"map","函数传入一个函数和一个序列，并把",[34,874,875],{},"函数作用到序列的每个元素上","，返回一个可迭代对象。",[42,878,881],{"className":879,"code":880,"language":47,"meta":48},[45],"list(map(lambda x: x % 2, mylist))\n[1, 0, 1, 0, 1, 0, 1, 0, 1]\n",[50,882,880],{"__ignoreMap":48},[10,884,885,847,888,891,892,117],{},[34,886,887],{},"reduce",[34,889,890],{},"递归计算","，同样需要传入一个函数和一个序列，并",[34,893,894],{},"把函数和序列元素的计算结果与下一个元素进行计算",[42,896,899],{"className":897,"code":898,"language":47,"meta":48},[45],"from functools import reduce\nreduce(lambda x, y: x + y, range(101))\n5050\n",[50,900,898],{"__ignoreMap":48},[20,902,904],{"id":903},"全局变量-局部变量-闭包","全局变量 局部变量 闭包",[10,906,907,908,911,912,915,916,919],{},"在函数定义的变量为",[34,909,910],{},"全局变量","。全局变量可以在函数中直接进行访问，但是在",[34,913,914],{},"修改全局变量","时，为了避免与局部变量产生混淆，需要先加上",[34,917,918],{},"global","声明，然后再修改。",[10,921,922,923,926,927,930,931,934,935,937,938,941,942,945],{},"闭包是Python编程一个非常重要的概念，如果一个",[34,924,925],{},"外函数","中定义一个",[34,928,929],{},"内函数","，且",[34,932,933],{},"内函数体内引用到了体外的变量","，这时外函数通过",[50,936,823],{"code":823},"返回",[34,939,940],{},"内函数的引用","时，会把",[34,943,944],{},"定义时涉及到的外部引用变量和内函数打包成一个整体(闭包)"," 返回。",[10,947,948],{},"闭包=函数＋它记住的外部变量",[10,950,73],{},[42,952,955],{"className":953,"code":954,"language":47,"meta":48},[45],"def outer():\n    x = 10\n    def inner():\n        print(x)\n    return inner\n",[50,956,954],{"__ignoreMap":48},[10,958,959],{},"执行：",[42,961,964],{"className":962,"code":963,"language":47,"meta":48},[45],"f = outer()\n",[50,965,963],{"__ignoreMap":48},[10,967,968,969,972],{},"注意：\n这里",[50,970,971],{"code":971},"outer","已经执行结束了\n正常来说：",[42,974,977],{"className":975,"code":976,"language":47,"meta":48},[45],"x = 10\n",[50,978,976],{"__ignoreMap":48},[10,980,981],{},"这个变量应该没了。\n但：",[42,983,988],{"className":984,"code":986,"language":987},[985],"language-text","f()\n","text",[50,989,986],{"__ignoreMap":48},[10,991,992],{},"还能输出10\n这就是闭包",[42,994,997],{"className":995,"code":996,"language":47,"meta":48},[45],"lst =[lambda x： x*i for i in range(4)]\nres = [m(2) for m in lst]\nprint(res)\n",[50,998,996],{"__ignoreMap":48},[10,1000,1001,1002,1005,1006],{},"预期的结果为：",[50,1003,1004],{"code":1004},"[0,2,4,6]","\n实际输出为：",[50,1007,1008],{"code":1008},"[6,6,6,6]",[10,1010,1011],{},"这个为什么叫闭包？",[10,1013,1014],{},"因为",[42,1016,1019],{"className":1017,"code":1018,"language":47,"meta":48},[45],"lambda x:x*i\n",[50,1020,1018],{"__ignoreMap":48},[10,1022,1023,1024,1027,1028],{},"这个lambda用到了自己",[34,1025,1026],{},"函数体外","的变量",[50,1029,1030],{"code":1030},"i",[10,1032,1033,1034,1037,1038,1041],{},"即内函数：",[50,1035,1036],{"code":1036},"lambda","，外部作用域：",[50,1039,1040],{"code":1040},"for","循环所在作用域",[20,1043,1044],{"id":1044},"匿名函数",[10,1046,1047,1048,1050,1051,1053,1054,1056],{},"匿名函数的关键字为",[50,1049,1036],{"code":1036},"，表现形式为",[50,1052,1036],{"code":1036}," 参数：返回值，",[50,1055,1036],{"code":1036},"后面的参数就是函数的形参，冒号后面的表达式就是返回值。",[10,1058,1059,1061],{},[50,1060,1036],{"code":1036},"表达式的意义：",[175,1063,1064,1071],{},[178,1065,1066,1067,1070],{},"对于",[34,1068,1069],{},"只有一行","的函数，使用此方式可以省去定义函数的过程，使代码简洁明了；",[178,1072,1066,1073,1076],{},[34,1074,1075],{},"不需要重复使用","的函数，此方式可以在用完之后，立即释放，提高程序执行性能",[20,1078,1079],{"id":1079},"垃圾回收机制",[10,1081,1082],{},[34,1083,1084],{},"引用计数(主要手段)+标记清除(辅助)+分代回收(辅助)",[10,1086,1087,1088],{},"1、",[34,1089,1090],{},"引用计数",[10,1092,1093,1094,1097,1098,1101,1102,1105],{},"在Python中，使用了引用计数这一技术来实现内存管理，一个对象被创建完成后就",[34,1095,1096],{},"有一个变量指向这个对象","，那么就这个对象的引用计数为1，以后如果有",[34,1099,1100],{},"其他变量指向这个对象","，其引用计数也会相应增加，如果",[34,1103,1104],{},"一个变量不再执行这个对象","，那么这个对象的引用计数减1。如果一个对象没有任何变量指向这个对象，也即引用计数为0，那么这个对象就会被python回收。",[10,1107,225],{},[175,1109,1110,1113,1120,1123,1126,1129],{},[178,1111,1112],{},"高效。",[178,1114,1115,1116,1119],{},"运行期没有停顿。可以类比一下Ruby的垃圾回收机制，也就是",[34,1117,1118],{},"实时性","：一旦没有引用，内存就直接释放了。不用像其他机制等到特定时机。实时性还带来一个好处：处理回收内存的时间分摊到了平时。",[178,1121,1122],{},"对象有确定的生命周期。",[178,1124,1125],{},"易于实现。\n缺点：",[178,1127,1128],{},"维护引用计数消耗资源，维护引用计数的次数和引用赋值成正比。",[178,1130,1131,1132,1135,1136,95,1138,1140,1141,1143,1144,1140,1146,1148,1149,1151,1152],{},"无法解决",[34,1133,1134],{},"循环引用","的问题。比如现在有两个对象分别为",[50,1137,14],{"code":14},[50,1139,98],{"code":98},"，",[50,1142,14],{"code":14},"指向了",[50,1145,98],{"code":98},[50,1147,98],{"code":98},"又指向了",[50,1150,14],{"code":14},"，那么他们两的引用计数永远都不会为0。也即永远得不到回收。\n2、",[34,1153,1154],{},"标记清除",[10,1156,1157,1158,1160],{},"针对",[34,1159,1134],{},"的情况，python引入标记清除算法。",[10,1162,1163,1165],{},[34,1164,1154],{},"算法是一种基于追踪回收技术实现的垃圾回收算法。它分为两个阶段",[175,1167,1168,1179],{},[178,1169,1170,1171,1174,1175,1178],{},"第一阶段是",[34,1172,1173],{},"标记阶段","，GC会把",[34,1176,1177],{},"所有的活动对象","打上标记",[178,1180,1181,1182,691,1185,1188],{},"第二阶段是把那些",[34,1183,1184],{},"没有标记",[34,1186,1187],{},"非活动对象","进行回收。\n3、分代回收",[10,1190,1191],{},"分代回收是建立在标记清除技术基础之上的。是一种以时间换空间的操作方式。",[10,1193,1194,1195,1198,1199,1202,1203,1206,1207,1210,1211,1214,1215,1218,1219,1222],{},"Python将内存根据",[34,1196,1197],{},"对象的存活时间","划分为不同的集合，每个集合称为一“代”, Python将内存分为了3“代”，分别为",[34,1200,1201],{},"年轻代","(第0代)、",[34,1204,1205],{},"中年代","(第1代)、",[34,1208,1209],{},"老年代","(第2代)，他们对应的是3个链表，它们的",[34,1212,1213],{},"垃圾收集频率与对象的存活时间的增大而减小","。新创建的对象都会分配在年轻代，",[34,1216,1217],{},"年轻代链表的总数达到上限时，Python垃圾回收机制就会被触发","，把那些可以被回收的对象回收掉，而",[34,1220,1221],{},"那些不会回收的对象就会被移到中年代去","，依此类推，老年代中的对象是存活时间最久的对象，甚至是存活于整个系统的生命周期内。",[20,1224,1225],{"id":1225},"协程",[10,1227,1228],{},"协程本质上是：",[428,1230,1231],{},[10,1232,1233],{},"一个可以主动暂停、以后再继续执行的函数",[10,1235,1236],{},"普通函数：",[175,1238,1239,1242,1245,1248],{},[178,1240,1241],{},"一路执行到底",[178,1243,1244],{},"不能中途挂起\n协程：",[178,1246,1247],{},"执行到一半可以暂停",[178,1249,1250],{},"之后还能从原位置恢复",[10,1252,1253],{},"协程的核心作用：",[428,1255,1256],{},[10,1257,1258],{},"提高IO密集型程序的执行效率",[10,1260,1261],{},"常见的IO操作：",[175,1263,1264,1267],{},[178,1265,1266],{},"网络请求",[178,1268,1269],{},"数据库查询",[10,1271,1272],{},"协程的思想：",[42,1274,1277],{"className":1275,"code":1276,"language":815,"meta":48},[813],"等待的时候，让CPU去执行别的任务\n",[50,1278,1276],{"__ignoreMap":48},[10,1280,1281],{},"如何定义协程？\nPython使用：",[42,1283,1286],{"className":1284,"code":1285,"language":47,"meta":48},[45],"async def\n",[50,1287,1285],{"__ignoreMap":48},[10,1289,1290],{},"定义协程函数",[10,1292,73],{},[42,1294,1297],{"className":1295,"code":1296,"language":47,"meta":48},[45],"async def test():\n    print(\"hello\")\n",[50,1298,1296],{"__ignoreMap":48},[10,1300,1301],{},"调用async函数不会立即执行，而是返回一个协程对象",[62,1303,1304],{"id":1304},"await的作用",[42,1306,1309],{"className":1307,"code":1308,"language":47,"meta":48},[45],"await 某个耗时操作\n",[50,1310,1308],{"__ignoreMap":48},[10,1312,1313],{},"表示：",[428,1315,1316],{},[10,1317,1318],{},"当前协程先暂停，去执行别的协程",[62,1320,1321],{"id":1321},"asyncio",[10,1323,1324,1326],{},[50,1325,1321],{"code":1321},"是Python的协程调度框架\n作用：",[175,1328,1329,1332,1335],{},[178,1330,1331],{},"管理协程",[178,1333,1334],{},"调度协程",[178,1336,1337],{},"控制暂停与恢复",[62,1339,1341],{"id":1340},"asynciorun","asyncio.run()",[10,1343,584],{},[42,1345,1348],{"className":1346,"code":1347,"language":47,"meta":48},[45],"asyncio.run(main())\n",[50,1349,1347],{"__ignoreMap":48},[10,1351,1352],{},"用于：",[175,1354,1355,1358],{},[178,1356,1357],{},"启动事件循环",[178,1359,1360],{},"执行协程",[10,1362,1363],{},"协程通常是单线程的任务切换，不是多个线程同时运行",{"title":48,"searchDepth":1365,"depth":1365,"links":1366},4,[1367,1369,1373,1374,1375,1376,1377,1378,1379,1380,1381,1386,1387,1388,1389,1390],{"id":22,"depth":1368,"text":23},3,{"id":29,"depth":1368,"text":30,"children":1370},[1371,1372],{"id":64,"depth":1365,"text":64},{"id":110,"depth":1365,"text":110},{"id":141,"depth":1368,"text":141},{"id":261,"depth":1368,"text":262},{"id":286,"depth":1368,"text":286},{"id":313,"depth":1368,"text":313},{"id":443,"depth":1368,"text":444},{"id":467,"depth":1368,"text":467},{"id":501,"depth":1368,"text":501},{"id":562,"depth":1368,"text":562},{"id":667,"depth":1368,"text":667,"children":1382},[1383,1384,1385],{"id":670,"depth":1365,"text":670},{"id":682,"depth":1365,"text":682},{"id":722,"depth":1365,"text":722},{"id":840,"depth":1368,"text":841},{"id":903,"depth":1368,"text":904},{"id":1044,"depth":1368,"text":1044},{"id":1079,"depth":1368,"text":1079},{"id":1225,"depth":1368,"text":1225,"children":1391},[1392,1393,1394],{"id":1304,"depth":1365,"text":1304},{"id":1321,"depth":1365,"text":1321},{"id":1340,"depth":1365,"text":1341},[1396],"复习","2026-05-21 11:20:00","Python八股自用",false,"md","https://assets.yangzy.top/python_essay.webp",{},true,"/2026/python_essay",{"text":1406,"minutes":1407,"time":1408,"words":1409},"19 min read",18.325,1099500,3665,null,{"title":5,"description":1398},{"loc":1404},"posts/2026/python_essay",[1415],"Python","x40NBCBGEWyENaWQB2SEG93nj5GcpTyYo_7wl8fLAo4",[1418,1410],{"title":1419,"path":1420,"stem":1421,"date":1422,"type":1410,"children":-1},"反向SSH内网服务器远程连接","/2026/ssh","posts/2026/ssh","2026-03-01 16:33:42",1779367926617]