当前位置: 首页 > news >正文

一文读懂 PHP PSR 接口 PSR-3、PSR-7、PSR-11、PSR-15 完整指南

一文读懂 PHP PSR 接口 PSR-3、PSR-7、PSR-11、PSR-15 完整指南

现代 PHP 的选择很多。这本来是好事,但一到升级框架、替换 Logger,或在团队间统一服务时,你会发现:看不见的耦合(类型、方法签名、约定)会把小改动变成大手术。

本文用通俗的话讲清四个关键标准——PSR-3(日志)、PSR-7(HTTP 消息)、PSR-11(容器)和 PSR-15(HTTP 中间件)——如何在代码里建立稳定的边界(seams)。入门读者能拿到清晰定义和可直接复用的示例;进阶读者可以参考迁移策略、取舍与度量方法。

你将学到

  • 用直白语言解释这些标准到底是什么
  • 如何按小步引入,每个 PSR 都附带可直接落地的代码
  • 一个小案例:低成本替换第三方库或框架
  • 常见坑(不可变性、过度适配、性能顾虑)以及哪些场景不该用 PSR
  • 一份检查清单与轻量指标,帮你证明确实降低了锁定(lock-in)

关键概念与定义

什么是 PSR? 由 PHP-FIG 发布的社区标准,侧重接口与规范。它只约定“契约”,不规定实现,因此不同库可以顺畅互通。

接口 vs 实现 接口规定“做什么”,实现负责“怎么做”。代码若依赖接口,就能在不改调用点的前提下替换实现。

PSR-3(日志)

Psr\Log\LoggerInterface 定义了 debug()info()error() 等方法,以及通用的 log($level, $message, array $context = [])。任何符合 PSR-3 的 Logger(如 Monolog)都能满足这个契约。

PSR-7(HTTP 消息)

为 HTTP 请求、响应、流、URI、上传文件提供接口(Psr\Http\Message\*)。对象是不可变的,例如 withHeader() 会返回新实例;好处是行为可预测、共享安全。

PSR-11(容器)

Psr\Container\ContainerInterface 是一个很小的依赖注入契约:get(string $id): mixedhas(string $id): bool。用它,框架与库之间无需绑定某个特定的 DI 实现。

PSR-15(HTTP 处理器与中间件)

Psr\Http\Server\RequestHandlerInterfaceMiddlewareInterface 规范了服务器端中间件如何处理 ServerRequestInterface 并返回 ResponseInterface。这是 HTTP 管道的通用形态。

为什么是这四个? 它们覆盖了多数应用的关键边界:日志、HTTP、依赖装配和跨请求的 HTTP 行为。把这些地方标准化,只需很少改动就能显著提升可移植性。

新手提示:若觉得缩写抽象,可以先看示例再回来看定义。进阶提示:这些 PSR 可分步引入,不需要大重构。

分步落地框架

第 1 步 —— 用 PSR 接口包住外部库

先改“你的代码依赖谁”,别急着动第三方库。加一层薄的适配器:业务代码只面向 PSR,适配器去对接具体库。

示例:把遗留 Logger 适配成 PSR-3

<?phpuse Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
final class LegacyToPsrLogger implements LoggerInterface
{public function __construct(private LegacyLogger $legacy) {}public function emergency($message, array $context = []) { $this->log(LogLevel::EMERGENCY, $message, $context); }public function alert($message, array $context = [])     { $this->log(LogLevel::ALERT, $message, $context); }public function critical($message, array $context = [])  { $this->log(LogLevel::CRITICAL, $message, $context); }public function error($message, array $context = [])     { $this->log(LogLevel::ERROR, $message, $context); }public function warning($message, array $context = [])   { $this->log(LogLevel::WARNING, $message, $context); }public function notice($message, array $context = [])    { $this->log(LogLevel::NOTICE, $message, $context); }public function info($message, array $context = [])      { $this->log(LogLevel::INFO, $message, $context); }public function debug($message, array $context = [])     { $this->log(LogLevel::DEBUG, $message, $context); }public function log($level, $message, array $context = []): void{$text = is_string($message) ? $message : json_encode($message);$this->legacy->write(strtoupper($level), $this->interpolate($text, $context));}private function interpolate(string $message, array $context): string{$replace = [];foreach ($context as $key => $val) {$replace['{'.$key.'}'] = is_scalar($val) ? (string)$val : json_encode($val);}return strtr($message, $replace);}
}

新手提示:继续用你现有的 Logger,只是通过适配器注入,让其他代码依赖 LoggerInterface。进阶提示:把适配器集中放在 Infrastructure\Bridge\VendorX 命名空间,边界更清晰。

第 2 步 —— 让 HTTP 消息统一到 PSR-7

把 HTTP 作为清晰的边界。让控制器与库接受/返回 Psr\Http\Message\RequestInterfaceResponseInterface,你就能在不同框架或服务器之间平滑迁移。

示例 A(上手快、具体):Nyholm PSR-7

<?phpuse Nyholm\Psr7\Response;
use Psr\Http\Message\ResponseInterface;
final class HelloController
{public function __invoke(string $name = 'world'): ResponseInterface{$response = new Response(200, ['Content-Type' => 'application/json']);$response->getBody()->write(json_encode(['message' => "Hello, {$name}!"]));return $response;}
}

示例 B(更通用、与实现无关):使用工厂。PSR-7 只定义接口;用 PSR-17 工厂来创建实例更干净(如果已有相关依赖)。

<?phpuse Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamFactoryInterface;
use Psr\Http\Message\ResponseFactoryInterface;
final class JsonResponder
{public function __construct(private ResponseFactoryInterface $responses,private StreamFactoryInterface $streams) {}public function ok(array $data): ResponseInterface{$body = $this->streams->createStream(json_encode($data));return $this->responses->createResponse(200)->withHeader('Content-Type', 'application/json')->withBody($body);}
}

新手提示:如果“工厂”听起来复杂,先用示例 A。进阶提示:在库代码里优先使用 PSR-17,才能真正保持与框架无关。

第 3 步 —— 用 PSR-11 解耦依赖装配

让应用通过构造函数接收依赖,把容器的使用放在系统边界。

示例:PSR-11 的应用引导

<?phpuse Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
final class App
{public function __construct(private ContainerInterface $container) {}public function run(): void{$logger = $this->container->get(LoggerInterface::class);$logger->info('App started');// 通过容器解析处理器、路由器等}
}

新手提示:避免在领域类中直接调用容器。把它们需要的依赖注入即可。进阶提示:用接口名绑定(如 LoggerInterface::class),在引导阶段用别名映射到实现。

第 4 步 —— 用 PSR-15 组合 HTTP 管道

鉴权、限流、缓存等横切问题应放在中间件里,而不是处理器里。

示例:耗时统计响应头中间件

<?phpuse Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
final class TimingMiddleware implements MiddlewareInterface
{public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface{$start    = microtime(true);$response = $handler->handle($request);$elapsed  = number_format((microtime(true) - $start) * 1000, 2);return $response->withHeader('X-Response-Time-ms', (string) $elapsed);}
}

新手提示:先加一个中间件(如请求日志),再逐步扩展到完整管道。进阶提示:让中间件保持纯粹——只依赖请求/处理器/响应,避免读写全局状态。

小案例

背景:你维护一套内部 API,基于某个框架 X。它使用自研 Logger、框架私有的 Request/Response 类型和专有中间件。你想降低锁定,为将来迁移到 Slim 或 Mezzio 做准备。

目标:用四个小步(可回滚)降低耦合,不打断日常迭代。

  • 动作 1 —— 在边界采用 PSR-3:把控制器/服务中对 CustomLogger 的直接引用改为 Psr\Log\LoggerInterface,加上第一步的适配器,旧 Logger 仍在背后运行。结果:代码不再依赖旧 Logger;切到 Monolog 只需在装配处改一行。
  • 动作 2 —— 在处理器采用 PSR-7:入口把框架 Request 转成 PSR-7 对象并向内传递;应用层返回 PSR-7 Response;最外层再转回框架类型。结果:核心逻辑只依赖 PSR-7。
  • 动作 3 —— 在引导采用 PSR-11:以 Psr\Container\ContainerInterface 暴露容器;应用代码通过构造函数接收依赖(优先接口)。结果:以后换容器只影响引导配置。
  • 动作 4 —— 管道采用 PSR-15:把现有过滤器/中间件包成 PSR-15 适配器;新中间件直接按 PSR-15 编写。结果:管道逻辑可移植;换框架时可复用同一批中间件。

切换:当你采用新框架时,只需重写最外层的适配器(请求/响应转换、路由装配)。领域、处理器和中间件保持不变。

常见坑与规避

  • 把 PSR 当“魔法”。接口治不了设计问题。让领域逻辑独立于框架与容器,把转换放在边界。
  • 忘记 PSR-7 的不可变性。withHeader() 会返回新对象。要链式调用或重赋值,不要指望原地修改。
  • 让供应商类型“漏进来”。入口若收 PSR 类型,却在某个 Helper 返回供应商类型,就把耦合带回来了。请在边界内外都用 PSR。
  • 过度工程化的适配器。没必要处处加适配器,先从热点(日志、HTTP、管道、容器)下手。
  • 适配器不写测试。桥接层容易出现细节问题(Header 大小写、Stream 读写位置)。围绕适配器写小而专注的测试。
  • 没数据支撑的性能担忧。多几个对象带来的开销通常比不上 I/O。如果出现回归,先 Profile 再优化(复用响应原型、Stream 工厂)。
  • 盲目“拿来主义”。若某个边界几乎不会变化,强行上 PSR 只会增加复杂度。标准是工具,不是教条。

示例和一些小的案例

  • PSR-3:Monolog;很多框架自带兼容 PSR-3 的 Logger

  • PSR-7:Laminas Diactoros、Nyholm/psr7、Guzzle PSR-7

  • PSR-11:PHP-DI、Laminas ServiceManager、Symfony 容器(兼容 PSR-11)、League Container

  • PSR-15:Slim(中间件管道)、Mezzio(Laminas)、Relay、middlewares/ 生态

  • 找出供应商类型渗透的位置(日志、HTTP、DI、管道)

  • 把这些缝合线的方法签名改成 PSR 接口

  • 加最小化适配器,确保旧代码仍能跑

  • 写针对性的测试:状态行、Header、Body 流、Middleware 顺序

  • 逐步把内部实现替换成 PSR 兼容的实现

  • 跟踪“替换耗时”和“耦合计数”

PSR-3 在领域服务中的用法

final class UserService
{public function __construct(private Psr\Log\LoggerInterface $logger) {}public function register(string $email): void{$this->logger->info('Registering user', ['email' => $email]);// ...}
}

PSR-15 处理器示例

final class HelloHandler implements Psr\Http\Server\RequestHandlerInterface
{public function handle(Psr\Http\Message\ServerRequestInterface $request): Psr\Http\Message\ResponseInterface{$name = $request->getQueryParams()['name'] ?? 'world';$res  = new Nyholm\Psr7\Response(200);$res->getBody()->write("Hello, {$name}!");return $res->withHeader('Content-Type', 'text/plain');}
}

如何度量与迭代

你需要证据来证明标准化确实有帮助。追踪简单且有意义的信号:

  • 替换耗时(Swap time):替换一个 Logger 或 HTTP 客户端要多久?合理目标是“分钟到小时”,而不是“几天”。
  • 耦合计数(Coupling score):在代码库里 grep 供应商类型(如框架的 Request/Response)。随着 PSR 替换,它们的数量应当逐步下降。
  • 边界测试覆盖率:为适配器的状态行、Header、Stream、Middleware 顺序编写测试。
  • 上手摩擦:新同学只看接口就能理解流程。核心代码里供应商概念越少,上手越快。
  • 运行时健康:采用 PSR-7/15 后观察延迟与内存。如有回归,先 Profile,再考虑“优化”。

迭代循环:

  1. 选择一个边界(如日志)
  2. 引入相应的 PSR 接口与适配器
  3. 把内部实现替换成兼容 PSR 的实现
  4. 度量替换耗时、耦合计数与性能
  5. 对 HTTP 消息、容器、中间件重复上述过程

要点速览

  • PSR-3、PSR-7、PSR-11、PSR-15 标准化了关键边界:日志、HTTP、DI 与管道
  • 面向接口编程,用薄适配器与工厂保持实现可替换
  • 从边界(控制器与基础设施)开始,逐步向内推进
  • 接受 PSR-7 的不可变性;使用 with*() 时要重赋值
  • 容器止步于边界;用 PSR-11,在领域中注入依赖
  • 中间件承载横切关注点,用 PSR-15 保持跨框架可移植
  • 用“替换耗时、耦合计数、适配器测试”来量化可移植性提升
  • 不要盲从标准;只在它们能降低风险与成本的地方使用

一文读懂 PHP PSR 接口 PSR-3、PSR-7、PSR-11、PSR-15 完整指南

相关文章:

一文读懂 PHP PSR 接口 PSR-3、PSR-7、PSR-11、PSR-15 完整指南

一文读懂 PHP PSR 接口 PSR-3、PSR-7、PSR-11、PSR-15 完整指南 现代 PHP 的选择很多。这本来是好事,但一到升级框架、替换 Logger,或在团队间统一服务时,你会发现:看不见的耦合(类型、方法签名、约定)会把小改动变成大手术。 本文用通俗的话讲清四个关键标准——PSR-3(…...

2025模拟赛Round9

T1 T2 T3 T4 T5 T6\({\color{#F39C11} 普及− }\) \({\color{#FFC116} 普及/提高− }\) \({\color{#3498DB} 提高+/省选− }\) \({\color{#3498DB} 提高+/省选− }\) \({\color{#3498DB} 提高+/省选− }\) \({\color{#3498DB} 提高+/省选− }\)参赛网址:https://boyacoding.cn…...

NOIP2025模拟赛19

T1 T2 T3 T4\({\color{#3498DB} 提高+/省选− }\) \({\color{#3498DB} 提高+/省选− }\) \({\color{#9D3DCF} 省选/NOI− }\) \({\color{#3498DB} 提高+/省选− }\)参赛网址:https://oj.33dai.cn/d/TYOI/contest/68919c89c5d9c2f14c1a537f T2,T4搭建未完成 T1 人才计数【NOIP2…...

Qt/C++开发监控GB28181系统/公网对讲/代码实现28181语音对讲/采集本地麦克风数据/支持udp和tcp模式

一、前言说明 按照国标的文档,语音对讲这块,并没有强制要求支持公网对讲,所以当初设备厂家做的都是支持的udp对讲,而且按照国标协议要求,对讲是先发一个语音对讲广播到设备,设备收到后,主动发起对讲到服务端,和视频点播是反着来的,这样的话数据的传输模式只能设备控制…...

P3195 [HNOI2008] 玩具装箱 (斜率优化)

题目描述 一道不限段数的分段问题,要求给出 \(n\) 个元素,求出分任意组所产生的最小代价。 思路 我们可以分为两步来求解这个问题,暴力转移与优化。 The First Step 暴力转移 考虑暴力DP,根据题目描述,每个容器之中玩具的编号都是连续的,并且不限容器数量,状态就很好定义…...

DBeaver使用指南

概述 由于众所周知的原因,公司不容许使用非授权正版软件。datagrip本身挺不错的,但是要倒腾激活码之类的,比较麻烦。只能从开源社区寻找好用的DBMS GUI工具。 发现DBeaver挺不错,功能很全,但是默认的配置不够好用、字体、样式等都不友好,需要打磨一番才行。 下文重点关注…...

sh-2025模拟赛

CSP-J 模拟(九)题目解答 一、单项选择题(每题2分,共30分) 1. 进制转换计算 答案:C 解析:先将八进制数\((2025)_8\)转换为十进制: \(2\times8^3 + 0\times8^2 + 2\times8^1 + 5\times8^0 = 2\times512 + 0 + 16 + 5 = 1024 + 21 = 1045\)。 将十六进制数\((2025)_{16}\)…...

C++ day7 - 指南

C++ day7 - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important; font-size: 14px !i…...

读人形机器人11娱乐领域

读人形机器人11娱乐领域1. 机器人表演者与艺术家 1.1. 在人类历史的宏大画卷中,艺术与娱乐一直是我们内心欲望、恐惧和抱负的映照 1.2. 音乐、舞蹈和戏剧表演中的机器人不再是科幻的虚构,而是正在重塑艺术表现形式的崭新现实 1.3. 机器人表演者和艺术家正在通过引入新的表现形…...

Java 注解机制全解析:原理、用途与框架中的实战

注解(Annotation)作为 Java 语言自 JDK5 引入以来的一项重要元编程特性,已经成为现代 Java 开发不可或缺的一部分。无论是 Spring 框架中的依赖注入、事务控制,还是 Hibernate 的对象关系映射,抑或是 Lombok 对代码生成的辅助,注解几乎贯穿于 Java 的开发全过程。 本文将…...

模板集

考虑到作为一名 Oier 有很多需要掌握的模板,所以整合了一下以前的专栏,就变成现在这样了! 有问题请加 qq 3848603482。可以帮你讲解。 给萌新的代码建议 尽量不要写全局变量,容易弄混不方便调试,要用了再创建。没有必要手写栈之类的,STL要了解多一点。不要写#define int …...

暑假

P2569 https://www.luogu.com.cn/problem/P2569 参考这篇。 /*单调队列优化dp买入股票的转移方程j是顺序枚举的,因为是买入股票,手中的股票应该是越来越多的, 当前的决策有可能在后面(j更大)的时候用到,所以你需要先求出来, 同理,卖出股票时,你手中的股票是越来越少的…...

做题记录

P1248 加工生产调度 比较妙的一道题,这里我们可以直接把 A 与 B 的最小值碾一遍,注意 B 操作时间要与 A 操作时间取最大值。...

课程助教工作总结

在上学期,我有幸担任了《数字电路与逻辑设计》课程的助教。这是一次极其宝贵和充实的经历,不仅巩固和深化了我的专业知识,更锻炼了我的沟通、组织和解决问题的能力。现将本学期的工作情况总结如下: 一、 助教工作的具体职责和任务 我的工作核心是成为连接主讲教师与学生的桥…...

6G 驱动的智慧城市新格局

引言随着科技的不断进步,6G 驱动的智慧城市新格局 正逐渐走向应用前沿。它不仅推动了相关产业的发展,也在改变人类社会的运作方式。本文将从背景、核心技术、应用案例、挑战与趋势、总结几个方面对其进行系统分析。 背景 📊6G 驱动的智慧城市新格局 的出现,是社会需求、政…...

SHA-1 证书淘汰警告:网站管理员需紧急验证TLS安全性

微软宣布自2017年5月9日起,Edge和IE11浏览器将逐步阻止SHA-1签名的TLS服务器证书。本文详细解析三阶段淘汰计划、受影响证书类型验证方法及企业应对方案,涉及证书链验证和弱签名日志收集技术。こんにちは、村木ゆりかです。 以前よりマイクロソフト セキュリティ アドバイザリ…...

数字孪生在制造业中的应用

引言在当前快速发展的科技环境中,数字孪生在制造业中的应用 已经成为学术界与产业界广泛关注的主题。本文将通过背景、核心技术、应用案例、挑战与趋势、总结六个部分进行系统性分析。 背景 📊数字孪生在制造业中的应用 的兴起与社会发展需求密切相关。随着数字化转型的加速…...

device第一周个人作业

一. 自我介绍 回顾我的学习经历,虽然没有什么惊天动地的大成就,但也没有一些值得骄傲的小闪光点。兴趣爱好是科幻和军事读物,以前喜欢跟朋友一起打比赛,现在发现朋友在打假赛…… 二.现状、经验与计划 (1)当前技能树与技术偏好 当前技能树: 我可以使用基础的C语言和java…...

Java 在移动开发与跨平台应用中的应用

随着智能手机的普及,移动应用已经成为数字化转型的重要载体。移动端承载着用户的核心交互,而跨平台开发趋势也不断兴起, 旨在减少多端重复开发成本。在这一过程中,Java 一直是移动开发的核心语言, 尤其在 Android 生态中占据主导地位,并通过跨平台技术、移动后端服务、混…...

5G 技术与远程教育

引言在当前快速发展的科技环境中,5G 技术与远程教育 已经成为学术界与产业界广泛关注的主题。本文将通过背景、核心技术、应用案例、挑战与趋势、总结六个部分进行系统性分析。 背景 📊5G 技术与远程教育 的兴起与社会发展需求密切相关。随着数字化转型的加速,全球化的扩展…...

5G 技术在工业互联网的应用

引言在当前社会与科技的双重推动下,5G 技术在工业互联网的应用 已成为一个举世瞩目的议题。它不仅仅是技术层面的创新,更代表着社会运行模式的转型。本文将从背景、核心技术、应用案例、挑战与趋势、总结几个方面进行深入探讨。 背景 📊5G 技术在工业互联网的应用 的发展源…...

一键部署ftp脚本

在 Ubuntu(root) 上搭建标准 FTP(vsftpd)服务器,带被动模式端口、用户创建、目录与权限配置,可直接落地执行。一、部署脚本(保存为 setup_ftp.sh,root 执行) #!/usr/bin/env bash set -euo pipefail### ====== 可按需修改的变量 ====== FTP_USER="ftpuser" …...

PySimpleGUI安装4.60.5老版本安装教程!

PySimpleGUI安装4.60.5老版本安装教程! ━━━━━━━━━━━━━━━━━━━━━━ https://download.csdn.net/download/mzl_18353516147/89506033?utm_medium=distribute.pc_relevant_download.none-task-download-2defaultBlogCommendFromBaiduRate-2-89506033-downlo…...

PySimpleGUI-免注册版本

PySimpleGUI 开始注册了,怎样能免注册使用早期版本? 若需免注册使用 PySimpleGUI 早期版本,可通过以下两种方法实现,具体操作及原理如下: 方法一:通过 pip 指定版本安装(推荐) 操作步骤:卸载现有版本(若已安装新版):pip uninstall PySimpleGUI安装指定旧版本(如 4…...

高三闲话 #1

APJ 三个银牌高考 699,我一个银牌考个 233 不过分吧高三生活还是如期而至了,写点高三闲话感觉太有道理了。不过我得先说明这篇文章的目的不是传播负能量,事实上我最近还是蛮积极的,只不过我无法回避这些我内心里的真实想法,而且感觉写出来很有意思,所以写一写。如果让我用…...

三大免费CDN推荐:安全防护强、稳定性卓越、加载飞速,长期使用超安心

三大免费CDN推荐:安全防护强、稳定性卓越、加载飞速,长期使用超安心1. 将盾CDN:防御与速度双卓越,建站首选利器 将盾CDN是一款专注于安全与性能的CDN服务,其免费版本在防御强度、国内访问速度及功能实用性上表现亮眼,无论是企业官网还是个人站点,都能提供可靠保障,是当…...

PySimpleGUI 开始注册了,怎样能免注册使用早期版本?

若需免注册使用 PySimpleGUI 早期版本,可通过以下两种方法实现,具体操作及原理如下: 方法一:通过 pip 指定版本安装(推荐) 操作步骤:卸载现有版本(若已安装新版):pip uninstall PySimpleGUI安装指定旧版本(如 4.60.5):pip install PySimpleGUI==4.60.5该版本在官方…...

全屏与退出全屏功能

全屏与退出全屏功能 📄 Fullscreen API 使用说明 通过浏览器提供的 Fullscreen API,你可以实现在任意 HTML 元素上的全屏展示与退出全屏效果,适用于视频播放器、看图模式、报表展示等场景。🧩 功能说明支持进入全屏 支持退出全屏 支持检测当前是否处于全屏状态 兼容多浏览…...

二十多年.NET老兵重返技术博客

缘起:博客园,我们的技术家园 自2005年入驻博客园,2006年开始撰写技术博客,直至2013年,我将博客园视为.NET技术交流的圣地。这里纯净、专注的技术氛围,以及众多技术精英的真诚分享,使其成为我们共同的网上家园。然而,由于工作性质的变化,我在2013年后逐渐淡出了技术博客…...

5月杂题

一点骨灰?臭不要脸的回到了机房,感觉大家越来越强了,膜拜。 想到什么写什么。多校清北营训练「清华场」B. 绕口令/gym100162B题意:定义一个字符串为好的当且仅当其中没有两个相邻字符相同,问你对 \(k\in[1,n]\),能否删去原字符串中连续 \(k\) 个字符得到一个好的字符串。…...

uv,下一代Python包管理工具

uv,下一代Python包管理工具 https://segmentfault.com/a/1190000047202911 什么是uv uv(Universal Virtual)是由Astral团队(知名Python工具Ruff的开发者)推出的下一代Python包管理工具,使用Rust编写。它集成了包管理、虚拟环境、依赖解析、Python版本控制等功能,它聚焦于…...

阅读 |《虚空》观后感以及一些想法——万物简史

保持学习,保持记录,保持思考—————— 啊啊啊,真的有好多想要去做的事情,好多想要体验的事情,真的没法同时去学习所有的事物,那是多么的令人感到幸福 这篇文主要就记下看完《虚空》之后的想法以及之后和AI的讨论 首先呢我初读这本书感觉很枯燥,但一整篇看下来之后还是…...

Python进阶必看:深入解析yield的强大功能

https://segmentfault.com/a/1190000045317342?utm_source=sf-similar-article Python进阶必看:深入解析yield的强大功能 头像 涛哥聊Python 2024-10-22 四川 阅读 3 分钟 头图 大家好,我是涛哥,本文内容来自 涛哥聊Python ,转载请标原创。 更多Python学习内容:http://ip…...

polyglot,一个有趣的 Python 库!

https://segmentfault.com/a/1190000045317129 polyglot,一个有趣的 Python 库! 头像 涛哥聊Python 2024-10-02 四川 阅读 4 分钟 头图 大家好,我是涛哥,本文内容来自 涛哥聊Python ,转载请标原创。 更多Python学习内容:http://ipengtao.com 今天为大家分享一个有趣的 Py…...

个人介绍与博客初建

大家好!我是 李祺,很高兴能通过博客园这个平台和大家交流。我是一名计算机相关专业的学生,在平时生活里,音乐、旅途和美食是三大支柱。耳机里永远循环着不同语言的旋律:华语流行的细腻歌词、K-pop 的强劲节奏、英文歌的叙事感,都能让我在忙碌时快速切换状态。 旅游是我探…...

PySimpleGUI,一个神奇的 Python 库!

https://segmentfault.com/a/1190000045317132?utm_source=sf-similar-article#item-3-3 大家好,我是涛哥,本文内容来自 涛哥聊Python ,转载请标原创。 更多Python学习内容:http://ipengtao.com 今天为大家分享一个神奇的 Python 库 - PySimpleGUI。 Github地址:https://…...

c++ 的拷贝构造函数

当类成员变量有指针类型的时候,要自定义拷贝函数,不要使用默认的拷贝构造函数.因为默认的拷贝构造构造函数是浅拷贝是位拷贝的,只拷贝指针指向的空间而没有把空间里的内容一起拷贝过来,这样会导致改变其中的一个,另一个也会跟着一起改变(老婆也都一样的了)class Teacher{ publi…...

变异

n可以理解成特征的对比 是的,完全可以这么理解!✅ 一句话总结:n 就是“你用多少种不同的视角/特征去衡量这两段区间的关系”。✅ 举个例子: 你把两条 150 kb 区间(X 和 Y)拿来比较,可以问:视角(特征) 具体问法 对应通道覆盖度视角 “X 和 Y 哪边 reads 更多?” read…...

【笔记】类欧几里得算法

类欧几里得算法(之后或许会加上万欧)直接用例子开始吧: \[给定 a,b,c,n,求解\sum_{i = 0}^n\left\lfloor\frac{ai+b}{c}\right\rfloor \]我们记 \(f(a,b,c,n) = \sum_{i = 0}^n\left\lfloor\frac{ai+b}{c}\right\rfloor\) 首先考虑 \(a \ge c\) 或 \(b \ge c\) 的情况: 先…...

AQS的一些思考

AQS-AI问答AQS是怎么实现CountDown AQS 为 CountDownLatch 提供了核心的 状态管理(state 作为计数器) 和 线程排队 / 唤醒机制(CLH 队列):通过 tryAcquireShared 检查计数器是否为 0,决定线程是否需要等待; 通过 tryReleaseShared 原子递减计数器,当计数器归零时唤醒所…...

DearPyGui-最强大的一款Python GUI工具

https://zhuanlan.zhihu.com/p/200754892 其实,在Python中不乏知名的UI构建工具包,例如,Tkinter,PyQT / PySide,wxPython,Kivy,PySimpleGui。这些工具包都很强大,但是,也非常繁琐。 开发一个框架要付出的精力和代码量几乎和核心逻辑相差无几,这与Python崇尚的简单是相…...

2 模型评估与选择

目录P18P23P25 P18 可以好好想一下ROC曲线是如何形成的:我们设置不同的二分类的阈值,就会有不同的(TPR,FPR)对;如果我们将所有数据按照其置信度从大到小排序,然后让阈值逐渐减小,并在ROC曲线上进行描点,那么我们可以发现,如果遇到一个正例,那么当前点会竖直向上走\(\fr…...

TY-290ES计算器屏幕逆向

刷拼多多时看到个便宜的TY-290ES计算器,到手价只需要人民币11块多,还是个点阵屏,真是难以想象国产计算器能做这么便宜,买一个来研究下。廉价小商品大本营(浙江)发的货,,,先点亮看看,功能很少,比82ES还差点意思。屏幕点阵粗略估了下,应该是96x31像素的,顶部有一行图标…...

CF1559E

时间限制 \(2\,\text{sec}\) 空间限制 \(256\,\text{MB}\) 题目来源 CodeForces。 题目大意 给定 \(n\) 个区间 \([l_i,\, r_i]\) 和一个常数 \(m\) ,在每个区间内选出一个正整数 \(a_i\) 构成一个数列 ,满足\(\displaystyle\sum^{n}_{i=1}a_i \leq m\) , \(\gcd \{a_i \} …...

笔记 哈希

A - Description 给定字符串 \(S\) 和 \(T\),问你在 \(S\) 中 \(T\) 出现了几次。 \(1\le |S|,|T|\le 2\times 10^6\) A - Solution 首先暴力地来想。在 \(S\) 中找出所有长度为 \(|T|\) 的子串,然后暴力逐字符匹配,复杂度显然是 \(O(n^2)\) 的,考虑优化。(此处假设 \(|T|…...

题解:CF566A Matching Names

题意 有 \(n\) 名同学,每位同学有一个真名与一个笔名,都是一个由小写英文字母组成的字符串。每位同学可以选择一位同学,使自己的真名与那位同学的笔名相匹配,产生的贡献为其最长公共前缀,每位同学的笔名只能与一人匹配,求贡献总和的最大值。 思路 把笔名插入字典树,并在…...

Tarjan 求连通性相关

复健发现自己对于 Tarjan 的一些东西都有些搞不清了啊。整理一下。 如有错误/不足,欢迎指出。 先给一些定义:\(u\) 表示某个子树的根节点。 \(v\) 表示与 \(u\) 相连的点。如果是无向图那么不包含父亲。 \(fa\) 表示 \(u\) 在 DFS 生成树上的父亲节点。 \(dfn_u\),表示 \(u\…...

暑假学习笔记

Hadoop 生态:实时 + 离线一体化 Flink on YARN 初体验 使用 Flink 1.17.1 提交 yarn-session 模式,队列 queue.stream 独享 4G 堆、2 vcore;编写 Kafka → Hive 的流式入湖作业,消费 user_behavior Topic,Checkpoint 30 s,Exactly-Once 写入 Hive 表 ods_log_rt,实现分钟…...

qoj #8557. Goldberg Machine 题解

有意思原题:https://qoj.ac/problem/8557 弱化版:https://www.luogu.com.cn/problem/P7830 但是弱化版要求做到更优复杂度,但是没有修改。 本文的 参考文章钦定树以 \(1\) 为根。钦定所有点 \(u\neq 1\) 的 \(e,t\) 循环位移成 \(e_{u,k_u-1}=fa_u\),就是把父亲丢到最后。 …...

centos7云主机磁盘清理过程纪要

云主机总磁盘大小为120G,在阿里云控制台配置了磁盘使用达90%告警 1. 收到告警短信 2. 当前磁盘占用情况 df -h | grep dev 已达到 89% 3. 开始排查 3-1. 查看哪个目录占用最大 du -sh /* 或者 du -sh /* | sort -h 发现 /www 目录占用 69G 3-2. 查看 /www du -sh /www/* /ww…...