☰
python的先进制造技术工业场景模拟第九篇:导入数控加工刀具寿命记录,筛选已达到寿命阀值的刀具,生成刀具更换清单。
2026/9/29 6:18:10 网站建设 项目流程

周五下午,CNC 加工车间工具室。

"又废了一批活,"车间主任老周把一摞报废的铝合金壳体推到我面前,"刀纹明显,粗糙度超差。调出系统一看——加工中心 3 号机用的那把 Φ10 立铣刀,已经连续切了 6.5 小时。标准寿命是 6 小时。"

我打开刀具管理系统导出的 CSV 文件。几千行记录,字段包括:刀具编号、类型(立铣刀/面铣刀/钻头/丝锥)、安装机床、安装时间、累计加工时间(h)、标准寿命(h)、已加工件数、磨损状态(正常/注意/警告/报废)、最后更新时间。

"系统里不是有寿命数据吗?"我问。

"有,"老周点开一行,"但它是按'把'记录的——每把刀一行,显示累计加工时间和标准寿命。我想知道的是:哪些刀已经达到寿命了、该换了;哪些快到了、要提前准备。系统没有'到期刀具清单'这个功能——它只会在一把刀报废的时候弹一个报警,但那时候活已经废了。"

"所以你现在每次换刀,都是凭经验看加工表面?"

"对,"老周苦笑,"老师傅凭声音和刀纹判断。但新人不行——上次有个新来的,一把刀干了 8 小时才发现不对,前面 2 小时的活全废了。厂长说必须搞一个'刀具更换预警清单',每天早会发一份。"

"明白了,"我打开 VS Code,"你需要一个程序:读取所有刀具的寿命记录,拿'累计加工时间'和'标准寿命'做比较,算出剩余寿命百分比,然后筛出两类刀——已经超期的(累计 > 标准)和即将到期的(剩余 < 20%)。输出一张清单,按紧急程度排序。这样每天早会,你直接把清单打印出来:红色的是必须立刻换的,黄色的是本周要准备的。"

我敲了几行代码:

import pandas as pd

import matplotlib.pyplot as plt

# 读取刀具寿命数据

df = pd.read_csv("tool_life.csv")

# 计算剩余寿命百分比

df["remaining_pct"] = (df["std_life_h"] - df["used_h"]) / df["std_life_h"] * 100

df["remaining_pct"] = df["remaining_pct"].clip(lower=0)

# 筛选到期刀具

expired = df[df["used_h"] >= df["std_life_h"]].copy()

expired["priority"] = "🔴 立即更换"

# 筛选预警刀具(剩余 < 20%)

warning = df[(df["used_h"] < df["std_life_h"]) & (df["remaining_pct"] < 20)].copy()

warning["priority"] = "🟡 近期更换"

# 合并清单

replacement_list = pd.concat([expired, warning]).sort_values("remaining_pct")

print(replacement_list[["tool_id", "tool_type", "machine", "used_h", "std_life_h", "remaining_pct", "priority"]])

"这只是核心逻辑,"我说,"完整版会用 OOP 封装:一个类管数据加载,一个类管数据清洗(处理缺失寿命值、统一磨损状态编码),一个类管寿命计算和阈值筛选,一个类管可视化(剩余寿命条形图、类型分布饼图、机床负载热力图)。数据自包含——用 numpy 合成一份刀具寿命 CSV,读者下载就能跑。"

老周凑近屏幕:"所以你这东西,就是把几千把刀的'用了多久'和'该用多久'比一下——超了的标红,快到的标黄,排个序打印出来。新人照着清单换刀,不会废活了。"

"对。而且还能做趋势分析,"我补充,"比如统计各类型刀具的平均实际寿命 vs 标准寿命,看看是不是某种刀的设定寿命偏短了——如果是,可以跟工艺部门反馈调整标准。刀具管理不是'到点就换',是'用数据证明该不该换'。"

一、实际应用场景(真实痛点)

场景设定:CNC 加工车间拥有数十台加工中心和数百把数控刀具,每把刀具在管理系统中记录安装时间、累计加工时间、标准寿命、已加工件数、磨损状态等字段。车间工具室需要定期生成刀具更换清单,防止刀具超期使用导致工件报废。现场常见痛点:刀具数据按"把"逐条记录,行数庞大(几百把活跃刀具),系统不提供按寿命阈值筛选的"到期清单"功能,依赖操作工凭经验判断,新人容易误判导致批量报废。

现场原话(叙事化):

"我不是不想管刀具寿命,"老周说,"每把刀的数据都在系统里,累计用了多久、标准寿命是多少,清清楚楚。但系统不会告诉我'现在有 12 把刀已经超期了、8 把快到了'——它只会在一把刀彻底报废的时候弹一个报警。那时候活已经废了,报警有什么用?我需要的是每天上班前,桌上有一张清单:哪些刀今天必须换、哪些这周要准备。"

核心矛盾:"逐把记录的刀具寿命明细"与"按阈值筛选的更换预警清单"之间的聚合断层。需要一个"刀具寿命筛选与更换清单生成程序",用

"pandas" 读取并计算剩余寿命,用

"numpy" 做阈值判断和统计,用

"matplotlib" 绘制剩余寿命分布图,输出结构化的刀具更换清单。

二、痛点分析(映射到滨州职业学院《先进制造技术》课程模型)

《先进制造技术》模块 本篇痛点对应

数控加工与CAD/CAM技术:数控刀具系统与寿命管理 刀具寿命模型:基于加工时间的刀具磨损规律与寿命阈值设定。

先进制造技术基础:先进制造系统的维护策略 预防性维护:基于寿命数据的刀具更换预警,避免突发报废。

FMS与先进生产管理:FMS 的刀具管理子系统 刀具调度与准备:提前生成更换清单,减少机床等待时间。

智能制造与数字孪生:加工过程的数字孪生 刀具磨损状态可视化:将寿命数据转化为直观的更换优先级。

一句话总结:我们需要构建一个"刀具寿命记录筛选与更换清单生成程序",用

"pandas" 读取并计算剩余寿命百分比,用

"numpy" 做阈值筛选,用

"matplotlib" 绘制寿命分布图,实现从逐把记录到更换预警清单的转化。

三、核心逻辑讲解(大白话)

3.1 问题本质:把刀具寿命想象成"汽车保养提醒"

把刀具寿命管理想象成"汽车的保养提醒系统":

* 标准寿命 = 保养周期:汽车每 5000 公里换机油,刀具每 6 小时加工时间换刀——都是"标准寿命"。

* 累计加工时间 = 已行驶里程:汽车仪表盘显示已跑 4800 公里,刀具记录显示已用 5.5 小时。

* 剩余寿命百分比 = 保养倒计时:(标准 - 已用) / 标准 × 100%。汽车剩 4% 该保养了,刀具剩 10% 该准备了。

* 更换清单 = 4S 店的"到期保养清单":把所有车按剩余保养里程排序,先保养快到周期的——对应车间里"先换快到期的刀"。

工业应用:

* pandas 计算剩余寿命:

"df["remaining_pct"] = (df["std_life_h"] - df["used_h"]) / df["std_life_h"] * 100",一行代码算出每把刀的剩余百分比。

* numpy 阈值筛选:

"np.where(df["used_h"] >= df["std_life_h"], "到期", np.where(df["remaining_pct"] < 20, "预警", "正常"))",向量化条件判断,比逐行 if-else 快几十倍。

* matplotlib 条形图:横轴刀具编号,纵轴剩余寿命百分比,红色标到期、黄色标预警、绿色标正常——一张图看清全车间刀具状态。

3.2 业务逻辑 → 代码映射

定义刀具寿命数据模型

│

▼ ToolDataLoader (pandas)

读取刀具 CSV:

pd.read_csv("tool_life.csv")

解析刀具编号、类型、机床、累计加工时间、标准寿命

│

▼ DataCleaner (pandas)

数据清洗:

处理缺失寿命值(删除或标记)

统一磨损状态编码(正常/注意/警告/报废 → 0/1/2/3)

│

▼ LifeCalculator (pandas/numpy)

寿命计算:

remaining_h = std_life_h - used_h

remaining_pct = remaining_h / std_life_h * 100

│

▼ ThresholdFilter (numpy)

阈值筛选:

到期:used_h >= std_life_h

预警:remaining_pct < 20%

正常:其余

│

▼ ReplacementListGenerator

更换清单生成:

按紧急程度排序(到期 → 预警 → 正常)

输出 CSV 清单

│

▼ ToolVisualizer (matplotlib)

可视化:

1. 剩余寿命水平条形图(按类型着色)

2. 刀具类型寿命分布箱线图

3. 各机床刀具数量与到期数对比

│

▼ SyntheticDataGenerator (numpy)

合成数据生成:

用 numpy 按类型生成刀具寿命数据

模拟不同刀具的寿命分布

确保数据自包含、可复现

3.3 为什么用向量化条件判断而不是逐行循环?

* 问题:300 把刀,每把写

"if used >= std: status = "到期"",代码冗长且慢。

* 处理策略:

"np.select()" 或

"np.where()" 向量化操作,一行代码完成全部判断,底层 C 加速。

* 工程合理性:车间可能有上千把刀在册,向量化是唯一合理的选择。

3.4 分析前后对比

维度 人工凭经验判断 Python 程序分析

判断依据 听声音、看刀纹(主观) 累计加工时间 vs 标准寿命(客观)

覆盖范围 只能关注正在用的刀 全部在册刀具

预警能力 报废了才发现 剩余 20% 就预警

输出形式 "感觉这把刀差不多了" 按紧急程度排序的更换清单

新人友好度 需要多年经验 照着清单换就行

四、OOP 代码实现

4.1 项目结构

cnc_tool_life_manager/

├── cnc_tool_life_manager/

│ ├── __init__.py

│ ├── data_loader.py # 刀具数据加载

│ ├── data_cleaner.py # 数据清洗

│ ├── life_calculator.py # 寿命计算

│ ├── threshold_filter.py # 阈值筛选

│ ├── replacement_list.py # 更换清单生成

│ ├── visualizer.py # 可视化

│ └── synthetic_data.py # 合成数据生成

├── tests/

│ ├── __init__.py

│ └── test_tool_life.py # 单元测试

├── results/

│ ├── replacement_list.csv # 刀具更换清单

│ ├── expired_only.csv # 已到期刀具

│ ├── warning_only.csv # 预警刀具

│ ├── remaining_life_bar.png # 剩余寿命条形图

│ ├── life_boxplot.png # 寿命分布箱线图

│ ├── machine_tool_heatmap.png # 机床刀具状态热力图

│ └── tool_report.txt # 分析报告

└── run_tool_life.py # 主程序入口

4.2 核心源码

<details>

<summary></summary>

"""数控刀具数据加载器"""

import pandas as pd

from pathlib import Path

from typing import Optional

class ToolDataLoader:

"""

数控刀具数据加载器

支持 CSV 格式的刀具寿命记录。

"""

def __init__(self, filepath: str, encoding: str = "utf-8"):

self.filepath = Path(filepath)

self.encoding = encoding

self._raw_df: Optional[pd.DataFrame] = None

def load(self,

tool_id_col: str = "tool_id",

type_col: str = "tool_type",

machine_col: str = "machine",

used_col: str = "used_h",

std_col: str = "std_life_h",

wear_col: str = "wear_status") -> pd.DataFrame:

"""

加载刀具寿命数据

Parameters

----------

tool_id_col : str

刀具编号列名

type_col : str

刀具类型列名

machine_col : str

安装机床列名

used_col : str

累计加工时间列名

std_col : str

标准寿命列名

wear_col : str

磨损状态列名

Returns

-------

pd.DataFrame

"""

if not self.filepath.exists():

raise FileNotFoundError(f"文件不存在: {self.filepath}")

self._raw_df = pd.read_csv(self.filepath, encoding=self.encoding)

# 列名标准化

col_aliases = {

tool_id_col: ["刀具编号", "tool_no", "tool_id", "id"],

type_col: ["刀具类型", "type", "tool_type", "category"],

machine_col: ["机床", "machine", "mc", "cnc"],

used_col: ["已用时间", "used", "used_h", "accumulated_time"],

std_col: ["标准寿命", "std_life", "std_life_h", "standard_life"],

wear_col: ["磨损状态", "wear", "wear_status", "condition"],

}

rename_map = {}

for target, aliases in col_aliases.items():

if target not in self._raw_df.columns:

for alias in aliases:

if alias in self._raw_df.columns:

rename_map[alias] = target

break

if rename_map:

self._raw_df = self._raw_df.rename(columns=rename_map)

return self._raw_df.copy()

def get_raw_data(self) -> Optional[pd.DataFrame]:

return self._raw_df.copy() if self._raw_df is not None else None

</details>

<details>

<summary></summary>

"""刀具数据清洗"""

import numpy as np

import pandas as pd

from typing import Optional

class DataCleaner:

"""

数控刀具数据清洗器

处理缺失值、统一磨损状态编码。

"""

# 磨损状态映射

WEAR_MAP = {

"正常": 0, "Normal": 0, "OK": 0, "0": 0,

"注意": 1, "Caution": 1, "Monitor": 1, "1": 1,

"警告": 2, "Warning": 2, "Warn": 2, "2": 2,

"报废": 3, "Failed": 3, "Fail": 3, "3": 3,

}

def __init__(self):

pass

def clean(self,

df: pd.DataFrame,

used_col: str = "used_h",

std_col: str = "std_life_h",

wear_col: str = "wear_status") -> pd.DataFrame:

"""

清洗刀具数据

Parameters

----------

df : pd.DataFrame

原始数据

used_col : str

累计加工时间列名

std_col : str

标准寿命列名

wear_col : str

磨损状态列名

Returns

-------

pd.DataFrame

"""

result = df.copy()

# 数值化

result[used_col] = pd.to_numeric(result[used_col], errors="coerce")

result[std_col] = pd.to_numeric(result[std_col], errors="coerce")

# 处理缺失值:删除关键字段为空且无法推断的行

result = result.dropna(subset=[used_col, std_col], how="all")

# 过滤异常值

result = result[result[used_col] >= 0]

result = result[result[std_col] > 0]

# 统一磨损状态编码

if wear_col in result.columns:

result["wear_code"] = result[wear_col].map(

lambda x: self.WEAR_MAP.get(str(x).strip(), -1)

)

else:

result["wear_code"] = -1

return result.reset_index(drop=True)

</details>

<details>

<summary></summary>

"""刀具寿命计算器"""

import numpy as np

import pandas as pd

from typing import Dict, Optional

class LifeCalculator:

"""

数控刀具寿命计算器

计算剩余寿命小时数和百分比。

"""

def __init__(self,

used_col: str = "used_h",

std_col: str = "std_life_h"):

self.used_col = used_col

self.std_col = std_col

def calculate(self, df: pd.DataFrame) -> pd.DataFrame:

"""

计算剩余寿命

Parameters

----------

df : pd.DataFrame

清洗后的数据

Returns

-------

pd.DataFrame

新增 remaining_h 和 remaining_pct 列

"""

result = df.copy()

result["remaining_h"] = (

result[self.std_col] - result[self.used_col]

).clip(lower=0)

result["remaining_pct"] = (

result["remaining_h"] / result[self.std_col] * 100

)

return result

def get_statistics(self, df: pd.DataFrame) -> Dict:

"""计算整体寿命统计"""

return {

"total_tools": len(df),

"avg_used": df[self.used_col].mean(),

"avg_std": df[self.std_col].mean(),

"avg_remaining_pct": df["remaining_pct"].mean(),

"min_remaining_pct": df["remaining_pct"].min(),

}

</details>

<details>

<summary></summary>

"""阈值筛选器"""

import numpy as np

import pandas as pd

from typing import Dict, Optional

class ThresholdFilter:

"""

数控刀具阈值筛选器

基于寿命阈值筛选到期和预警刀具。

"""

STATUS_EXPIRED = "到期"

STATUS_WARNING = "预警"

STATUS_NORMAL = "正常"

def __init__(self,

used_col: str = "used_h",

std_col: str = "std_life_h",

remaining_pct_col: str = "remaining_pct",

warning_threshold: float = 20.0):

self.used_col = used_col

self.std_col = std_col

self.remaining_pct_col = remaining_pct_col

self.warning_threshold = warning_threshold

def filter(self, df: pd.DataFrame) -> pd.DataFrame:

"""

阈值筛选

Parameters

----------

df : pd.DataFrame

含寿命计算结果的数据

Returns

-------

pd.DataFrame

新增 status 列

"""

result = df.copy()

conditions = [

result[self.used_col] >= result[self.std_col],

result[self.remaining_pct_col] < self.warning_threshold,

]

choices = [self.STATUS_EXPIRED, self.STATUS_WARNING]

result["status"] = np.select(conditions, choices, default=self.STATUS_NORMAL)

return result

def get_expired(self, df: pd.DataFrame) -> pd.DataFrame:

"""获取已到期刀具"""

return df[df["status"] == self.STATUS_EXPIRED].copy()

def get_warning(self, df: pd.DataFrame) -> pd.DataFrame:

"""获取预警刀具"""

return df[df["status"] == self.STATUS_WARNING].copy()

def get_normal(self, df: pd.DataFrame) -> pd.DataFrame:

"""获取正常刀具"""

return df[df["status"] == self.STATUS_NORMAL].copy()

def summary(self, df: pd.DataFrame) -> Dict[str, int]:

"""统计各状态数量"""

return {

self.STATUS_EXPIRED: (df["status"] == self.STATUS_EXPIRED).sum(),

self.STATUS_WARNING: (df["status"] == self.STATUS_WARNING).sum(),

self.STATUS_NORMAL: (df["status"] == self.STATUS_NORMAL).sum(),

}

</details>

<details>

<summary></summary>

"""更换清单生成器"""

import numpy as np

import pandas as pd

from typing import Optional

class ReplacementListGenerator:

"""

刀具更换清单生成器

按紧急程度排序,生成结构化更换清单。

"""

PRIORITY_MAP = {

"到期": 0,

"预警": 1,

"正常": 2,

}

def __init__(self,

tool_id_col: str = "tool_id",

type_col: str = "tool_type",

machine_col: str = "machine"):

self.tool_id_col = tool_id_col

self.type_col = type_col

self.machine_col = machine_col

def generate(self, df: pd.DataFrame) -> pd.DataFrame:

"""

生成更换清单

Parameters

----------

df : pd.DataFrame

已筛选和标记状态的数据

Returns

-------

pd.DataFrame

按优先级排序的更换清单

"""

result = df.copy()

# 添加优先级

result["priority"] = result["status"].map(self.PRIORITY_MAP)

# 按优先级和剩余寿命排序

result = result.sort_values(

["priority", "remaining_pct"],

ascending=[True, True],

)

# 选择输出列

output_cols = [

self.tool_id_col, self.type_col, self.machine_col,

"used_h", "std_life_h", "remaining_h",

"remaining_pct", "status", "wear_status",

]

available_cols = [c for c in output_cols if c in result.columns]

return result[available_cols].reset_index(drop=True)

def to_csv(self, df: pd.DataFrame, filepath: str) -> None:

"""导出为 CSV"""

df.to_csv(filepath, index=False, encoding="utf-8-sig")

</details>

<details>

<summary></summary>

"""刀具寿命可视化器"""

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

from pathlib import Path

from typing import Optional

plt.rcParams["font.sans-serif"] = ["SimHei", "DejaVu Sans"]

plt.rcParams["axes.unicode_minus"] = False

class ToolVisualizer:

"""数控刀具寿命可视化"""

STATUS_COLORS = {

"到期": "#E74C3C",

"预警": "#F39C12",

"正常": "#2ECC71",

}

TYPE_COLORS = {

"立铣刀": "#3498DB",

"面铣刀": "#9B59B6",

"钻头": "#1ABC9C",

"丝锥": "#E67E22",

"镗刀": "#34495E",

"球头铣刀": "#E91E63",

}

def __init__(self, results_dir: str = "results"):

self.results_dir = Path(results_dir)

self.results_dir.mkdir(exist_ok=True)

def plot_remaining_life_bar(self,

df: pd.DataFrame,

top_n: int = 30,

title: str = "刀具剩余寿命排行") -> None:

"""绘制剩余寿命水平条形图"""

# 取剩余寿命最低的 top_n

plot_df = df.nsmallest(top_n, "remaining_pct").copy()

plot_df = plot_df.sort_values("remaining_pct", ascending=True)

fig, ax = plt.subplots(figsize=(12, max(6, top_n * 0.35)))

colors = [

self.STATUS_COLORS.get(row["status"], "#BDC3C7")

for _, row in plot_df.iterrows()

]

bars = ax.barh(

plot_df["tool_id"].astype(str),

plot_df["remaining_pct"],

color=colors,

height=0.6,

)

ax.set_xlabel("剩余寿命 (%)", fontsize=12)

ax.set_title(title, fontsize=14, fontweight="bold")

ax.set_xlim(0, 105)

# 参考线

ax.axvline(x=20, color="#F39C12", linestyle="--",

linewidth=1, alpha=0.7, label="预警线 20%")

ax.axvline(x=0, color="#E74C3C", linestyle="--",

linewidth=1, alpha=0.7, label="到期线 0%")

ax.legend(loc="lower right")

# 标注数值

for bar, val in zip(bars, plot_df["remaining_pct"]):

ax.text(

bar.get_width() + 1,

bar.get_y() + bar.get_height() / 2,

f"{val:.1f}%",

va="center",

fontsize=8,

)

plt.tight_layout()

plt.savefig(self.results_dir / "remaining_life_bar.png",

dpi=150, bbox_inches="tight")

plt.close()

def plot_life_boxplot(self,

df: pd.DataFrame,

type_col: str = "tool_type",

used_col: str = "used_h",

title: str = "各类型刀具寿命分布") -> None:

"""绘制各类型刀具寿命分布箱线图"""

types = df[type_col].unique()

data = [df[df[type_col] == t][used_col].values for t in types]

fig, ax = plt.subplots(figsize=(10, 6))

bp = ax.boxplot(data, labels=types, patch_artist=True)

# 着色

for patch, t in zip(bp["boxes"], types):

patch.set_facecolor(self.TYPE_COLORS.get(t, "#BDC3C7"))

patch.set_alpha(0.7)

ax.set_ylabel("累计加工时间 (h)", fontsize=12)

ax.set_title(title, fontsize=14, fontweight="bold")

ax.tick_params(axis="x", rotation=30)

plt.tight_layout()

plt.savefig(self.results_dir / "life_boxplot.png",

dpi=150, bbox_inches="tight")

plt.close()

def plot_machine_heatmap(self,

df: pd.DataFrame,

machine_col: str = "machine",

status_col: str = "status") -> None:

"""绘制各机床刀具状态热力图"""

# 统计每台机床各状态数量

cross = df.groupby([machine_col, status_col]).size().unstack(fill_value=0)

if cross.empty:

return

fig, ax = plt.subplots(figsize=(10, max(4, len(cross) * 0.5)))

im = ax.imshow(cross.values, cmap="RdYlGn_r", aspect="auto")

ax.set_xticks(range(len(cross.columns)))

ax.set_xticklabels(cross.columns)

ax.set_yticks(range(len(cross.index)))

ax.set_yticklabels(cross.index)

ax.set_xlabel("状态", fontsize=12)

ax.set_ylabel("机床", fontsize=12)

ax.set_title("各机床刀具状态分布", fontsize=14, fontweight="bold")

plt.colorbar(im, ax=ax, label="刀具数量")

plt.tight_layout()

plt.savefig(self.results_dir / "machine_tool_heatmap.png",

dpi=150, bbox_inches="tight")

plt.close()

</details>

<details>

<summary></summary>

"""合成数据生成器"""

import numpy as np

import pandas as pd

from pathlib import Path

from typing import Optional

class SyntheticDataGenerator:

"""

数控刀具合成数据生成器

模拟多类型、多机床的刀具寿命数据。

"""

def __init__(self, rng: Optional[np.random.RandomState] = None):

self.rng = rng or np.random.RandomState(42)

# 刀具类型配置:(名称, 标准寿命均值 h, 标准寿命标准差, 磨损速率均值)

self.tool_types = [

("立铣刀", 6.0, 1.5, 1.0),

("面铣刀", 12.0, 2.0, 0.8),

("钻头", 4.0, 1.0, 1.2),

("丝锥", 3.0, 0.8, 1.5),

("镗刀", 20.0, 3.0, 0.5),

("球头铣刀", 5.0, 1.2, 1.1),

]

self.machines = [f"CNC-{i:02d}" for i in range(1, 13)] # 12 台机床

def generate(self,

n_tools: int = 300,

output_path: str = "tool_life.csv") -> pd.DataFrame:

"""

生成合成刀具寿命数据

Parameters

----------

n_tools : int

刀具数量

output_path : str

输出路径

Returns

-------

pd.DataFrame

"""

records = []

for i in range(n_tools):

# 随机选择刀具类型

type_name, std_mean, std_std, wear_rate = self.tool_types[

self.rng.randint(0, len(self.tool_types))

]

# 标准寿命(正态分布)

std_life = max(1.0, self.rng.normal(std_mean, std_std))

# 已用时间(取决于磨损速率和随机波动)

# 模拟部分刀具已超期、部分接近寿命、部分正常

usage_factor = self.rn

利用AI解决实际问题,如果你觉得这个工具好用,欢迎关注长安牧笛!

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询