写代码时候的命名规则、命名规范、命名常用词汇
版权声明
这个大部分笔记是观看up主红桃A士
的视频记录下来的,因为本人在学习的过程中也经常出现类似的问题,并且觉得Up主的视频讲解很好,做此笔记反复学习,若有侵权请联系删除,此推荐视频地址:【改善丑陋的代码】 https://www.bilibili.com/video/BV1844y1N7S8/p=28&share_source=copy_web&vd_source=688b3f7cfe13111b787853fb99306d7b
1.命名规则
本命名规范针对深度学习,根据我平时写代码的时候自己总结的一套规则。
1.1 路径命名规则
全部采用小写代码,使用名词,不适用动词。
比如我自己的一个代码结构:
---- data: 数据集
---- models:模型
---- dataprocess:数据处理
---- logs:日志文件
---- utils:工具类
1.2 代码文件/类命名
驼峰命名法则,开头大写,使用名字、动名词
比如我自己一个代码命名
---- ModelingAbstrct:模型训练抽象类
---- DataSetLoader:数据集加载类
---- DataProcesser: 数据预处理类
1.3 函数/变量命名规则
java使用驼峰命名法,首字母小写,动词加名词
python使用蛇形命名法,全部使用小写字母,使用下划线做为分隔符号
比如我自己的一个代码命名:
---- def convert_word_to_token():将汉字转换成token
---- def load_origin_data():加载原始数据
---- best_micaroF1:最优微平均
---- max_doument_length:最大文本长度
2.高可读命名规范
2.1 为什么命名这么重要
原因:
- 第一眼被人看到,留下第一印象
- 看不懂代码片段的时候,会结合命名进行联想
- 获取某个范围中的关键信息时,会使用全局字符查找
那么如何又能规范命名?
- 变量名能否看出这个变量关联什么东西
- 变量名是否能够看出变量是用来做什么的?
举一个例子:
给一段我们通常容易写的代码命名
class File
{
int d;
}
bool flag=false;
List<File>list1=new List<File>(....);
foreach(var item in list1){if(item.d>0){flag=true;break;}
}
看了这段代码是不是很熟悉,就像我们平时写的代码一样,代码中的变量没有人和语义信息,需要联系上下文才可以看出代码所表达的含义。
** 优化命名规范:**
class File
{
int daysSinceModifycation;
}bool isFileChanged=false;
List<File>createFiles=new List<File>(...);
foreach(var file in createdFiles){if(file.daysSinceModification>0){isFileChanged=true;break;}
}
这是优化后的代码,是不是感觉代码的可读性瞬间提高了?
2.2 变量的命名规范
2.2.1 整型变量命名
举个小例子,我们需要命名一个整数的天数和时间,看看一般人是怎么命名的,然后大佬又是怎么命名的。
int d; //菜鸡
int days;// 正常//大佬的命名方式,将天数与用途全部写入命名中
int elapsedTimeInDays;// 流逝的时间天数
int daysSinceCreation;// 创建的时间天数
int daysSinceModdification;//修改的时间天数
int fileAgeInDays;// 文件存在时间天数//----------------------------------------
int t;
int times;int timesOfRequestRetry;//请求重复次数
注意点:
- 1.如果命名需要注释来补充,那其本身就不算
名副其实
- 2.明确计量
对象(What)
和计量单位(Count,Time,Day,Minute,Second)
2.2.2 布尔类型变量命名
举个小例子
boolean flag; // 我想表达进程是否已经完成
boolean loaded; //我想表达页面是否加载完成//高级表达
boolean isProcessFinished;
boolean isPageLoaded;
注意点:
- 1.以正逻辑为主(个人习惯), 减少反逻辑带来的可读性影响
- 2.
前缀词(is,can,has,need)
+名词
+形容词/动词
,让变量更直观
2.2.3集合型变量命名
通常我在遍历集合的时候,都是用item作为变量,如果有多个item的时候时候,就会混淆。
举个例子:
List<File>list1=new List<File>(....) // 创件一个file list
foreach(var item in list){
........
}//---------------规范表达--------------------
List<File>createdFiles=new List<File>(.....);
foreach(var file in createdFiles){
..........
}
注意点:
- 1.对于自定义类型名,可以考虑作为变量名中的一部分
- 2.加_上复数表示,可以让遍历操作的代码可读性更加直观
最后对开始的案例进行一个规范的修改:
2. 3变量命名容易出现名不副实的场景
1.使用简单代码调试之后准备正式使用的时候
注意:是否有测试时图方便而命名不规范的地方
2.拷贝网上的代码用于项目中时
注意:是否有需要调整命名的地方
3.业务逻辑修改之后
注意:是否有命名和现有逻辑不匹配的地方
4.阅读自己或他人之前编写的代码的时候
注意:是否有不符合规范的地方
2.4 比较建议的重构原则
- 定要全局修改所有引用处,避免存在全局变量的影响
- 只要看到不规范的地方,就可以顺手修改,避免以后忘记
- 每一处小小的优化都是对代码质量的提升
3.对变量做有意义的区分
如果程序员只是为满足编译器或解释器的需要而写代码,就会制造麻烦。
例如:
因为同一作用范围内东西不能重名,你可能会随手改掉其中一个名称,或干脆以错误的拼写充数。
3.1 案例分析
3.1.1 数字系列命名
举个例子:
public void copyChars(char a1[],char a2[]){for(int i=0;i<a1.length;i++)a2[i]=a1[i]}
}
问题:
依义命名成了依数命名,这样的名称纯属误导,没有提供正确信息,对可读性带来危害。
后续如果还存在相近的变量,仍然存在命名冲突的烦恼。
优化:
public void copyChars(char sourceChars[],char destinationChars[]){for(int i=0;i<a1.length;i++)destinationChars[i]= sourceChars[i]}
}
使用sourceChars/source和destinationChars/destination作为参数名。即清晰表示了变量本身的含义,又不容易有后续命名冲突上的烦恼。
3.1.2 nonsense命名
举个例子:
class Product{...
}class ProductInfo{....
}class ProductdData{....
}
问题:
Info和Data本身意义含混,无论是否加上它们意义都基本没有区别。
无法体现类之间的不同点,会让代码阅读者抓狂。
优化:
如果打算这样命名,先问自己:
- 几个类之间具体的含义/功能区别是什么,是否有必要分成多个类?
- 如果有必要区分,是否具有更清晰的命名? (通常一一定可以找到更有区别意义的命名)
3.2 变量名容易出现无意义区分的场景
1.多次修改代码后编译一直出现错误
注意:耐心定位代码中的问题,切勿暴躁地随意修改。
2.设计、编码的思考不够
注意:命名时不仅要考虑本身的含义,还需要注意相近意义的区分。
3.3 比较建议的重构原则
1.研究清楚逻辑后再小心修改。
代码中有相近命名时本身就容易混淆,理解代码逻辑后再修改可以避免重构后引发问题。
2.代码是给程序员阅读和修改的,编码时应尽量从读者的角度去思考。
4.避免误导命名
程序员必须避免留下掩藏代码本意的错误线索。
4.1 误导的来源:
- 1.缩写/简写误导
- 2.多义词汇误导
- 3.变量类型误导
- 4.外形相似误导
4.2 案例分析
4.2.1 缩写/简写误导一使用的缩写/简写只有自己认知
//通用的简写/缩写
// Get source position
GetSrcPos();//Convert rgb to gray format
Rgb2Gray();//可能只有自己才看的懂的
// Set data's status
SetDataSta()//Query user address
QueryUserAdd();
问题:
- 1.使用的简写/缩写形式不一定每人都能理解,需要具体研究代码才明白。
- 2.简写/缩写的结果不规范,出现同义词的情况。
优化:
//Set data's status
SetDataStatus();
//Query user address
QueryUserAddress()
1.如果要用简写,就使用通用的/大众认可的。
2.不确定是否能被理解的情况下尽量用全写,这样不会有问题。
4.2.2 多义词汇误导——出现其他含义的联想
原文举例: hp、aix、 sco不该用作变量名,因为都是Unix平台的专有名称。
举个例子:
//开始时间or持续时间
public bool SetMonitorTime(){
//Set something
/Windows注册表or登记机关?
public string QueryRegistryContent(){
//Query something
}
问题:
如果没有上下文语境的提示,会有双关含义。
优化:
public bool SetMonitorStartTime(){
//Set something
}
class WindowsRegistry{public string QueryRegistryContent(){//Query something}
}
- 1.添加对应上下文的语境,比如迁移到类中或者模块里,方便理解。
- 2.更换/添加对应单词。
4.2.3 变量类型误导——一某些命名会让人误解变量的类型
举个例子:
class Account{......
}
Account[] accountList;
问题:
别用accountList来表示一组账号,除非它真的是List类型,List对于程序员有特殊意义。
优化:
class Account{.....Account[] accountGroup;Account[] bunchOfAccounts;Account[] accounts;
删除类型名,用更清晰的命名替代(即便容器是List,也最好别用其命名)。
4.2.4 外形相似误导一-两个命名过于相近/含有 易混淆字符
举个例子:
class XYZControllerForHandlingOfStrings{
}
class XYZControllerForStorageOfStrings{
}inta= 1;if(O == 1){a= O1;else{|= 01;
问题:
- 两个命名过于相似,阅读者看到后可能产生误会。
- O,0,o以及i, 1这样的字符很相近,容易看错。
优化:
避免变量名过于相似(尤其是长变量名),避免使用易混淆字符。
5.函数命名常见误区以及命名规则总结
5.1 动词滥用问题
注意:
避免滥用通用单词
问题:
- 通用单词可以在很多场景下命名,但不能区分具体函数职责。
- 当函数本身的实现途径不同时,难以从函数名得到足够的信息
下面就列举几个例子
5.1.1 万能的Get
GetTotalAmount();
上述的函数名是表达什么呢?
获取属性?
获取本地存储内容?
获取网络内容?
获取数据库内容?
获取计算后的内容?
…
5.1.2 万能的Add
AddCharacter();
上述函数名是想表达什么呢?
添加到头部?
添加到尾部?
从中间插入字符?
…
5.2 各类函数命名动词详细总结
5.2.1 创建/销毁
动词 | 用途 | 示例 |
---|---|---|
Create | 创建实例,常用于实例化方法和工厂方法的命名 | CreateInstance |
Initialize | 初始化实例的属性和设置,Initialize本身也可作为类方法用来初始化 | InitializeInstance,Initialize |
Load | 加载配置,根据配置创建内容 | LoadFromConfig |
Destroy | 销毁实例,常用语析构方法 | DestroyInstance |
Uninitialize | 清理实例的属性和设置,通常和Initialize对应 | UninitializeInstance,Uninitialize |
5.2.2 获取/设置
动词 | 用途 | 示例 |
---|---|---|
Get | 常用于取属性的类方法命名,也可作为通用获取方法命名 | GetStartTime |
Fetch | 通过网络请求获取内容 | FetchAllUsers |
Calculate | 通过计算获取内容 | CalculateTotalAmount |
Read | 读取(多用于文件,配置等) | ReadFile,ReadConfig |
Query | 查询 | QueryRemainingAmount |
Find | 查找(多用于数据库,集合等),和search相似 | FindOrder |
Receive | 接收(多用于文件,消息等) | ReceiveNewMessage |
Pull | 拉取 | PullLastestSourceCode |
Set | 常用于设置属性的类方法命名,也可作为通用设置方法命名 | SetStartTime |
Write | 写入(文件/配置等) | WriteFile,WriteConfig |
Put | 放入 | PutUserWithId |
Push | 存入,推送(通知) | PushNotification |
5.2.3 更新
动词 | 用途 | 示例 |
---|---|---|
Reset | 强调重置(标记,状态) | ResetTimer |
Refresh | 用于命名刷新(多用于页面,缓存等) | RefreshCurrentPage |
Update | 更新(多用于配置,状态等) | UpdateUserSetting |
5.2.4 添加/移除
动词 | 用途 | 示例 |
---|---|---|
Add | 用于通用添加方法命名 | AddNewStudent |
Append | 强调在尾部添加(追加) | AppendCharacter |
Insert | 强调插入(可以在任意位置) | InsertCharacter |
Delete | 表示删除,和Remove相近 | DeleteDirectory |
Remove | 表示移除,和Delete相近 | RemoveInvalidDeals |
5.2.5 启动/停止
动词 | 用途 | 示例 |
---|---|---|
Open | 开启(多用于开启状态,打开文件等) | OpenEnhanceMode |
Start | 开始(强调开始某个流程) | StartPortListening |
Launch | 发动/启动(多用于启动程序,服务) | LaunchAssistService |
Close | 关闭(多用于关闭状态,关闭文件等) | CloseEnhanceMode |
Stop | 停止(强调流程的终止) | StopPortListening |
Pause | 暂停(强调流程的暂停,有可能后续会继续开启) | PausePageLoading |
Finish | 完成(强调流程的完成) | FinishRequesting |
5.2.6 集合类型相关数据处理
动词 | 用途 | 示例 |
---|---|---|
Filter | 过滤,筛选(强调按照某些条件) | FilterByName |
Merge | 合并(有时会带上合并规则) | MergeTwoConfig |
Concat | 拼接(直接在结尾添加) | ConcatToArray |
Split | 分割 | SplitInput |
Deduplicate | 去重(去重完全相同的项) | DeduplicateList |
Reverse | 颠倒,反向排列 | ReverseRecord |
Sort | 排序(有时会带上排序规则) | SortDealsByAmount |
Fill | 填充(一般会进行覆盖) | FillAmountList |
5.2.7 通用业务数据处理
动词 | 用途 | 示例 |
---|---|---|
Parse | 解析(解析成某些格式,解析提取某些内容) | ParseFromJson,ParseResult |
Analyse | 分析(不一定能通过简单的方式获取) | AnalyseLocation |
Convert | 类型转换(通常用于从一个类型转换到另一种类型) | ConvertToString |
Format | 格式化数据 | FormatToLocaleString |
Validate | 合法性/有效性的校验 | ValidateUserInputs |
Ensure | 期待值的校验 | EnsureUserAge |
Compose | 组成(一般由多项内容组成一个结果) | ComposeMessage |
Encode | 编码(依赖约定的编码格式) | EncodeUrl |
Decode | 解码(依赖约定的解码格式) | DecodeUrl |
Encrypt | 数据加密(依赖约定的加密算法) | EncryptContent |
Decrypt | 数据解密(依赖约定的解密算法) | DecryptContent |
Backup | 备份(需要注意拷贝方式,避免误导) | BackupUserSettings |
Restore | 恢复 | RestoreUserSettings |
Import | 导入(通常用于按照特定格式的文件转换) | ImportFromFile |
Export | 导出(通常用于转换成特定格式的文件) | ExportToFile |
Compress | 压缩(依赖约定的算法) | CompressOversizedFile |
Decompress | 解压缩(依赖约定的算法) | DecompressOversizedFile |
相关文章:

写代码时候的命名规则、命名规范、命名常用词汇
版权声明 这个大部分笔记是观看up主红桃A士的视频记录下来的,因为本人在学习的过程中也经常出现类似的问题,并且觉得Up主的视频讲解很好,做此笔记反复学习,若有侵权请联系删除,此推荐视频地址:【改善丑陋的…...

Linux之iptables防火墙
一.网络安全技术 ①入侵检测系统(Intrusion Detection Systems):特点是不阻断任何网络访问,量化、定位来自内外网络的威胁情况,主要以提供报警和事后监督为主,提供有针对性的指导措施和安全决策依据,类 似于…...

启动服务报错:Command line is too long Shorten command line for xxx or also for Spri
ommand line is too long. Shorten command line for ProjectApprovalApplication or also for Spring Boot default configuration. 启动springboot 项目的时候报错 解决方案: 点击提示中的:default:然后在弹出窗口中选择:JAR xx…...

docker安装elasticsearch、kibana
安装过程中,遇到最大的问题就是在安装kibana的时候发现 一直连接不上 elasticsearch。最后解决的问题就是 我通过 ifconfig en0 | grep inet| awk {print $2} 在mac中找到本机的ip,然后去到kibana容器中 修改 vi config/kibana.yml中的elasticsearch.hos…...

前端 CSS - 如何隐藏右侧的滚动条 -关于出现过多的滚动条导致界面不美观
1、配置 HTML 标签,隐藏右侧的滚动条 CSS 配置:下面两个一起写进进去,适配 IE、火狐、谷歌浏览器 html {/*隐藏滚动条,当IE下溢出,仍然可以滚动*/-ms-overflow-style:none;/*火狐下隐藏滚动条*/overflow:-moz-scroll…...

2.神经网络的实现
创建神经网络类 import numpy # scipy.special包含S函数expit(x) import scipy.special # 打包模块 import pickle# 激活函数 def activation_func(x):return scipy.special.expit(x)# 用于创建、 训练和查询3层神经网络 class neuralNetwork:# 初始化神经网络def __init__(se…...

合宙Air724UG LuatOS-Air LVGL API控件-键盘 (Keyboard)
键盘 (Keyboard) LVGL 可以添加触摸键盘,但是很明显,使用触摸键盘的话必须要使用触摸的输入方式,否则无法驱动键盘。 示例代码 function keyCb(obj, e)-- 默认处理事件lvgl.keyboard_def_event_cb(keyBoard, e)if(e lvgl.EVENT_CANCEL)the…...

pytorch深度学习实践
B站-刘二大人 参考-PyTorch 深度学习实践_错错莫的博客-CSDN博客 线性模型 import numpy as np import matplotlib.pyplot as pltx_data [1.0, 2.0, 3.0] y_data [2.0, 4.0, 6.0]def forward(x):return x * wdef loss(x, y):y_pred forward(x)return (y_pred - y) ** 2# …...

直方图反向投影(Histogram Backprojection)
直方图反向投影(Histogram Backprojection)是一种在计算机视觉中用于对象检测和图像分割的技术。它的原理基于图像的颜色分布,允许我们在一幅图像中找到与给定对象颜色分布相匹配的区域。这个技术常常用于图像中的目标跟踪、物体识别和图像分…...

day32 泛型 数据结构 List
一、泛型 概述 JDK1.5同时推出了两个和集合相关的特性:增强for循环,泛型 泛型可以修饰泛型类中的属性,方法返回值,方法参数, 构造函数的参数 Java提供的泛型类/接口 Collection, List, Set,Iterator 等 …...

DW-AHB Central DMAC
文章目录 AHB Central DMAC —— Design Ware AHB Central DMAC —— Design Ware AHB(Adavenced High-performace BUS) Central DMAC(Direct Memory Access Controller) : 一个高性能总线系统。 作用:在嵌入式系统种连接高速设备,如处理器内存&#x…...

JavaScript设计模式(四)——策略模式、代理模式、观察者模式
个人简介 👀个人主页: 前端杂货铺 🙋♂️学习方向: 主攻前端方向,正逐渐往全干发展 📃个人状态: 研发工程师,现效力于中国工业软件事业 🚀人生格言: 积跬步…...

JS画布的基本使用
直线 <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title></title> <style> #myname{ border: 1px solid red; /* background: linear-gradient(to righ…...

c++ set/multiset
set/multiset 集合,一个单个,一个多个(multi)。两个库都是"set"。 https://blog.csdn.net/fckbb/article/details/130917681 对象创建 set(const Pred& compPred(),const A& alA()):创建空集合。set(const set& x):…...

多线程与高并发——并发编程(4)
文章目录 四、阻塞队列1 基础概念1.1 生产者消费者概念1.2 JUC阻塞队列的存取方法2 ArrayBlockingQueue2.1 ArrayBlockingQueue的基本使用2.2 生产者方法实现原理2.2.1 ArrayBlockingQueue的常见属性2.2.2 add方法2.2.3 offer方法2.2.4 offer(time,unit)方法2.2.5 put方法2.3 消…...

设计模式之建造者模式
文章目录 盖房项目需求传统方式解决盖房需求传统方式的问题分析建造者模式概述是建造者模式的四个角色建造者模式原理类图建造者模式的注意事项和细节 盖房项目需求 需要建房子:这一过程为打桩、砌墙、封顶房子有各种各样的,比如普通房,高楼…...

源码编译安装opencv4.6.0,别的版本也行
1.下载opencv4.6.0 系统: ubuntu 1804 64位点我下载opencv 4.6.0 https://codeload.github.com/opencv/opencv/zip/refs/tags/4.6.0 指令下载 推荐: wget -O opencv.zip https://github.com/opencv/opencv/archive/4.6.0.zip wget -O opencv_contrib.zip https://github.com/…...

【MongoDB】Springboot中MongoDB简单使用
1. docker安装MongoDB 拉取镜像 docker pull mongo创建容器 docker run -di --name mongo-service --restartalways -p 27017:27017 -v ~/data/mongodata:/data mongo2. 导入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactI…...

Python 面试:单元测试unit testing 使用pytest
1. 对于函数进行单元测试 calc.py def add(x, y):"""Add Function"""return x ydef subtract(x, y):"""Subtract Function"""return x - ydef multiply(x, y):"""Multiply Function""…...

螺旋矩阵、旋转矩阵、矩阵Z字打印
螺旋矩阵 #include <iostream> #include <vector> void display(std::vector<std::vector<int>>&nums){for(int i 0; i < nums.size(); i){for(int j 0; j < nums[0].size(); j){std::cout<<nums[i][j]<< ;}std::cout<<…...

Seaborn绘制热力图的子图
Seaborn绘制热力图的子图 提示:如何绘制三张子图 绘制的时候,会出现如下问题 (1)如何绘制1*3的子图 (2)三个显示条,如何只显示最后一个 提示:下面就展示详细步骤 Seaborn绘制热力…...

C++二级题目4
小白鼠再排队 不会 多余的数 #include<iostream> #include<string.h> #include<stdio.h> #include<iomanip> #include<cmath> #include<bits/stdc.h> int a[2000][2000]; int b[2000]; char c[2000]; long long n; using namespace std; i…...

Tomcat 部署时 war 和 war exploded区别
在 Tomcat 调试部署的时候,我们通常会看到有下面 2 个选项。 是选择war还是war exploded 这里首先看一下他们两个的区别: war 模式:将WEB工程以包的形式上传到服务器 ;war exploded 模式:将WEB工程以当前文件夹的位置…...

Delphi IdTcpServer IdTcpClient 传输简单文本
Delphi IdTcpServer IdTcpClient 传输简单文本 已经很久敲代码了,想找一段直接Delphi11 TCP简单文本传输,费劲!FStringStream 、FStrStream : FStringStream:TStringStream.Create(,TEncoding.UTF8); 已经很久敲代码了,…...

界面控件Telerik UI for WPF——Windows 11主题精简模式提升应用体验
Telerik UI for WPF拥有超过100个控件来创建美观、高性能的桌面应用程序,同时还能快速构建企业级办公WPF应用程序。Telerik UI for WPF支持MVVM、触摸等,创建的应用程序可靠且结构良好,非常容易维护,其直观的API将无缝地集成Visua…...

PoseC3D 基于人体姿态的动作识别新范式
摘要1. Introduction2. Related Work动作识别 3D-CNN基于骨架的动作识别 GCN基于骨骼的动作识别 2D-CNN3. Framework3.1. Good Practice for Pose Extraction3.2. From 2D Poses to 3D Heatmap Volumes3.3 基于骨骼的动作识别 3D-CNNPose-SlowOnlyRGBPose-SlowFast4. Experimen…...

html2canvas 截图空白 或出现toDataURL‘ on ‘HTMLCanvasElement或img标签没截下来 的所有解决办法
1.如果截图空白: 1.1以下的参数是必须要有的。 width: shareContent.offsetWidth, //设置canvas尺寸与所截图尺寸相同,防止白边height: shareContent.offsetHeight, //防止白边logging: true,useCORS: true,x:0,y:0,2,如果出现了报错 toData…...

Eclipse错误提示: Symbol ‘xxxx‘ could not be resolved
问题现象: 调试FPGA时,如果在qsys中增加新的内容,到nios中编译的时候就会提示找不到宏定义。 而这些宏定义都是在system.h这个头文件中的,原来的宏定义都能找到,就是新增的找不到,这个应该和头文件路径没有…...

基于Java的OA办公管理系统,Spring Boot框架,vue技术,mysql数据库,前台+后台,完美运行,有一万一千字论文。
基于Java的OA办公管理系统,Spring Boot框架,vue技术,mysql数据库,前台后台,完美运行,有一万一千字论文。 系统中的功能模块主要是实现管理员和员工的管理; 管理员:个人中心、普通员工…...

正则表达式(JAVA)
正则表达式(JAVA) 文章目录 正则表达式(JAVA)用法字符类(只匹配一个字符)预定义字符(只匹配一个字符)数量词贪婪爬取符号捕获分组规则捕获分组符号 非捕获分组案例忽略大小写 用法 正则表达式在用于校验信息是否满足某些规则的时候,非常的好用 在文本中查找满足要求的内容 字…...