分类目录归档:Python

如何优雅地用 Python 为项目安装和创建 Python 包依赖?

在接手他人项目的时候,或者创建一个项目依赖时:

  • 如果项目用 anaconda,项目就需要导出一个 environment.yaml ,存在下面问题:

    • 文件过大:Anaconda 的 environment.yaml 往往包含了大量的包和依赖,其中一些可能与项目不直接相关。这不仅增加了环境搭建的复杂性,而且可能引入不必要的依赖。
    • 平台依赖性:environment.yaml 文件可能包含特定于操作系统或平台的包,这会在不同系统间迁移项目时造成问题。
    • 最大的问题是:environment.yaml 文件无法复现用 whl 包或者 gz 包等这些本地包安装的库。也无法安装第三方源安装的包,比如 pytorch。
  • 如果项目用 pip,项目就需要导出一个 requirements.txt 文件,但这种方法也有其局限性:

    • 不完整的依赖管理:requirements.txt 文件通常只列出了项目直接依赖的包,而不包括这些包的依赖(即二级依赖)。这可能导致缺失依赖或版本冲突。
    • 版本冲突问题:在没有明确指定依赖版本的情况下,pip 可能会安装最新版本的包,这可能与项目的实际兼容性不符。
    • 安装顺序问题:pip 不保证按照 requirements.txt 中的顺序安装包,这在某些包有特定安装顺序要求时可能导致问题。

相信平常接手过其他人项目的人应该很清楚其中的血与泪,因此我们更推荐 Poetry,它有以下的优点:

  1. 更简洁的依赖文件:Poetry 使用 pyproject.toml 来管理依赖,这使得依赖声明更为简洁和直观。同时,Poetry 通过 poetry.lock 文件锁定具体版本,确保环境的一致性。
  2. 完整的依赖解析:Poetry 能够解析和管理项目的全部依赖(包括子依赖),减少了版本冲突的可能性。
  3. 虚拟环境管理:Poetry 自动管理虚拟环境,无需手动创建和激活,简化了环境配置的步骤。
  4. 更好的跨平台兼容性:Poetry 在处理依赖时考虑了跨平台的问题,使得在不同操作系统间迁移和设置项目变得更加容易。
  5. 支持本地包和多源包:Poetry 支持从本地路径、私有仓库或多个源安装包,提供了比 pip 更灵活的包管理选项。

Poetry 类似于 pip,能帮助你进行包管理(dependency management),但它比 pip 强大得多,因为它还包含了以下 pip 没有的功能:

  • 虚拟环境管理
  • 包依赖管理
  • 包的打包与发布

虚拟环境管理

指的是使用内置的 venv 或 virtualenv 包来创建和管理 Python 的虚拟环境,不同的虚拟环境之间是相互独立的,也就是说,它们对应的路径各不相同。

包管理

包管理(dependency management) 指的是使用像 pip 这类的包管理器来管理 Python 环境(不一定是虚拟环境),即管理环境中安装的所有包(package、dependency)及其版本。

依赖性管理

在这个语境下,dependency 基本上就是你安装的包(package)。

包的“依赖性管理”(重要) 这个有点难以定义,因为它不是一个有广泛共识的术语,在英文中也难以找到对应的单词。这里指的是管理包之间的“依赖关系”和“版本冲突”这两件事:

  • 依赖关系指的是,当一个包被安装时,它所依赖的包也必须一并安装(这个比较简单)。相反,当一个包被移除时,它所依赖的包也必须一并移除——除非这些包还被其他包所依赖(这就复杂了)。
  • 而版本冲突,指的是单一包被两个以上的包所依赖,但不同的包对依赖的包有不同的最低或最高版本要求,若两者要求的范围“没有交集”,则会发生冲突,导致包失效或无法安装。

这两大问题,都是 pip 无法解决的,也是 Python 开发上的两大痛点。

How? Conda + Poetry

由于我们大多数人都有 Conda,用 Conda 创建 Python 版本,然后用 Poetry 创建虚拟环境,然后管理包依赖。

Conda 创建预期 Python

conda 在这里用于创建特定的 Python 版本。

  • 如果是接手项目,参考 pyproject.toml 中内容(如下),如果发现是 Python 3.8,则创建一个环境 conda create -n python_env_name python=3.8

    [tool.poetry.dependencies]
    python = "^3.8"
  • 如果是自己创建项目,只需要用 conda 创建自己想要的环境。

安装 Poetry

pip install poetry==1.7.1 -i https://pypi.tuna.tsinghua.edu.cn/simple

下面的指令都需要在包含 pyproject.toml 文件的项目目录中运行:

  1. 打开终端或命令提示符:首先,确保你可以访问命令行界面。
  2. 定位到你的项目目录:使用 cd 命令切换到包含 pyproject.toml 文件的项目目录。

    cd path/to/your/project

创建项目虚拟环境

  1. 确认pyproject.toml存在:
  • 若存在 pyproject.toml,则运行

    conda activate python_env_name    # 激活对应 Python 环境
    poetry env use python # 使用当前 conda

    使用 Poetry 创建项目的虚拟环境是一个自动化过程,这可以确保你的项目依赖被正确地隔离。

  • 若不存在pyproject.toml,则运行下一节 初始化项目的 pyproject.toml

  1. 初始化虚拟环境:在项目目录中,运行以下命令来使用 Poetry 创建虚拟环境。
poetry env use python   #   使用当前环境的 Python
poetry shell    #   进入虚拟环境

这个命令会创建一个新的虚拟环境(如果尚未创建),并激活它。如果虚拟环境已经存在,它会被重新激活。

  1. 检查虚拟环境信息:要确认虚拟环境已经被正确创建并激活,可以使用以下命令:
poetry env info

这个命令会显示关于当前激活的虚拟环境的信息,包括它的位置和使用的 Python 版本。

初始化项目的 pyproject.toml

如果是创建项目则需要用 poetry init 初始化项目文件,它会引导你创建一个 pyproject.toml 文件,这个文件是 Poetry 用来管理项目的依赖和各种配置的主要文件。以下是如何使用 poetry init 的步骤:

  1. 运行 poetry init 命令:在项目目录中,运行以下命令:

    poetry init
  2. 跟随提示进行操作:执行该命令后,Poetry 会引导你通过一系列问题来创建 pyproject.toml 文件。这包括:

    • 项目的基本信息:例如项目名称、版本、描述、作者等。
    • 定义依赖:Poetry 会询问是否要交互式地定义项目依赖。如果选择是,它会提示你搜索并添加包。你也可以跳过这一步,稍后手动添加依赖到 pyproject.toml 文件中。
    • 开发依赖:类似地,Poetry 也会询问是否要添加开发时依赖(例如,用于测试或构建的包)。
  3. 完成并查看 pyproject.toml:完成上述步骤后,Poetry 会创建 pyproject.toml 文件。打开这个文件,确认里面的内容是否符合你的预期。
  4. (可选)手动编辑 pyproject.toml:如果需要,你可以直接编辑这个文件来添加或修改依赖、修改项目信息等。如果你想要用第三方源(比如清华源),请看下下节【添加镜像源】。

安装项目依赖

  • 如果是接手项目,直接 poetry install就可以,它会自动根据依赖使用最佳的安装方式。poetry install 命令是 Poetry 中用于安装项目依赖的主要命令。当你在项目中运行此命令时,它会根据 pyproject.toml 文件和 poetry.lock 文件(如果存在)安装所有必要的依赖。以下是使用 poetry install 的基本步骤:

    1. 运行 poetry install 命令:在项目目录中,运行以下命令:

      poetry install

      这个命令将会:

      • 检查 pyproject.toml 文件中列出的依赖。
      • 如果存在 poetry.lock 文件,Poetry 会根据该文件中锁定的版本来安装依赖。这确保了环境的一致性。
      • 如果不存在 poetry.lock 文件,Poetry 会解析 pyproject.toml 中的依赖并生成一个新的 poetry.lock 文件。
      • 安装所有必要的依赖到项目的虚拟环境中。如果项目的虚拟环境还未创建,Poetry 会先创建它。
    2. 验证安装:安装完成后,你可以通过运行项目或其测试来验证依赖是否正确安装。

poetry init 是一个非常方便的命令,特别是当你开始一个新项目而还未确定所有依赖时。它不仅帮助你创建了项目的基本结构,还使得后续的依赖管理变得简单。此外,即使在项目已经开始的情况下,poetry init 也可以用于引入 Poetry 作为依赖管理工具。在这种情况下,它将帮助你创建 pyproject.toml 文件,而不会影响现有的项目文件。

添加镜像源

poetry source add 用于向 Poetry 项目添加一个新的包源(repository)。这在你需要从不是默认的 PyPI 源安装包时非常有用,比如你可能需要从私有仓库或其他第三方仓库安装包。以下是如何使用 poetry source add 的步骤:

  1. 添加新的包源:使用 poetry source add 命令添加一个新的源。这个命令通常需要三个主要参数:源的名称、源的 URL 和源的类型(默认为 legacy)。

    poetry source add   [--type ]

    例如,如果你想添加一个名为 my-private-repo 的私有仓库,你可以运行:

    poetry source add my-private-repo https://private-repo.example.com/simple/

    如果该仓库是一个 PyPI 兼容仓库(例如,使用 PyPI 格式的私有 Artifactory 仓库),你可能不需要指定 --type 参数,因为默认值 legacy 适用于标准的 PyPI 格式仓库。

  2. 验证源是否已添加:完成添加源后,你可以通过查看 pyproject.toml 文件来验证新源是否已被正确添加。该文件现在应该包含一个 [tool.poetry.source] 部分,其中列出了刚刚添加的源信息。
  3. 安装或更新依赖:添加新的源之后,你可以通过 poetry addpoetry update 命令来安装或更新依赖,Poetry 将会考虑这些新添加的源。

使用 poetry source add 命令可以扩展你的项目以从多个源获取依赖,这在使用私有包或特定于项目的包时特别有用。

例子,添加清华源作为默认源:

poetry source add tsinghua https://pypi.tuna.tsinghua.edu.cn/simple --default

增加依赖包

poetry add 命令是用于向 Poetry 管理的项目中添加依赖的。当你执行这个命令时,Poetry 会将指定的包添加到你的 pyproject.toml 文件中,并自动更新 poetry.lock 文件,以确保依赖的一致性。以下是使用 poetry add 的基本步骤:

  1. 添加一个依赖:使用 poetry add <package-name> 命令添加一个依赖。例如,如果你想添加 requests 包,你应该运行:

    poetry add requests

    这会将 requests 包添加到你的项目中,并自动选择一个合适的版本。

  2. 指定依赖版本:如果你需要指定依赖的特定版本或版本范围,你可以在包名后加上版本号。例如:

    poetry add requests@^2.25.1 
    poetry add requests==2.25.1 # 或者像 pip 一样。

    这将会安装 requests 包的 2.25.1 版本或更高的兼容版本(但不会升级到 3.x 版本)。

  3. 添加开发依赖:如果你想添加一个仅在开发过程中使用的包(如测试框架),可以使用 -D--dev 选项。例如,添加测试库 pytest 作为开发依赖:

    poetry add pytest --dev
  4. 等待命令执行完成:Poetry 会解析和安装依赖,并更新 pyproject.tomlpoetry.lock 文件。
  5. 验证依赖:添加完依赖后,可以通过运行项目来验证新添加的依赖是否按预期工作。

poetry add 命令简化了依赖管理过程,它不仅添加了依赖,还考虑了版本兼容性和项目的整体依赖树。通过自动更新 pyproject.tomlpoetry.lock 文件,它确保了项目依赖的一致性和项目团队成员之间的依赖同步。

移除依赖包

在 Poetry 中删除一个包,即从项目的依赖中移除它,使用 poetry remove 命令实现。命令会从 pyproject.toml 文件中删除指定的包,并更新 poetry.lock 文件以反映这一变化。以下是详细步骤:

  1. 删除一个依赖包:使用 poetry remove <package-name> 命令删除一个依赖。例如,如果你想从项目中移除 requests 包,你应该运行:

    poetry remove requests

    这会从你的项目依赖中移除 requests 包,并更新 pyproject.tomlpoetry.lock 文件。

  2. 删除开发依赖:如果要删除的包是一个开发依赖(即原本是使用 poetry add --dev 添加的),你同样使用 poetry remove 命令,Poetry 会自动识别它是开发依赖并进行处理。

    poetry remove 
  3. 等待命令执行完成:Poetry 会处理依赖的移除,并更新相关文件。
  4. 验证依赖已被移除:完成命令执行后,你可以检查 pyproject.toml 文件以确认该依赖已被移除。同时,确保项目在移除了该依赖后仍然按预期运行。

通过使用 poetry remove 命令,你可以轻松地管理项目的依赖列表,确保它们保持最新且与项目需求一致。

如何发布

  • 编写 README 文件:一个清晰的 README 文件对于你的包的可用性至关重要。确保它包含了项目描述、安装指南、使用示例和任何必要的文档链接。

  • 检查版本号:确保 pyproject.toml 文件中的版本号是正确的,并且遵循语义化版本控制规则。如果是首次发布,通常版本号会是 0.1.01.0.0

  • 运行 poetry lock 命令poetry lock 命令在 Poetry 中用于创建或更新 poetry.lock 文件,这个文件精确记录了项目所有依赖(包括子依赖)的具体版本。通过使用这个命令,你可以确保在不同环境中重现相同的依赖安装,这对于项目的一致性和稳定性至关重要。以下是使用 poetry lock 命令的步骤:

    1. 在项目目录中,运行以下命令:

      poetry lock

      这个命令会执行以下操作:

      • 解析 pyproject.toml 文件中指定的依赖,包括版本范围。
      • 生成或更新 poetry.lock 文件,其中包含了所有依赖的精确版本号和其他必要信息,以确保在任何环境中安装相同的依赖集。
    2. 检查 poetry.lock 文件:执行命令后,检查项目目录中的 poetry.lock 文件。这个文件应该被更新,反映了当前依赖的精确状态。
    3. 提交 poetry.lock 文件到版本控制系统:为了保持团队或部署环境间的一致性,确保将更新后的 poetry.lock 文件提交到版本控制系统(如 Git)。

    使用 poetry lock 命令的场景包括:

    • 当你添加、删除或修改 pyproject.toml 中的依赖时。
    • 当你希望更新依赖到可用的最新版本,但又不想更改 pyproject.toml 中的版本规范时。
    • 当你需要确保项目依赖的一致性和稳定性时。

    记住,poetry.lock 文件应该与 pyproject.toml 文件一起被版本控制,以保证项目在不同开发和部署环境中的一致性。(注意:poetry add 运行时会自动运行 poetry lock

  • Git 发布:通过 git 命令 push 到远程仓库。

进阶用法

配置 Poetry 和 PyPI 仓库

为了更方便地管理和发布包,你可以配置 Poetry 以使用不同的 PyPI 仓库。

  1. 添加自定义仓库:如果你想使用除了官方 PyPI 以外的仓库,可以添加一个新的仓库配置:

    poetry config repositories.custom_repo_name https://custom-repo-url.com

    这里的 custom_repo_name 是你为仓库设置的名字,https://custom-repo-url.com 是仓库的 URL。

  2. 发布包到自定义仓库:如果你开发了自己的包并想发布到配置的仓库,可以使用:

    poetry publish --repository custom_repo_name

    确保你已经正确设置了认证信息,如需要的 API token。

使用 Poetry 进行版本控制

Poetry 还可以帮助你管理项目的版本。

  1. 版本号:查看当前项目的版本号,可以使用:

    poetry version
  2. 版本更新:要更新项目版本(如进行小的修改或发布新的版本),可以使用:

    poetry version patch  # 小更新
    poetry version minor  # 次要更新
    poetry version major  # 主要更新

    这将更新 pyproject.toml 中的版本号。

常见问题

HTTPResponse Error

一般来说,这是因为你在安装某个安装包的时候,影响了 poetry 库所依赖的库,如果你使用了 poetry 自带的虚拟环境,就不会出现这种问题。比如下面的 urllib3:

在遇到 'HTTPResponse' object has no attribute 'strict' 问题时,应该降级 urllib3,一般这种情况是因为 Poetry 本身不兼容更高版本的 urllib3

'HTTPResponse' object has no attribute 'strict' · Issue #7936 · python-poetry/poetry

Poetry has urllib3 pinned below 2.0, so you had to mess something up on your end (for example by installing your project and poetry into the same environment). In any case, this is not Poetry’s fault.

运行:

poetry add urllib3==1.26.15

安装 Pytorch 的例子

pytorch 官方源

Previous PyTorch Versions | PyTorch 从这里找地址,缺点是下载速度慢,容易超时失败。

建议设置环境变量 POETRY_REQUESTS_TIMEOUT 作为超时时长,单位秒。

poetry source add -p explicit pytorch https://download.pytorch.org/whl/cu118
poetry add --source pytorch torch torchvision

腾讯云源

缺点是这个源只支持 cuda 12.1 的 torch,不过一般情况下建议使用这个,能兼容我们的设备:

poetry source add -p explicit pytorch-tencent https://mirrors.cloud.tencent.com/pypi/simple/
poetry add --source pytorch-tencent torch torchvision

本地源

Previous PyTorch Versions | PyTorch 下载,比如从 https://download.pytorch.org/whl/cu118下载符合你系统环境的版本,建议安装本地包的时候上传到 dvc,加快下载速度:Tech / Kensho / mchat_x_LMA · GitLab 就是这样。

  • pyproject.toml 中添加内容就好了,例如:
[tool.poetry.dependencies]
python = "^3.8"
loguru = "^0.7.2"
dvc = "2.51.0"
dvc-webhdfs = "^3.1.0"
lit = { file = "model/torch2.0.1_cu118/lit-15.0.7.tar.gz" }
torch = { file = "model/torch2.0.1_cu118/torch-2.0.1+cu118-cp38-cp38-linux_x86_64.whl" }

添加之后运行 poetry install

  • 直接运行
poetry add model/torch2.0.1_cu118/torch-2.0.1+cu118-cp38-cp38-linux_x86_64.whl

尾声

进阶请查看官方文档:Introduction | Documentation | Poetry – Python dependency management and packaging made easy

本文说明了使用 Poetry 的动机、基本使用说明,以及在特定场景下的使用。poetry是什么poetry 中文poetry 中文poetry 中文poetry 中文poetry 中文poetry 中文poetry 中文poetry 中文poetry 中文poetry 中文poetry 中文poetry 中文poetry 中文poetry installpoetry install

第 10 课 NumPy 计算和广播原理

前情提要

第 9 课补

  • arr[2, :]

  • np.ix_()

    import numpy as np
    
    arr2 = np.arange(32).reshape((8,4))
    print(arr2)
    
    arr2[np.ix_([1,5,7,2],[0,3,1,2])]
    
    arr2[np.ix_([1,5,7,2],[0,1,2])]

第 9 课答案

    1. numpy.random.randint

      np.random.seed(3)
      x1 = np.random.randint(low=1, high=10, size=100)
      np.save("save.npy", x1)
      
      x1 = np.load("save.npy")
      print(x1)

课程纲要

  • 数学计算

    • 逻辑运算np.where np.all() np.any()
    arr = np.random.rand(2, 3)
    result = np.where(arr > 0.5, 1, 0)
    #   condition ? arr1: arr2
    arr = np.random.rand(2, 3)
    result = np.all(arr > 0.1)
    arr = np.array([2, 2, 3, 3, 1])
    result = np.unique(arr)
    • 线性代数:numpy.linalg 库文档

    • np.trace np.inner()

    • linalg.qr linalg.svd

      arr = np.array([[2, 2, 3, 3], [4, 3, 2, 1]])
      U, s, V = np.linalg.svd(arr)
    • 统计运算

    • 求和 arr.sum(axis=0)

      arr = np.random.rand(2, 3)
      result = np.sum(arr)
      
      result = np.sum(arr > 0.5)    #   根据条件求真值的和
    • 最值 arr.max() arr.min() arr.argmin() arr.argmax() 文档

      arr = np.random.rand(2, 3)
      result = np.max(arr)
      
      arr = np.random.rand(2, 3)
      result = np.argmin(arr)
    • 算术平均数 np.mean()

      arr = np.random.rand(2, 3)
      result = np.mean(arr)
    • 标准差、方差 np.std() np.var()

  • Numpy 的形状操作

    • 添加维度
    arr = np.array([1, 2, 3])
    result = arr[np.newaxis, :, ]
    print(arr)
    print(result)
    • 改变维度个数和大小 np.resize() np.reshape() ,前者改变源数组,后者不会。
    arr = np.random.random((4, 4))
    print(arr)
    arr.resize((2, 3))
    print(arr)
    arr.resize((1))
    print(arr)
  • NumPy 的广播原理

    • 维度和维度大小

    • 广播(broadcasting)

    • 什么是广播

      arr = np.ones((2, 4))
      arr2 = 1
      print(arr)
      print(arr2)
      print(arr + arr2)
    • 规则1:数组维度和大小,从后往前有连续的相同部分

      arr = np.ones((2, 4, 4))
      arr2 = np.ones((4, 4))
    • 规则2:不相同的部分维度大小为1

      arr = np.zeros((2, 4, 4))
      arr2 = np.ones((1, 1))
  • Matplotlib

    • 画一个三角函数吧
    import numpy as np
    import matplotlib.pyplot as plt
    
    X = np.linspace(-np.pi, np.pi, 100)
    COS, SIN = np.cos(X), np.sin(X)
    ax = np.zeros(100)
    plt.plot(COS)
    plt.plot(SIN)
    plt.plot(ax)
    plt.show()
    

第 8 课 数据分析初步

讲的是利用Python进行数据控制、处理、整理、分析等方面的具体细节和基本要点。

  • 为什么是 Python 用于数据分析?

    1. Python 成功的部分原因是其能轻松地集成和调用 C、C++、Fortran 代码。大部分现代计算软件利用了一些 Fortran和 C 库来实现线性代数、积分、快速傅里叶变换等算法。许多企业和国家实验室也利用 Python 粘合来已经用了30多年的遗留软件系统。
    2. Python 和自然语言相似,很多科研人员和程序员非常喜欢,因此产生了第3点👇。
    3. Python 有很多高效、实用的类库,并可以方便地建立网站、爬取数据、数据分析、进行机器学习。
  • 库以及 pip 软件管理

    • library (类、库)是什么
    import time
    from time import sleep
    • pip 类库管理

    • pip 文档地址:https://pypi.org/project/pip/

    • 更换数据源:清华源地址

      • 升级 pip 到最新的版本 (>=10.0.0) 后进行配置:
      pip install pip -U
      pip config set global.index-url https://mirrors.cloud.tencent.com/pypi/simple/
      pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
      # 阿里源
      pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/
      # 腾讯源
      pip config set global.index-url http://mirrors.cloud.tencent.com/pypi/simple
      # 豆瓣源
      pip config set global.index-url http://pypi.douban.com/simple/
    • 如果您到 pip 默认源的网络连接较差,临时使用本镜像站来升级 pip:

      pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pip -U
    • 安装

      python -m pip install SomePackage            # latest version
      python -m pip install SomePackage==1.0.4     # specific version
      python -m pip install 'SomePackage>=1.0.4'     # minimum version
      # -m 的含义表示将库当作脚本来执行。
      pip install SomePackage            # latest version
      pip install SomePackage==1.0.4     # specific version
      pip install 'SomePackage>=1.0.4'     # minimum version
      pip freeze > requirements.txt
      pip install -r requirements.txt
      pip list  #   list installed packages
    • 卸载

      python -m pip uninstall SomePackage
    • 更新

      pip install package_name --upgrade
    • 科学计算的常用类库:

    • NumPy 是以矩阵为基础的数值计算模块,提供高性能的数组对象。文档地址:http://www.numpy.org/

    • Pandas 是基于 NumPy 的一种工具,纳入了一些标准的数据模型,提供了处理数字图表和时序数据的数据结构和操作功能,常用于金融数据分析。文档地址:https://pandas.pydata.org/

    • Scipy 是基于 NumPy 的一种高级数据处理工具,提供最优化、回归、插值、线性代数模块、傅里叶变换、信号和图像处理,常微分方程求解器等功能。文档地址:http://www.scipy.org/

    • Matplotlib 是2D绘图工具,常用于可视化展示数据。文档地址:http://matplotlib.org/

    • 其他类库

    • seaborn 是基于 Matplotlib 的更加美观的绘图工具。文档地址:https://seaborn.pydata.org/

    • anaconda 是科学计算常用的环境管理工具,什么是环境?

  • NumPy 初步

    • Python 自带的数据类型性能低。

    • jupyter 文档地址 pip install jupyterlab

    • 数据类型:ndarray

    • 特点:数组里面每一个元素是相同类型。

    • 手动创建数组

      import numpy as np    # 推荐如此导入Numpy
      vec = np.array([0, 1, 2, 3])
      mat = np.array([[0, 1, 2], [3, 4, 5]])
      mat.ndim
      mat.shape
      mat.dtype
      len(mat)    
    • 函数创建数组

      a = np.arange(9)
      b = np.arange(2, 2, 2)
  • 指定长度的数组

      c = np.linspace(1, 6, 6) 
  • 特殊的数组

      np.ones((2, 2)) # tuple
      np.eye(3) #   单位矩阵
      np.diag(np.array([1, 2, 3, 4]))   #   对角阵
      np.random.rand(4) #   随机数组
    
      np.random.seed(0)  # 设定随机种子,保证实验的可重现
      x1 = np.random.randint(10, size=6)  # 一维数组
      x2 = np.random.randint(10, size=(3, 4))  # 二维数组
      x3 = np.random.randint(10, size=(3, 4, 5))  # 三维数组
  • 内置数据类型

    • 明确定义数组数据类型:(默认数据类型是浮点型)
        tmp = np.array([1, 2, 3], dtype=float)
    • 所有内置类型
        f = np.array([1+2j, 3+4j, 5+6*1j])  #   j为虚部
        f.dtype
        b = np.array([True, False, False, True])
        s = np.array(['Bonjour', 'Hello', 'Hallo',])
        # int32
        # int64
        # uint32
        # uint64
    • 更多内容在下节

课后作业

  • 安装 pip 环境,和那几个数据分析库并且运行上述代码。

第 7 课 面向对象的类设计

课程代码链接

  • 类设计

    • 参数传递

    • 作用域的实质

    • 内存绑定 : 如何编写带输出参数的函数(通过引用调用)?

    • 不可更改的类型 可以修改的类型
      string list
      tuple dict
      float
      int
      float
    • 保护数据

    • 私有属性 self.__name

    • 私有方法 self.__function_name()

    • 继承与多态

    • 理解为子承父业。

    • 父类(基类)和子类(派生类)

    • 覆盖方法

    • 多态:不同类型调用不同的实现。

  • dict 字典 {key: value}

    • dict_name [key] = value
    • del dict_name[key] dict_name.get()
    • dict_name[key] = value
    • dict_name[key]

第 6 课 类与数据结构

课程提纲

面向对象的类

  • 类(类型),是特殊的数据结构
  • 为什么要有类和对象?封装,把代码实现的细节覆盖。类就像一条生产线,就像一个完美模具。柏拉图的理型论认为:先有了这个理型世界,然后这个世界会按照这个完美的模子发展着。
  • 类设计:数据与行为(鸭子的模具,数据:声音、形状、颜色,行为:叫、游泳)
    • 方法:类中定义的函数。(鸭子的行为)
    • 对象:通过类定义的数据结构实例。(用模具创造一个鸭子)
    • 定义一个类(设计一个鸭子的模具)
    • class
    • def __init__
    • self 代表类的实例,而非类
    • 创建和使用
    • instance.method_name() instance.member
    • class_name.method_name() class_name.member

计算机领域的数据结构(了解即可):集合、数组、队列、栈、树、图等

  • 集合关系 set
    • 结构:元素无序地组织
    • 操作:{交、并、补 | 集合与集合之间}、{ 存、取、查找 | 集合内元素 }
    • 例子:是否有人迟到?
  • 线性结构,一对一,前驱后继关系
    • 列表
    • 队列(可用list实现),先进先出 queue
      • 结构:像排队一样
      • 操作:增add() 、删pop()
    • 栈(可用list实现),先进后出
      • 结构:像桶一样
      • 操作:增、删
  • 树状结构,一对多
    • 二叉树
      • 结构:像族谱图
      • 110511_WqcR_2348884
    • m叉树
  • 图状结构,多对多
      • 结构:像地图一样
      • 操作:增、删
  • 特殊的数据结构
    • 字典 dict

Python 中的数据结构

集合关系 set

  • 结构:元素无序地组织 \ 无重复元素
  • 操作:初始化 set() {}
    • 逻辑运算 not ==
    • add()
    • remove(key) clear() pop()
    • 改 不可改!
    • in
    • setA & setBsetA | setB 差集setA - setB 对等差分 setA ^ setB

课后作业

注:那个爬虫作业取消,感觉还是太难,爬虫代码在这:https://github.com/xrandx/Dating-with-python-this-winter/blob/master/douban_book.py (存在 bug:定位的逻辑不对,只能爬页数大于1且小于11的读书页面)

队列(queue)是一种先进先出(FIFO, First-In-First-Out)的、操作受限的线性表。在具体应用中通常用链表或者数组来实现。

队列只允许在后端(称为rear)进行插入操作,在前端(称为front)进行取出操作。队列的容量是它能容纳元素的多少,队列的大小是元素已经占用的空间多少。

请定义一个 Queue 类,基于 list 实现如下的方法:

    queue = Queue()
    queue.enqueue()  # 将任意对象从队尾入队
    queue.dequeue()  #  使队头对象出队
    queue.size()  # 返回队列的长度(int)
    queue.capcity() #   返回队列的容量(int)
    queue.is_full() #   队列是否已满(bool)
    queue.is_empty()    #   队列是否为空 (bool)

第 5 课 函数、作用域与递归

第 5 课 函数、作用域与递归

注意标准库文档入门教程

课程纲要

变量

  • 函数(必须掌握):接收输入、提供输出的东西

    • 关键字def 与参数:定义一个 echo()(回声),参数、默认参数和关键字参数

    • 返回值和 return 语句:

    • def function_name:
      do_something()
        return something 
    • None 值:NoneType数据类型,如果你不返回任何值。(type)

    • 诀窍:一个函数最好不要超过40行。

  • 作用域(掌握思想):

    • 起因:公用私用问题,保护数据。尽量不要使用全局变量。
    • 规则(不应该背下来):
    • 局部变量不能在全局作用域内使用
    • 局部作用域不能使用其他局部作用域内的变量
    • 全局变量可以在局部作用域中读取
    • global 关键字
  • 递归(掌握如何写递归函数):函数自己调用自己

    • 例子:

    • 从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是什么呢?「从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是什么呢?『从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是什么呢?……』」

    • 直播例子

    • 数学归纳法:

      • 证明 「第一张骨牌会倒。」
      • 证明 「只要任意一张骨牌倒了,其下一张骨牌也会因為前面的骨牌倒而跟著倒。」
      • 则可下结论:所有的骨牌都会倒下。
    • 如何写递归函数:

    • 确定初始条件和函数的作用

    • 由"情况 n" 变化到"情况 n+1"

    • 确定递归结束的条件

    • 题目:

    • 斐波那契数列 用递归做太慢,只借鉴思路。

    • 递归乘法

课后作业

  • 定义一个gcd(m, n)函数,该函数可以求出m与n的最大公约数,用辗转相除法递归实现。
  • 用递归实现阶乘函数factorial(n),对于任意的整数n都能返回其对应的阶乘。
  • 跳水板