from pathlib import Path# 从train目录下的文件中提取文本t_train = []for file_path in Path(raw_train_path).glob("*.xml"):list_train_doc_1 = [r.text for r in ET.parse(file_path).getroot()[0]]train_doc_1 = " ".join(t for t in list_train_doc_1)t_train.append(train_doc_1)t_train_docs = " ".join(t_train)# 从测试目录的文件中提取文本t_test = []for file_path in Path(raw_test_path).glob("*.xml"):list_test_doc_1 = [r.text for r in ET.parse(file_path).getroot()[0]]test_doc_1 = " ".join(t for t in list_test_doc_1)t_test.append(test_doc_1)t_test_docs = " ".join(t_test)我们可以通过将重复的代码合并到一个名为extract_texts_from_multiple_files的单一函数中来消除重复,该函数从指定位置的多个文件中提取文本 。
def extract_texts_from_multiple_files(folder_path) -> str:
all_docs = []for file_path in Path(folder_path).glob("*.xml"):list_of_text_in_one_file = [r.text for r in ET.parse(file_path).getroot()[0]]text_in_one_file = " ".join(list_of_text_in_one_file)all_docs.append(text_in_one_file)return " ".join(all_docs)现在你可以使用这个功能从不同的地方提取文本,而不需要重复编码 。
t_train = extract_texts_from_multiple_files(raw_train_path)t_test= extract_texts_from_multiple_files(raw_test_path)一个层次的抽象抽象水平是指一个系统的复杂程度 。高层次指的是对系统更概括的看法,而低层次指的是系统更具体的方面 。
在一个代码段内保持相同的抽象水平是一个很好的做法,使代码更容易理解 。
以下函数证明了这一点:
def extract_texts_from_multiple_files(folder_path) -> str:all_docs = []for file_path in Path(folder_path).glob("*.xml"):list_of_text_in_one_file = [r.text for r in ET.parse(file_path).getroot()[0]]text_in_one_file = " ".join(list_of_text_in_one_file)all_docs.append(text_in_one_file)return " ".join(all_docs)该函数本身处于较高层次,但 for 循环内的代码涉及与XML解析、文本提取和字符串操作有关的较低层次的操作 。
为了解决这种抽象层次的混合,我们可以将低层次的操作封装在extract_texts_from_each_file函数中:
def extract_texts_from_multiple_files(folder_path: str) -> str:all_docs = []for file_path in Path(folder_path).glob("*.xml"):text_in_one_file = extract_texts_from_each_file(file_path)all_docs.append(text_in_one_file)return " ".join(all_docs)def extract_texts_from_each_file(file_path: str) -> str:list_of_text_in_one_file = [r.text for r in ET.parse(file_path).getroot()[0]]return " ".join(list_of_text_in_one_file)这为文本提取过程引入了更高层次的抽象,使代码更具可读性 。
描述性的名称一个函数的名字应该有足够的描述性,使用户不用阅读代码就能理解其目的 。长一点的、描述性的名字比模糊的名字要好 。例如,命名一个函数get_texts就不如命名为extract_texts_from_multiple_files来得清楚 。
然而,如果一个函数的名字变得太长,比如retrieve_data_extract_text_and_save_data,这说明这个函数可能做了太多的事情,应该拆分成更小的函数 。
少于四个参数随着函数参数数量的增加,跟踪众多参数之间的顺序、目的和关系变得更加复杂 。这使得开发人员难以理解和使用该函数 。
def main(url: str,zip_path: str,raw_train_path: str,raw_test_path: str,processed_train_path: str,processed_test_path: str,) -> None:get_raw_data(url, zip_path)t_train, t_test = get_train_test_docs(raw_train_path, raw_test_path)save_train_test_docs(processed_train_path, processed_test_path, t_train, t_test)为了提高代码的可读性,你可以用数据类或Pydantic模型将多个相关参数封装在一个数据结构中 。
from pydantic import BaseModelclass RawLocation(BaseModel):url: strzip_path: strpath_train: strpath_test: strclass ProcessedLocation(BaseModel):path_train: strpath_test: strdef main(raw_location: RawLocation, processed_location: ProcessedLocation) -> None:get_raw_data(raw_location)t_train, t_test = get_train_test_docs(raw_location)save_train_test_docs(processed_location, t_train, t_test)我如何写这样的函数?在编写Python函数时,你不需要记住所有这些最佳实践 。衡量一个Python函数质量的一个很好的指标是它的可测试性 。如果一个函数可以很容易地被测试,这表明该函数是模块化的,执行单一的任务,并且没有重复的代码 。
def save_data(processed_path: str, processed_data: str) -> None:with open(processed_path, "w") as f:f.write(processed_data)def test_save_data(tmp_path):processed_path = tmp_path / "processed_data.txt"processed_data = https://www.isolves.com/it/cxkf/yy/Python/2023-08-28/"Sample processed data"save_data(processed_path, processed_data)assert processed_path.exists()assert processed_path.read_text() == processed_data
推荐阅读
- 手把手将Visual Studio Code变成Python开发神器
- OpenHarmony组件复用示例
- AI可以读取人心了 心中的小秘密还能藏多久?
- 将 Pandas 换为交互式表格的 Python 库
- Django和Flask:Python Web开发的不同选择
- 肉松面包可以加热吗 肉松面包能加热吗
- 微信网名女生小清新好听 微信网名女生小清新可爱
- 《披荆斩棘》大爆三宝,赵丽颖的可靠,高启盛的后劲,林志颖的脸
- 秋葵切开后可以放冰箱第二天煮吗 秋葵切开了可以放多久
- 粉丝可以不泡水直接煮吗
