Python工程化入门:面向对象、文件读写与异常处理实战笔记
1. 学习笔记三走出语法舒适区开始接触真正工程化的 Python进入这套 100 天学习路线图的第三阶段最大的感受是前面几章还停留在认识 Python的层面到了这一部分才真正开始用 Python 写东西。如果你和我一样前两个阶段啃完了变量、分支、循环、列表、字典、函数这些基础语法那么这一部分的内容会帮你把零散的知识点串成一条线你会发现原来编程不是记住语法而是组织思路。这一阶段的核心主题包括面向对象编程OOP、文件读写、异常处理以及几块真正工程化的实战内容。说白了前两个阶段你在学习怎么把话说清楚从这一阶段开始你在学习怎么把一件事完整地做成。从整条 100 天路线来看这部分也是很多人最容易放弃的一道坎因为面向对象的抽象思维、文件 IO 的编码细节、异常处理的边界情况稍微一个环节没想明白后面的项目练习就会卡壳。这套笔记适合三类人一是像我这样跟着 100 天路线走的自学者二是已经学过基础语法、但写代码依然停留在脚本拼凑阶段的人三是准备转向 Python 开发岗或者需要拿 Python 做数据处理但总被代码结构困扰的从业者。不管你是哪一类我的建议是这一阶段的内容不要急着三天内刷完每一节都要动手敲、动手改、动手拆。2. 这一阶段在整条学习路线里的定位从看懂到能写2.1 前两个阶段与第三阶段的边界在哪里如果你回头翻前面两个阶段的笔记会发现内容集中在算术运算、字符串操作、流程控制、函数定义和常用数据结构。那些内容有一个共同特点它们是零件彼此之间没有严格的依赖关系你完全可以单独理解一个列表推导式而不需要知道它在一个完整项目里怎么用。到了第三阶段知识的组织方式发生了根本变化。类与对象、文件读写、异常机制这三块内容都是围绕多个部件如何协作展开的。以类为例你定义了一个用户类它包含用户名、密码、状态这些属性也包含登录、登出这些方法。这个类本身没什么用但当你在一个程序里创建多个用户对象、把这些对象放进列表、再配合文件持久化保存时类与 IO 就拧在了一起。前面学过的函数和数据结构仍然是基础从这一阶段开始它们成了搭建复杂系统的积木。2.2 为什么第三阶段是分水岭我见过不少学习者前两个阶段进展神速每天能刷好几章碰到第三阶段突然就停下来了。停下来的原因几乎一致不是内容变难而是练习变重了。前两个阶段的练习题比如将一个字符串反转或统计列表中重复元素的个数都是十几行代码能解决的问题。第三阶段的练习往往是编写一个图书管理系统写一个 ATM 机模拟程序这类需要几十上百行代码的小型项目。这带来的冲击不只是工作量更是思维模式的转变。写反转字符串时你只需要考虑输入和输出写图书管理系统时你必须考虑数据结构怎么组织、操作流程怎么设计、用户输入错了怎么办。这种全局设计的意识在前两个阶段是不需要的但它是真实开发的常态。第三阶段就是在帮你建立这种意识所以千万不要跳过项目练习直接去看后面的内容。2.3 何时学这部分内容最合适说实话很多人都掉进过一个坑基础语法还没完全消化就急着看面向对象结果被self和__init__搞得头晕然后怀疑自己不适合编程。如果你现在正处于这种状态往回退一退先确保自己能在不看资料的情况下独立写出函数、处理列表和字典再来闯这一关。反过来如果你已经能写出给一个文本文件统计里面每个单词出现次数这类程序但代码全部塞在一个大while循环里不知道该怎么组织、怎么扩展那第三阶段正适合你。这一阶段的最终目标就是让你具备把一个几十行的脚本改造成一个有结构、可维护的小型程序的能力。3. 面向对象编程用角色建模的思维替代流水账式的代码3.1 类与对象的本质把数据和操作打包在一起面向对象的概念网上教程说得天花乱坠什么封装、继承、多态名词一个接一个。但我在实际学习中体会最深的一点是类的本质是把数据和操作这些数据的函数打包成一个整体。举个例子没有面向对象时描述一个学生的信息你得维护一个字典student1 {name: 张三, score: 85, level: B}如果要对学生进行升级操作就得写一个函数def upgrade(student): if student[score] 90: student[level] A问题在于student字典和upgrade函数之间没有强制绑定关系你完全可能在一个不相关的函数里误改了level字段。而用类来写数据和操作被天然地放在一起class Student: def __init__(self, name, score): self.name name self.score score self.level B def upgrade(self): if self.score 90: self.level A你可能会觉得这不就是把字典换成类了吗有什么区别。区别在于思维模型。字典是被动的容器你需要记住哪个函数操作它类是有行为的主体它自己知道怎么处理自己的数据。当系统中的实体变多、实体之间的交互变复杂时这种主动性的优势会被迅速放大。3.2 理解self是第一道门槛第三阶段最劝退人的点大概就是__init__和self。我自己第一次看的时候也很懵为什么每个方法的第一个参数都是self而且手动调用时又不需要传这个参数这里可以用一个生活化的类比来理解。你有一张表单模板类需要用它给不同的客户对象生成合同。每当调用模板生成一份合同时模板得知道我这次是在给谁生成这个谁就是self。当你写student1.upgrade()时Python 会自动把student1当作第一个参数传给upgrade所以在方法定义里必须留出一个位置接收它这就是self。一些教学材料经常纠结于这个参数是不是必须叫 self其实没有强制要求你叫this也可以。但 99% 的 Python 代码都约定俗成用self建议不要标新立异免得别人看得费劲也免得工具链的代码检查报一堆警告。3.3 写一个带项目感的例子图书借阅系统第三阶段的项目练习我做得最完整的是一个超级简单的图书借阅系统。当时跟着路线图要求自己动手用类重新实现了一遍过程很有收获这里把核心结构分享一下也附上我踩过的坑。先用类描述图书class Book: def __init__(self, book_id, title, author, count1): self.book_id book_id self.title title self.author author self.count count self.borrowed_count 0 def borrow(self): if self.count - self.borrowed_count 0: raise ValueError(f图书《{self.title}》库存不足) self.borrowed_count 1 def return_book(self): if self.borrowed_count 0: raise ValueError(归还数量超出借出数量) self.borrowed_count - 1 property def available_count(self): return self.count - self.borrowed_count再定义一个图书馆类来管理这些图书class Library: def __init__(self): self.books [] def add_book(self, book: Book): self.books.append(book) def search_by_title(self, keyword: str): return [book for book in self.books if keyword in book.title]当时我把borrow_count借出数量和count总数量都定义成普通变量结果在操作时直接导致库存逻辑混乱。后来才体会到一个类内部的状态如果有不能为负不能超过总量这类约束最好把修改入口收敛到方法里通过方法内的if判断来保证约束。这就是封装的实际意义不是为了好看而是为了不让外部调用者胡乱改动内部状态。3.4 类变量与实例变量的区别踩过的一次隐形坑初学类的时候很多人都会栽在类变量和实例变量的区分上。看代码class Employee: company 某科技有限公司 # 类变量 count 0 # 类变量 def __init__(self, name): self.name name # 实例变量 Employee.count 1类变量是被所有实例共享的实例变量是每个对象自己独有的。实操中我犯过一个典型错误把可变对象当类变量用然后某天发现所有实例都互相影响。比如class Task: tags [] # 危险写法 def __init__(self, name): self.name name当你执行task1.tags.append(urgent)时task2.tags也会多出这个标签因为tags是类级别的列表所有实例共享同一个列表对象。如果想让每个任务实例拥有独立的标签列表必须在__init__里写self.tags []。这个差异不自己动手踩一回很难留下深刻印象。3.5 继承与多态先学会用再理解为什么100 天路线的这一阶段会把继承封装好地讲一遍。我在学习中的建议是第一遍不用纠结设计模式层面的为什么用继承先学会基本的使用方法子类通过class Child(Parent)继承父类的方法和属性通过super().__init__(...)调用父类构造器。一个经典的练习题是图形面积计算。定义基类Shape子类Rectangle和Circle各自实现area()方法。这个练习的价值在于它展示了多态的意义你不必关心某个对象具体是哪种图形只需要知道它一定有area()方法就可以统一处理。class Shape: def area(self): raise NotImplementedError class Rectangle(Shape): def __init__(self, width, height): self.width width self.height height def area(self): return self.width * self.height class Circle(Shape): def __init__(self, radius): self.radius radius def area(self): return 3.14159 * self.radius ** 2这种写法的好处是当你增加一个Triangle类时不需要修改任何调用方的代码调用方只需要知道它在调用一个有area()方法的对象。这在工作中的直接受益就是可扩展性加需求时改动量最小。4. 文件读写与数据持久化把程序的内存世界落到硬盘上4.1 读写文件的基础套路前两个阶段敲的代码运行完就消失了因为数据都存在内存里。到了第三阶段开始涉及文件读写程序与程序之间、程序与用户之间的数据交换才真正打通。最简单的基础写法大家都见过可我还是建议不要跳过用自己的话复述一遍# 打开文件读取全部内容 with open(data.txt, r, encodingutf-8) as f: content f.read() # 逐行读取 with open(data.txt, r, encodingutf-8) as f: for line in f: print(line.strip())这里有几个细节值得单独说一下。encodingutf-8在很多人看来是可写可不写的参数但如果你在 Windows 上处理中文文件不指定编码会默认使用系统编码比如 GBK轻则中文乱码重则抛UnicodeDecodeError。所以我的习惯是只要读写文本文件一律显式指定utf-8。这样跨平台、跨机器时行为是可预期的。另一个细节是with语句。很多老教程还在用f open(...)然后手动f.close()。一旦你在read之前触发了异常close就不会执行文件句柄就泄漏了。with语句会在代码块结束后自动关闭文件不管中途有没有异常这是 Python 里最推荐的文件处理方式。4.2 编码迷思为什么我的中文读出乱码乱码问题排在文件操作新手谜团第一名。核心原因并不复杂文件在磁盘上存储的是字节序列用什么编码写入就要用什么编码读取。用utf-8写入的你好和用gbk解析它得到的就是另一堆字符。实操中我建议把编码问题当作契约来管理如果这个文件是你自己创建的那么写入和读取时指定同一个编码如果是外部拿到的文件先用记事本或其他工具查看编码格式再在代码里匹配。还有一个小技巧读取时如果实在不确定编码可以试试errorsreplace参数把无法解码的字节替换为特殊字符至少能保证程序不崩溃但这不是长久之计。4.3 CSV 文件处理中的看不见的坑100 天路线图在文件操作阶段一定会安排 CSV 文件的练习。CSV 看似简单但实际处理时有个经典问题字段里如果包含逗号或换行怎么办标准库csv模块就是为了解决这类问题而存在的所以尽量别用split(,)去解析 CSV。我用一个导出联系人列表的场景来示范import csv contacts [ {name: 李雷, phone: 13800001111, note: 外号,小李}, {name: 韩梅梅, phone: 13900002222, note: 备注里有\n换行} ] with open(contacts.csv, w, encodingutf-8, newline) as f: writer csv.DictWriter(f, fieldnames[name, phone, note]) writer.writeheader() writer.writerows(contacts)注意写入时的newline参数如果不设置Windows 下会在行尾出现多余的空行。这个坑几乎每个人都会踩一遍我现在每次写 CSV 都条件反射地加上它。4.4 JSON 序列化Python 字典与外部世界的桥梁JSON 比 CSV 更适合表达嵌套结构。把 Python 的列表、字典结构保存为 JSON 文件是项目开发里最常见的操作之一。基础的json.dump()和json.load()对应写入和读取这里我想分享一个实际项目里会很常用的增强写法。假设你的程序里有一批自定义对象直接json.dump会报错因为 JSON 没法序列化自定义对象。解决办法是给dump传入default参数用函数把对象转成字典import json class Person: def __init__(self, name, age): self.name name self.age age def to_dict(self): return {name: self.name, age: self.age} p Person(周杰, 25) with open(person.json, w, encodingutf-8) as f: json.dump(p, f, ensure_asciiFalse, defaultlambda obj: obj.to_dict())这里ensure_asciiFalse也很关键。默认值是ensure_asciiTrue写入的中文会被转成\uXXXX形式的转义序列文件可读性瞬间变差。不指定这个参数虽然读回来数据一样但中途调试时很难受。4.5 文件读写实战统计日志文件中的错误码分布这段是我部分实践过程中留下最深印象的一个练习模拟一个简单的日志系统文件中每一行是一条日志格式为时间,错误级别,信息。我们要统计各级别的数量。from collections import Counter def count_log_levels(log_path): level_counter Counter() with open(log_path, r, encodingutf-8) as f: for line in f: parts line.strip().split(,) if len(parts) 2: level parts[1].strip() level_counter[level] 1 return level_counter # 使用示例 levels count_log_levels(app.log) print(levels.get(ERROR, 0))这个练习看上去平淡但把迭代读取、字符串处理、数据结构统计串起来了是第三阶段很好的综合训练。做完之后你会意识到所谓编程能力不在于会不会某个单独语法而在于能否把一个原始的需求拆解成打开文件、逐行解析、聚合统计这样环环相扣的步骤。5. 异常处理不是出了错再补救而是提前预设所有意外5.1 理解异常传播机制异常处理绝不只是写几个try...except那么简单。我在第三阶段最大的领悟是异常是从底层函数一层层往外传播的。一个函数内部抛出异常调用它的代码如果没有捕获异常就继续往上抛直到某层捕获或者程序崩溃。这个传播机制用一个小例子就能说清def func_a(): return func_b() def func_b(): return func_c() def func_c(): raise ValueError(底层出错了) try: func_a() except ValueError as e: print(f在最外层捕获异常: {e})func_c抛出的异常会经过func_b和func_a最终被最外层的try捕获。理解这个机制后你会发现一个设计原则异常应该在有能力处理它的地方被捕获而不是在最底层就直接吞掉。5.2 常见的错误空异常块、过宽的 except、忘记 finally新手最容易犯的三个错误我几乎照单全收地犯过一遍。第一个是捕获了异常却什么都不做try: num int(input(请输入数字: )) except ValueError: pass # 坚决不要这样写这样写最大的问题是出现异常后程序继续走但num可能根本没被定义下一行代码使用num时又要报一个NameError排查起来特别浪费时间。至少也要在 except 里用print输出一条提示或者用log记录。第二个是过宽地使用except Exception捕获所有异常。这会让程序在真正有 bug 时静默继续运行问题被掩盖。经验法则是知道可能抛什么异常就捕获什么异常比如int()抛ValueError文件操作抛IOError等。实在不确定时先精确捕获已知异常再决定是否添加兜底分支。第三个是忘了finally。如果你在文件读写或网络连接这类场景里使用了try即使异常发生了也要完成清理动作就把清理动作放到finally里。不过在 Python 的上下文管理器with普及之后很多清理动作可以用with取代finally这也是推荐的做法。5.3 自定义异常给你的项目一个清晰的错误信号在稍大一点的项目里内置异常类型往往不够表达业务语义。比如借阅系统里库存不足和书籍不存在都是业务错误用内置的ValueError去区分不够直观。更好的做法是自定义异常class BookNotFoundError(Exception): pass class InsufficientStockError(Exception): pass然后在入库或借阅时按场景抛出对应的异常调用方就能根据异常类型做出不同的处理。虽然现阶段自定义异常看起来像多此一举但当你参与了稍大规模的项目协作别人看到BookNotFoundError比看到Exception能更快定位问题。5.4 用异常而非返回值来传达失败这一阶段还有一个比较隐蔽的设计理念什么情况下该用返回值表示失败什么情况下该抛异常我的体会是如果某个操作的结果本身就是可能为空的用返回值更合适比如查找一个不存在的词条返回None如果操作过程中出现了程序无法继续运行的条件则应该抛异常比如依赖的配置文件缺失。这个边界虽然并不绝对但站在可读性的角度上它能让代码意图更明确。你调用一个函数看到它返回None你会觉得结果不存在看到它抛出ConfigMissingError你会立刻意识到环境有问题。异常不是程序的敌人它是程序在说人话。6. 项目实战的迁移过程从能跑到能改6.1 一个完整的综合练习命令行通讯录第三阶段最适合作为里程碑的练习是一个命令行通讯录程序支持添加联系人、删除联系人、查找联系人、列出所有联系人并且数据要能持久化保存到 JSON 文件。我完成这个练习时的代码结构大概是这样的定义Contact类包含姓名、电话、备注定义AddressBook类负责管理联系人列表并提供add、remove、search、save、load方法在主程序中提供命令行菜单循环读取用户指令核心部分的骨架import json class Contact: def __init__(self, name, phone, note): self.name name self.phone phone self.note note class AddressBook: def __init__(self): self.contacts [] self.file_path contacts.json def add(self, contact: Contact): self.contacts.append(contact) def search(self, keyword: str): return [c for c in self.contacts if keyword in c.name or keyword in c.phone] def save(self): data [{name: c.name, phone: c.phone, note: c.note} for c in self.contacts] with open(self.file_path, w, encodingutf-8) as f: json.dump(data, f, ensure_asciiFalse, indent2) def load(self): try: with open(self.file_path, r, encodingutf-8) as f: data json.load(f) self.contacts [Contact(**item) for item in data] except FileNotFoundError: print(通讯录文件不存在将创建新文件。)写完后我反复改了两三版。第一版是纯脚本所有逻辑堆在一个while True循环里改一个功能就要动一大片代码。第二版把Contact和AddressBook抽出来后主程序只剩菜单和输入输出清爽很多。这个对比本身就是极好的教学素材抽象不是为了炫技而是为了让代码的年久失修来得晚一些。6.2 应该测试哪些边界情况练习做完以后不要急着进入下一章。我自己的习惯是拿几个边界情况试一试这一步在第三阶段尤其重要因为这一阶段的代码开始涉及状态和外部资源你养的虫子也会突然变多。拿着上面这个通讯录至少要考虑这些情况通讯录文件不存在时load会不会崩联系人里有中文名字时保存后的 JSON 文件里中文会不会变成乱码搜索时输入空字符串程序会不会进入死循环连续添加多个联系人后再启动程序能不能正确恢复之前的数据如果 JSON 文件被用户手改成了非法格式load会不会报出让人费解的堆栈我实际测下来的结果是第四、五两个问题最容易暴露隐患尤其是 JSON 文件格式被破坏的情况如果没有对json.JSONDecodeError做处理程序会直接堆栈报错。这些测试经验在后续学习爬虫、Web 开发时都非常有用因为你面对的不再是完美的代码环境而是真实世界里各种不规则输入。6.3 从这个小项目延伸出去的进阶方向如果你做完通讯录觉得意犹未尽可以尝试给这个练习打几个补丁这比直接翻到下一个章节更有效果第一增加分组支持。每个联系人可以属于多个分组分组信息也存到 JSON 里搜索时支持按组筛选。这样你可以练习更复杂的对象关系和嵌套数据结构。第二把数据存储换成 SQLite体验一下程序要把对象数据放入关系型数据库的转换过程。这一步可能过早但如果你有数据库基础完全可以试试。第三把命令行交互改成一个简单的菜单界面。这听起来简单实际操作时你会发现无限循环等待输入的设计和事件驱动的差异这个体验非常宝贵。7. 第三阶段常见问题与排查技巧实录7.1 我们最常撞上的几个报错与解决思路这一阶段报错的频率会显著超过前两个阶段主要是因为错误不再只和语法相关还和运行环境、外部文件、对象状态相关。我把最常见的几类错误整理成速查表。报错原生信息大概率原因排查思路NameError: name self is not defined在方法里忘了写self参数或调用私有属性时写错了作用域检查方法定义第一行是否有selfTypeError: __init__() takes 1 positional argument but 2 were given创建对象时传的参数与__init__方法定义不一致逐一对齐构造器参数列表AttributeError: NoneType object has no attribute xxx某个函数返回了None但调用方没有检查就继续用返回值在可能出现None的地方打印调试UnicodeDecodeError读取文件时用了错误的编码检查原始文件的编码格式显式指定encodingjson.JSONDecodeError读取的 JSON 文件格式非法用格式化工具检查 JSON 文件内容ValueError: could not convert string to float字符串转换数值时格式异常打印出原始字符串确认是否有空白或符号这里想强调一点报错信息是程序给我们的第一条线索不要一看英文报错就直接复制去搜索答案。先自己读一遍报错信息通常里面已经包含文件在哪一行哪个对象找不到哪个类型不匹配带着这些精确信息去排查效率远高于盲目搜索。7.2 我踩过的一个隐形状态坑在对象方法的协作中最容易出现的逻辑错误不是语法错误而是对象内部状态没有按预期更新。举例来说我写图书借阅系统时一开始在borrow方法里忘了更新borrowed_count字段结果程序不报任何错误但反复借同一本书 100 次都不触发库存不足的提示。这类问题特别隐蔽因为代码能运行、调用也正常就是结果不对。我的排查经验是在关键方法里临时加print(self.borrowed_count)这类调试语句观察状态变化是否符合预期。很多时候我们觉得 bug 难找是因为我们把程序没报错和程序正确画了等号这两者之间其实差着十万八千里。7.3 用最简单的调试方法解决最复杂的问题到这一阶段很多人开始接触各种调试工具。我很想提醒一句在 100 天路线的这个阶段用print大法即可不要急着上复杂的调试器或自动化测试框架。不是说那些工具没用而是当你对程序的控制流还不够敏感时过早引入工具反而会干扰判断。我自己的调试步骤如下至今仍然受用先确认报错信息来自哪一行用print打印该行相关的变量。如果运行结果不正确但不报错优先检查对象状态变化打印对象的所有关键属性。缩小范围注释掉一小部分逻辑只保留核心路径运行后看结果是否符合预期。用二分法定位在程序中间位置打印一个标记确认前半段是否正确。这一套朴素的方法在面对这个阶段的绝大多数问题时都非常有效。等到你进阶到并发和网络编程再学习专业的调试工具也不迟。8. 这一阶段学完之后可以回头看但别忘了前进第三阶段的内容体量比我预想的大难度也不是线性上升而是存在几个明显的跳跃点尤其是面向对象的抽象设计。但跟着练完两个综合项目后我确实清楚地感觉到自己对程序如何构建的理解上了一个台阶。有个小建议分享给你学完这一阶段先别急着进入下一章回头把自己第一阶段写的简单脚本翻出来用面向对象和异常处理的知识重构一遍。你会发现原来有些代码可以组织得如此简洁也会发现自己在不知不觉中已经建立了先设计再写代码的意识。从 100 天整体规划来看第三阶段是承前启后的核心环节。基础语法提供了表达的能力这个阶段补上了组织代码的能力这两样东西合在一起才能撑起后面那些涉及算法、爬虫、数据处理和 Web 开发的复杂内容。我在实际学习中还有一个体会不要怕在这里多花时间因为你在这一阶段建立的代码组织方式会直接影响后面每一段代码的阅读体验和维护成本。

相关新闻

R语言基础入门:向量、循环法则与NA/NaN处理

R语言基础入门:向量、循环法则与NA/NaN处理

搞R语言也有几年了,每次带新人入门,我都会让他们先把向量、循环法则、NA和NaN这几个概念弄明白,再往后学才是正路。别小看这些基础,多少人在实际处理数据时,被循环法则静默回收坑得怀疑人生,被NA和NaN的组合…

2026/10/12 12:38:52 阅读更多 →
南开大学编译原理作业实战:简单C语言编译器从词法到代码生成

南开大学编译原理作业实战:简单C语言编译器从词法到代码生成

简介:这份资源是南开大学软件学院编译原理课程的作业成果,包含一个可运行的简单C语言编译器完整源码与配套文档,面向计算机、人工智能、通信工程等专业的在校学生及自学者,适合用作课程设计、毕业设计参考或编译原理入门实践。压缩…

2026/10/12 12:38:52 阅读更多 →
基于Docker的大学生兼职平台部署:容器化设计与避坑实践

基于Docker的大学生兼职平台部署:容器化设计与避坑实践

简介:基于Docker的大学生兼职平台项目完整资源包,服务于计算机专业学生与后端开发人员,也适合作为毕业设计选题参考。项目围绕兼职信息发布、岗位检索、用户管理等核心功能展开,采用Java语言结合常见微服务开发框架,后…

2026/10/12 12:38:52 阅读更多 →

最新新闻

Adapt 与 AdaptView 实战:把 endpoint 改到 TaoToken 的配置与验证

Adapt 与 AdaptView 实战:把 endpoint 改到 TaoToken 的配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 13:32:46 阅读更多 →
微博文本爬取与舆情分析实战:requests+Pyecharts可复现闭环

微博文本爬取与舆情分析实战:requests+Pyecharts可复现闭环

简介:这是一份面向Python爬虫与文本分析初学者的实战项目资源,聚焦微博平台用户行为数据采集与多维可视化分析。资源提供完整的微博UID定向抓取方案,支持获取用户资料、原创及转发微博(含图文)、热评数据,并…

2026/10/12 13:32:46 阅读更多 →
Agent Skills使用指南:让AI智能体拥有“即插即用”的超能力|TaoToken统一Key接入实践

Agent Skills使用指南:让AI智能体拥有“即插即用”的超能力|TaoToken统一Key接入实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 13:32:46 阅读更多 →
KNN算法实战:从原理到决策边界可视化

KNN算法实战:从原理到决策边界可视化

1. 从KNN说起:为什么一个“懒惰”算法值得单独开一篇很多人学机器学习,第一个接触的分类算法是逻辑回归或者决策树,但真正让我觉得“有意思”的,其实是KNN。原因很简单:它几乎不训练,却能把分类这件事做得有…

2026/10/12 13:32:46 阅读更多 →
排列组合算法全解析:从全排列到可重复组合的代码实现与去重剪枝

排列组合算法全解析:从全排列到可重复组合的代码实现与去重剪枝

1. 为什么排列组合值得单独开一个系列来整理排列组合这四个字,很多人第一次听到是在高中课堂,第二次听到就是在面试或者实际项目里被卡住的时候。我做了十多年开发,带过不少新人,发现一个很普遍的现象:动态规划、二分查…

2026/10/12 13:32:46 阅读更多 →
Linux目录结构完全解读:从挂载点到虚拟文件系统的实战指南

Linux目录结构完全解读:从挂载点到虚拟文件系统的实战指南

从 Windows 切到 Linux 的第一周,我干过一件现在想起来挺蠢的事:习惯性地想去盘符里找 C 盘、D 盘,结果打开文件管理器,看到的是一棵以/为根的目录树,满屏的/usr、/var、/etc、/dev。当时脑子里就一句话:这…

2026/10/12 13:31:45 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/12 0:16:30 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:54 阅读更多 →