【全栈之路】10 天掌握 Python 开发(6)文件读写和内建模块

140 阅读6分钟

文件读写

文件读写是编程中常见的 IO 操作。

任务

现有一个 books.txt ,读取并检查是否包含中国四大名著,如有缺失,请补充缺失的名著并写入该文件中。

JavaScript 实现

import fs from 'fs';

const data = fs.readFileSync('books.txt', 'utf8');
const books = data.split('\n');
const classics = ['红楼梦', '西游记', '水浒传', '三国演义'];
const missingClassics = classics.filter(classic => !books.includes(classic));

if (missingClassics.length === 0) {
    console.log('文件中已包含中国四大名著。');
    return;
}

const missingClassicsText = missingClassics.join('\n');
fs.appendFileSync('books.txt', `\n${missingClassicsText}`, 'utf8');
console.log(`已补充缺失的名著到文件中: ${missingClassicsText}`);

Python 实现

# 读取books.txt文件内容
with open('books.txt', 'r', encoding='utf-8') as file:
    books = file.read().splitlines()

# 检查是否包含中国四大名著
classics = ['红楼梦', '西游记', '水浒传', '三国演义']
missing_classics = [classic for classic in classics if classic not in books]

if len(missing_classics) == 0:
    print('文件中已包含中国四大名著。')
else:
    # 补充缺失的名著到文件中
    with open('books.txt', 'a', encoding='utf-8') as file:
        file.write('\n' + '\n'.join(missing_classics))
    print(f'已补充缺失的名著到文件中: {", ".join(missing_classics)}')

代码解读

  • Python 使用 open() 函数打开文件,使用 with 语句确保文件被正确关闭。
  • Python 使用 wra 指定文件的写、读、追加访问模式。

差异速览

特性JavaScriptPython
读取文件fs.readFileSync(file, 'utf-8')open(file, 'r', encoding='utf-8').read()
写入文件fs.writeFileSync(file, data, 'utf-8')open(file, 'w', encoding='utf-8').write()
追加文件fs.appendFileSync(file, data, 'utf-8')open(file, 'a', encoding='utf-8').write()

相关资源


datetime 模块

Python 中的 datetime 模块提供了处理日期、时间和时间间隔的类和函数。

任务

小明的生日是 1992 年 1月 15 日,设计一个程序,计算他的年龄和距离下次生日的天数。

JavaScript 实现

// 获取当前日期
const currentDate = new Date();

// 设置小明的生日
const birthday = new Date(1992, 0, 15);

// 计算年龄
let age = currentDate.getFullYear() - birthday.getFullYear();

// 检查是否已经过了生日
if (currentDate.getMonth() < birthday.getMonth() || (currentDate.getMonth() === birthday.getMonth() && currentDate.getDate() < birthday.getDate())) {
  age--;
}

// 计算距离下次生日的天数
const nextBirthday = new Date(currentDate.getFullYear(), birthday.getMonth(), birthday.getDate());
if (currentDate > nextBirthday) {
  nextBirthday.setFullYear(nextBirthday.getFullYear() + 1);
}

const daysUntilNextBirthday = Math.ceil((nextBirthday - currentDate) / (1000 * 60 * 60 * 24));

// 输出结果
console.log("年龄: " + age);
console.log("距离下次生日的天数: " + daysUntilNextBirthday);

Python 实现

import datetime

# 获取当前日期
current_date = datetime.date.today()

# 设置小明的生日
birthday = datetime.date(1992, 1, 15)

# 计算年龄
age = current_date.year - birthday.year
if current_date.month < birthday.month or (current_date.month == birthday.month and current_date.day < birthday.day):
    age -= 1

# 计算距离下次生日的天数
next_birthday = datetime.date(current_date.year, birthday.month, birthday.day)
if current_date > next_birthday:
    next_birthday = datetime.date(current_date.year + 1, birthday.month, birthday.day)

days_until_next_birthday = (next_birthday - current_date).days

# 输出结果
print("年龄:", age)
print("距离下次生日的天数:", days_until_next_birthday)

代码解读

  • 在 Python 中,从 datetime 模块中导入 date 用于操作日期,而 JavaScript 使用 Date
  • 在 Python 中,可以直接使用 +- 算术运算符对日期进行运算。

差异速览

特性JavaScriptPython
创建日期时间对象new Date(1992, 0, 15)datetime.datetime(1992, 1, 15)
当前本地日期时间new Date()datetime.datetime.now()
当前 UTC 日期时间 new Date().toUTCString()datetime.datetime.utcnow()
日期格式化moment(myDateTime).format(format)my_datetime.strftime(format)
获取年、月、日myDateTime.getFullYear()
myDateTime.getMonth() + 1
myDateTime.getDate()
my_datetime.year
my_datetime.month
my_datetime.day
获取时、分、秒myDateTime.getHours()
myDateTime.getMinutes()
myDateTime.getSeconds()
my_datetime.hour
my_datetime.minute
my_datetime.second
添加时间间隔myDateTime.setSeconds(date.getSeconds() + secondsToAdd)new_datetime = my_datetime + timedelta(seconds=secondsToAdd)
减去时间间隔myDateTime.setSeconds(date.getSeconds() - secondsToSubtract)new_datetime = my_datetime - timedelta(seconds=secondsToSubtract)
比较日期dateTime1.getTime() - dateTime2.getTime()datetime1 - datetime2

:::tip timedelta 如基本的日期时间运算无法满足需求,可以借助 timedelta,它是一个用于表示时间间隔的类。它可以用来执行日期和时间的加减操作,以及计算时间差。

from datetime import timedelta,datetime
current_datetime = datetime.now()

# 获取 2 天 3 小时 30 分钟 后的日期时间
new_datetime = current_datetime + timedelta(days=2, hours=3, minutes=30)
print(new_datetime)

:::

相关资源


os 模块

Python 中的 os 模块提供了用于操作文件和目录以及访问与系统相关的信息的函数。

任务

编写一个程序,列出给定目录中的所有文件和目录。该程序应打印每个项的名称,并指示它是文件还是目录。

JavaScript 实现

import fs from 'fs';
import path from 'path';

function listItems(directory) {
  fs.readdir(directory, (err, items) => {
    if (err) {
      console.log(`读取目录时出错:${err}`);
      return;
    }

    items.forEach((item) => {
      const itemPath = path.join(directory, item);
      fs.stat(itemPath, (err, stats) => {
        if (err) {
          console.log(`获取${item}的信息时出错:${err}`);
        } else {
          console.log(`${item}${stats.isDirectory() ? '目录' : '文件'}`);
        }
      });
    });
  });
}

listItems('../');

Python 实现

import os

def list_items(directory):
    items = os.listdir(directory)

    for item in items:
        item_path = os.path.join(directory, item)
        if os.path.isdir(item_path):
            print(f"{item}:目录")
        else:
            print(f"{item}:文件")

list_items('../')

差异速览

特性JavaScriptPython
文件或目录是否存在fs.existsSync(path)os.path.exists(path)
创建目录fs.mkdir(path, [options], callback)os.mkdir(path)
列出目录fs.readdir(path, [options], callback)os.listdir(path)

相关资源


json 模块

Python 中的 json 模块提供了处理 JSON 数据的函数。

任务

设计一个程序,读取 database.json 中的 port属性的值,并将其修改为 5432,然后写回到该文件中。

JavaScript 实现

import fs from 'fs';

// 读取JSON文件
fs.readFile('database.json', 'utf8', (err, data) => {
  if (err) {
    console.error(err);
    return;
  }

  try {
    // 将JSON数据解析为JavaScript对象
    const jsonData = JSON.parse(data);

    // 修改port属性的值为5432
    jsonData.port = 5432;

    // 将JavaScript对象转换回JSON字符串
    const updatedData = JSON.stringify(jsonData, null, 2);

    // 将更新后的JSON字符串写回文件
    fs.writeFile('database.json', updatedData, 'utf8', (err) => {
      if (err) {
        console.error(err);
        return;
      }

      console.log('JSON文件已更新');
    });
  } catch (err) {
    console.error('无法解析JSON文件:', err);
  }
});

Python 实现

import json

# 读取JSON文件
with open('database.json', 'r') as file:
    json_data = json.load(file)

# 修改port属性的值为5432
json_data['port'] = 5432

# 将更新后的JSON数据写回文件
with open('database.json', 'w') as file:
    json.dump(json_data, file, indent=2)

print('JSON文件已更新')

代码解读

  • Python 使用 json.dumps() 将对象转换为 JSON 字符串,JavaScript 中的 JSON.stringify() 与之等效。
  • Python 使用 json.loads() 将 JSON 字符串转换为字典,JavaScript 中的 JSON.parse() 与之等效。

:::danger 中文编码问题 将 Python 对象转换为 JSON 字符串时,如果遇到中文乱码问题,可以使用 ensure_ascii=False 参数确保中文字符以原始的 Unicode 形式进行编码,而不是 ASCII 编码。例如:

import json

data = {"name": "张三", "age": 25}
json_str = json.dumps(data, ensure_ascii=False)
print(json_str)

:::

差异速览

特性JavaScriptPython
解析 JSON 字符串JSON.parse(myStr)json.loads(my_str)
将对象转为 JSON 字符串JSON.stringify(myObj)json.dumps(my_obj)
读取 JSON 文件-json.load(my_file)
写入 JSON 文件-json.dump(my_file)

:::danger Python 中使用 json.loads(my_str)json.load(my_file) 会将得到一个 字典列表(取决于 JSON 数据的结构)。对于字典以及嵌套字典而言,需要特别注意 Python 语法不支持使用点运算符(.)获取值,你需要需要使用 [] 获取值。

import json

my_dict = json.loads('{"name": "luckrnx09", "age": 18}')
print(my_dict.name) # Error: 'dict' object has no attribute 'name'
print(my_dict['name']) # luckrnx09

:::

相关资源


re 模块

正则表达式是编程语言中用于搜索、匹配和操作文本的强大工具,Python 中的 re 模块提供了对正则表达式的支持。

任务

编写一个程序,接受一个电子邮件地址列表,并使用正则表达式提取每个地址的用户名和域名。

JavaScript 实现

const emailAddresses = [
  "john.doe@example1.com",
  "jane.smith@example2.com",
  "foo@bar.com",
];

const regex = /([^@]+)@(.+)/;

emailAddresses.forEach((email) => {
  const [_, username, domain] = email.match(regex);
  console.log(`Username: ${username}, Domain: ${domain}`);
});

Python实现:

import re

email_addresses = [
  "john.doe@example1.com",
  "jane.smith@example2.com",
  "foo@bar.com",
]

regex = re.compile(r"([^@]+)@(.+)")

for email in email_addresses:
  match = regex.match(email)
  if match:
    username, domain = match.groups()
    print(f"Username: {username}, Domain: {domain}")

:::tip Python 中的字符串前面添加 r,表示不对字符串字面量进行转义。 :::

代码解读

  • 在 JavaScript 中,使用 /.../new Regex(...)定义正则表达式,而在 Python 中,使用 re.compile() 函数创建正则表达式。

差异速览

特性JavaScriptPython
创建正则表达式const myReg = /pattern/;new Regex(pattern)my_regex = re.compile(r'pattern')
匹配正则表达式myReg.test(myStr)my_regex.match(my_str)
查找第一个匹配项myReg.exec(myStr)my_regex.search(my_str)
查找所有匹配项myStr.match(myReg)my_regex.findall(my_str)
替换匹配项myStr.replace(myReg, replacement)my_regex.sub(replacement, my_str)
使用正则表达式拆分字符串myStr.split(myReg)my_regex.split(my_str)

:::tip 除了使用 re.compile() 预先创建正则表达式外,你还可以直接使用 re 模块的 sub、'search' 等方法实现相同的功能,如:

import re

re.search(r'pattern', my_str)
re.split(r'pattern', my_str)

:::

相关资源


random 模块

Python 中的 random 模块提供了生成随机数的函数。

任务

生成一个包含随机大小写字母、数字的 32 位密码。

JavaScript 实现

function generatePassword() {
  var length = 32;
  var charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  var password = "";
  
  for (var i = 0; i < length; i++) {
    var randomIndex = Math.floor(Math.random() * charset.length);
    password += charset.charAt(randomIndex);
  }
  
  return password;
}

var password = generatePassword();
console.log(password);

Python 实现

import random
import string

def generate_password():
    length = 32
    charset = string.ascii_letters + string.digits
    password = ''.join(random.choice(charset) for _ in range(length))
    return password

password = generate_password()
print(password)

代码解读

  • Python 中 string 模块的 ascii_letters 包含了所有的小写和大写字母,digits 包含了所有的数字。
  • Python 使用 random.randint() 函数生成给定最小值和最大值之间的随机整数,而在 JavaScript 中,我们使用自定义函数 getRandomInt() 利用 Math.random() 实现相同的功能。

差异速览

特性JavaScriptPython
生成 0 到 1 之间的随机数Math.random()random.random()
在范围内生成随机整数Math.floor(Math.random() * (max - min + 1)) + minrandom.randint(min_val, max_val)
从列表中随机选择 1 个元素-random.choice(sequence)
对列表中的元素进行洗牌-random.shuffle(sequence)
在范围内生成随机浮点数-random.uniform(min_val, max_val)
设置随机种子-random.seed(seed_val)

相关资源


math 模块

Python 中的 math 模块提供了各种数学函数和常量。

任务

设计一个程序,通过输入半径来计算圆的面积。

JavaScript 实现

const radius = 5;
const area = Math.PI * Math.pow(radius, 2);
console.log(area);

Python 实现

import math

radius = 5
area = math.pi * math.pow(radius, 2)
print(area)

差异速览

特性JavaScriptPython
绝对值Math.abs(x)abs(x)
四舍五入到最近的整数Math.round(x)round(x)
向上取整(不小于x的最小整数)Math.ceil(x)math.ceil(x)
向下取整(不大于x的最大整数)Math.floor(x)math.floor(x)
指数运算Math.pow(x, y)pow(x, y)
平方根Math.sqrt(x)math.sqrt(x)
三角函数Math.sin(x)Math.cos(x)Math.tan(x)Math.asin(x)Math.acos(x)Math.atan(x)math.sin(x)math.cos(x)math.tan(x)math.asin(x)math.acos(x)math.atan(x)
将角度转换为弧度-math.radians(x)
将弧度转换为角度-math.degrees(x)

相关资源


本书的内容完全免费,开源地址:github.com/luckrnx09/p…