

换源

```
https://pypi.python.org/simple
https://pypi.tuna.tsinghua.edu.cn/simple/
https://pypi.mirrors.ustc.edu.cn/simple/
https://pypi.douban.com/simple
```

在 PyCharm 中查看到的 "Interpreter Paths" 列表显示的是 Python 解释器用于查找库和模块的路径。这些路径包括 Python 的标准库位置、第三方库位置以及您的项目特定环境的位置。根据您提供的路径，这里是它们的含义：

1. **`C:\Users\86131AppData Local Programs\Python Python38\DLLs`**:
   - 这是 Python 标准动态链接库（DLLs）的存放位置。Python 使用这些 DLLs 来执行各种内置功能。

2. **`C:\Users\86131AppData Local Programs\Python\Python38\Lib`**:
   - 这是 Python 的标准库位置。这里包含了 Python 自带的各种模块和包。

3. **`C:\Users\86131AppData Local Programs Python\Python38`**:
   - 这可能是 Python 解释器自身的位置。

4. **`D:\pythonProject\paclvenv`**:
   - 这看起来像是一个为特定项目（在这里是 `pythonProject`）创建的虚拟环境的根目录。

5. **`D:\pythonProject\pac venv Lib\site-packages`**:
   - 这是上述虚拟环境中的 `site-packages` 目录，存放该环境安装的第三方库。
   这些路径似乎是您 Miniconda 环境中一个名为 `test1` 的 Python 虚拟环境的组成部分。每个路径都指向该环境中的不同库和资源的位置。下面是它们各自的作用：

1. **`E:\Miniconda3\envs\test1\DLLs`**:
   - 这个目录包含动态链接库（DLLs）。在 Windows 系统中，这些文件通常包含执行某些操作所需的代码和数据。

2. **`E:\Miniconda3\envs\test1\Lib`**:
   - 这是标准库文件的存放位置。这里包含 Python 自带的各种模块和包。

3. **`E:\Miniconda3\envs\test1\Lib\site-packages`**:
   - 这个目录是第三方包和模块安装的地方。当您使用 `pip` 安装新包时，它们通常会被放置在这里。

4. **`E:\Miniconda3\envs\test1\Lib\site-packages\win32`**:
   - 这个目录包含特定于 Windows 的附加库和模块。

5. **`E:\Miniconda3\envs\test1\Lib\site-packages\win32\lib`**:
   - 与上述 `win32` 目录类似，这个目录包含更多特定于 Windows 平台的库。

6. **`E:\Miniconda3\envs\test1\Lib\site-packages\pythonwin`**:
   - 这个目录可能包含 Python for Windows 扩展，这是一组用于 Windows 的 Python 扩展工具和模块。

这些目录构成了您的 `test1` 虚拟环境的核心，包含了运行 Python 程序所需的所有标准库、第三方库以及平台特定的扩展。这些路径都是环境正常运行的重要组成部分，通常不应被删除或修改，除非您明确知道自己在做什么。
**是否可以删除这些路径？**

- 通常情况下，不建议删除这些路径。这些是 Python 解释器正常工作所必需的，或者是您项目特定的环境设置。
- 删除标准库路径或 DLLs 路径可能会导致 Python 解释器无法正常运行。
- 删除项目虚拟环境的路径可能会导致您的项目无法找到所需的第三方库。

如果您的意图是整理或重置项目环境，通常有更安全的方法，比如在 PyCharm 中重新配置解释器或创建新的虚拟环境，而不是直接删除这些路径。如果您不确定，最好是保留这些路径，以避免意外破坏您的 Python 安装或项目环境。

您之前询问的是 PyCharm 中的一个 Python 解释器的路径，而这次您提供的是 Miniconda 环境中名为 `test1` 的虚拟环境的路径。虽然这两个问题都涉及 Python 环境的不同部分，但它们是关于不同类型的环境设置的：

1. **PyCharm Python 解释器路径**:
   - 这涉及到在 PyCharm IDE 中配置的 Python 解释器。它可以是系统全局的 Python 安装，也可以是特定的虚拟环境。
   - PyCharm 中的解释器设置决定了在该 IDE 内运行和调试 Python 代码时使用的 Python 环境。

2. **Miniconda 环境路径**:
   - 这是您通过 Miniconda 创建的一个特定虚拟环境（在这个例子中是 `test1`）的路径。这个环境可能与 PyCharm 中配置的环境不同。
   - Miniconda 环境是 Conda 管理的，通常用于数据科学和机器学习项目，它支持易于管理和隔离的环境。

尽管两者都涉及 Python 环境的设置，但它们服务于不同的目的和上下文。PyCharm 解释器路径更侧重于 IDE 中的项目开发和调试，而 Miniconda 环境路径则关注于为特定需求创建独立的、可重复的 Python 工作环境。





Miniconda 环境（test1）的路径：
这些路径指向的是您通过 Miniconda 创建的名为 test1 的虚拟环境：

E:\Miniconda3\envs\test1\DLLs 等：这些是 Miniconda 环境中的标准库、第三方库以及特定于 Windows 平台的库的位置。它们是 Miniconda 管理下的虚拟环境的一部分，意味着在这个环境中安装的库和模块与您的系统全局 Python 环境或其他虚拟环境隔离。
本地 Python 安装（可能是 Python 3.8）的路径：
这些路径看起来像是指向您在本地安装的 Python 版本（可能是 Python 3.8）：

C:\Users\86131AppData\Local\Programs\Python\Python38\DLLs 等：这些是您系统中安装的 Python 版本的标准库和第三方库的位置。这些路径指向的是您电脑上的全局 Python 安装。

在 Miniconda 环境（test1）中存在额外的路径，如 win32, win32/lib, 和 pythonwin，这主要是因为这个特定环境可能安装了一些专门用于 Windows 操作系统的扩展和模块。这些路径的出现通常与环境中安装的特定包有关。让我们来详细看看这些路径的可能用途：

win32 和 win32/lib:

这些目录通常包含 pywin32 库的一部分，它是一个非常流行的 Python 扩展，提供了对 Windows API 的访问。pywin32 允许 Python 脚本执行许多 Windows 特有的操作，如自动化 GUI、访问系统服务、读取注册表等。
这些路径下可能包含用于 Windows 平台的特定函数和类的 Python 模块。
pythonwin:

pythonwin 目录是 pywin32 的一部分，它包含 PythonWin，这是一个 Windows 下的 Python IDE，提供了一个交互式的开发环境。
它通常包含用于开发和调试 Windows 应用程序的附加工具和模块。

```
conda install pytorch==2.0.1 torchvision==0.15.2 torchaudio==2.0.2 pytorch-cuda=11.7
anaconda search -t conda https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge
conda create --prefix D:/top  ./my_venv python=3.8
conda install conda-forge::pyprojec
conda create --prefix ./myenv python=3.8
pip install torch==2.0.1+cu117 torchvision==0.15.2+cu117 torchaudio==2.0.2 
pip install --user torch==2.0.1+cu117 -f  https://download.pytorch.org/whl/cu117
 -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.douban.com。
 先用test1打开notebook
%matplotlib  inline 可以分开但是移动不了
你需要用%matplotlib notbook 然后每次绘图前用plt.figure()
避免重合在一张图表里
```

对于对象引用的笔记

**对象可由一组属性构成。**

**伪代码中函数传参按照值传递。**

**多重赋值 i<-j<-e将表达式e的值赋给变量j和i**

**（相当于i=j=e）**

**变量（如i，j和key）是局部于给定过程的，在没有显示说明的情况下，我们不使用全局变量**

**评：函数传参有三种方式：值传递，地址传递，引用传递（应注意C语言没有引用）。**

**参数采用按值传递的方式，且传递的是引用（指针），那么是“引用的值被复制”，当对象被传递时，实际传递的是对象引用的拷贝（指向该对象数据的指针值的拷贝），而对象的各个域则不被拷贝（对象本身不被拷贝）。例如，x是某个被调用过程的参数，在被调过程中的赋值x<-y对主调过程是不可见的，但是f[x]<-3是可见的。**

1. **按值传递（True pass-by-value）：**
   - **完整拷贝对象及其所有数据**
   - **所有修改对调用方都不可见**
   - **典型语言：C++（非引用参数）、Java基本类型**
2. **按共享传递（Pass-by-sharing）：**
   - **拷贝对象引用（指针），不拷贝对象数据**
   - **修改引用不可见，修改数据可见**
   - **典型语言：Python、Java对象类型**
3. **按引用传递（Pass-by-reference）：**
   - **直接传递原始变量的引用**
   - **所有修改对调用方都可见**
   - **典型语言：C++引用参数、C# ref参数**

 

**# Python示例（按共享传递）**

**def modify(obj):**

  **obj = [4,5,6] # 修改引用，外部不可见**

  **obj[0] = 100  # 修改数据，外部可见**

 

**original = [1,2,3]**

**modify(original)**

**print(original) # 输出[100, 2, 3] 而非[4,5,6]**

1. **对被调用过程中：**
   - **重新赋值参数变量（如x←y）不会影响调用方**
   - **通过引用修改对象内容（如f[x]←3）会影响调用方"**

**前句说传递"对象的一个拷贝"，后句又说"对象的各个域不被拷贝"，这是自相矛盾的。正确的表述应该是：**

- **浅拷贝（shallow copy）：拷贝对象引用（指针），但不拷贝引用指向的数据。**
- **深拷贝（deep copy）：拷贝对象及其所有嵌套数据**

**"对象的一个拷贝"是浅拷贝还是深拷贝？**

**答案：取决于上下文，但通常指浅拷贝（除非明确说明是深拷贝）。**

**. 按值传递（Pass-by-value）是浅拷贝还是深拷贝？**

**答案：取决于数据类型，但严格来说，按值传递是值的完整拷贝。**

- **基本类型（int, float, bool 等）：**
  - **按值传递 = 深拷贝（完全独立的副本）。**
  - **例如：C/C++ 的 int、Java 的 int、Python 的不可变类型。**
- **对象/引用类型（类实例、数组、字典等）：**
  - **按值传递 = 浅拷贝（传递的是引用的拷贝，而非对象本身）。**
  - **例如：Java 的对象、Python 的列表/字典。**

- **按值传递的本质是拷贝变量的值。**
  - **如果是基本类型，拷贝的是实际值（深拷贝）。**
  - **如果是引用类型，拷贝的是指针/引用（浅拷贝）。**

**// Java 示例（按值传递，但对象是浅拷贝）**

**void modify(List<Integer> list) {**

  **list = new ArrayList<>(Arrays.asList(4, 5, 6)); // 新引用，外部不可见**

  **list.set(0, 100); // 修改引用指向的数据，外部可见**

**}**

 

**List<Integer> original = new ArrayList<>(Arrays.asList(1, 2, 3));**

**modify(original);**

**System.out.println(original); // 输出 [100, 2, 3]（证明是浅拷贝）**

**. 按共享传递（Pass-by-sharing）是浅拷贝还是深拷贝？**

**答案：浅拷贝（传递的是引用的拷贝）。**

- **按共享传递（如 Python、Java 的对象传递）本质上是按值传递引用。**
  - **即传递的是对象的指针/引用的拷贝，但对象本身不拷贝。**
  - **因此，修改引用指向的数据会影响原对象（浅拷贝行为）。**

**示例：**

**python**

**def modify(obj):**

  **obj[0] = 100 \*#\* \*修改引用指向的数据，外部可见\***

 

**original = [1, 2, 3]**

**modify(original)**

**print(original) \*#\* \*输出 [100, 2, 3]（浅拷贝行为）\***

 

| **概念**                 | **拷贝方式**     | **是否拷贝数据** | **影响原对象**       | **典型语言/场景**                     |
| ------------------------ | ---------------- | ---------------- | -------------------- | ------------------------------------- |
| **浅拷贝**               | **仅拷贝引用**   | **❌ 不拷贝数据** | **✅ 修改影响原对象** | **Python list.copy(),  Java clone()** |
| **深拷贝**               | **递归拷贝数据** | **✅ 完全拷贝**   | **❌ 不影响原对象**   | **Python copy.deepcopy()**            |
| **按值传递（基本类型）** | **深拷贝**       | **✅ 完全拷贝**   | **❌ 不影响原变量**   | **C int,  Java int**                  |
| **按值传递（引用类型）** | **浅拷贝**       | **❌ 仅拷贝引用** | **✅ 修改影响原对象** | **Java  对象、Python 列表**           |
| **按共享传递**           | **浅拷贝**       | **❌ 仅拷贝引用** | **✅ 修改影响原对象** | **Python、JavaScript**                |

1. **可见性规则表述不严谨：**
   - **"x<-y不可见但f[x]<-3可见"的表述过于绝对。正确的可见性规则应明确取决于：**
     - **如果传递的是对象引用的拷贝：**
       - **修改引用本身（如x = y）对调用方不可见**
       - **通过引用修改对象内容（如f[x] = 3）对调用方可见**
     - **如果传递的是完整对象拷贝：**
       - **所有修改都对调用方不可见**


```mermaid
graph TD
    A[参数传递方式] --> B[按值传递]
    B --> C[深拷贝对象]
    A -->D[按引用传递]
    A --> E[按共享传递]
    E --> G[拷贝对象引用]
    E--> H[不拷贝对象数据]
```




**返回(return)语句执行后将返回到函数的调用点，大多数返回语句能返回一个值，伪代码中可以返回多个值。**

**评：一些高级语言例如C++不支持多个返回值，一般就采用全局变量，引用传递，结构体，元组等方式，伪代码支持多返回值会非常方便。**

**布尔运算符”and“和”or“都是短路的。**

**关键词error表示已调用过程不对，出现了错误。**

声明在函数原型里的形式参数名字，只在该函数生命内有效，作用域是该函数声明，因此函数声明内形参名字也因此可以省略；
声明或定义在函数体内的名字、函数作用域是该函数体，作为对象名字时，相应对象也是局部对象；
函数定义时的形参作用域就是该函数定义，形参对象也是局部对象；



```
Book object (1) <class 'TestModel.models.Book'>
TestModel.Book.objects <class 'django.db.models.manager.Manager'>
300.00 <class 'django.db.models.query.QuerySet'>
```



```
本来是觉得应该做一个输入一个表达式，将其转换成数学表达式并计算，返回布尔值非0或0，然后传递给my_assert，作出判断

但第一个问题是怎么把输入的字符串怎么转换成一个数学表达式并返回其值

然而python中有eval（）这个函数，但是c语言没有。（静态语言不可能有eval类似的函数）

eval问题是简单的了，用栈的形式储存每个字符，逆波兰表达式…….

但是怎么解决“==”这个判断语句？用bool形式吗？

如何实现判断呢？然后如何返回0或者非0呢？问题就是这里了。
```

为什么在login还没登陆呢就有用户名或密码错误的提示>应该在第一次输入后如果错误才有的

jupyter一抛弃extension，在jupyter lab中自带





# Python是什么？

像 Perl 语言一样，Python 源代码同样遵循 GPL(GNU General Public License)协议。

- **Python 是一种解释型语言：** 这意味着开发过程中没有了编译这个环节。类似于PHP和Perl语言。
- **Python 是交互式语言：** 这意味着，您可以在一个 Python 提示符 **>>>** 后直接执行代码。
- **Python 是面向对象语言:** 这意味着Python支持面向对象的风格或代码封装在对象的编程技术。

Python 解释器是一个非常重要的程序，用于执行 Python 代码。它与编译器有一些相似之处，但也存在显著的不同。

**Python 解释器**

1. **功能**：Python 解释器的主要功能是读取 Python 代码，理解和处理其语法，然后执行这些代码。这涉及到将 Python 代码转换成一种可以被计算机处理器理解的形式。

2. **实时执行**：与编译器不同，解释器通常在运行时（即代码执行时）逐行解释代码。它不需要在执行之前将整个程序编译成机器代码。

3. **交互式编程**：Python 解释器支持交互式编程。这意味着您可以一次输入一行代码，并立即看到执行结果，这在 Python Shell 或 Jupyter Notebook 等工具中非常常见。

4. **多种实现**：Python 有几种解释器实现，最常见的是 CPython（用 C 语言编写的 Python 解释器）。还有其他实现，如 Jython（Java 实现的 Python）、IronPython（C# 实现的 Python）等。

编译器

1. **功能**：编译器的工作是将源代码（如 C 或 Java 代码）转换成机器代码或中间代码，这个过程在程序运行之前完成。

2. **一次性转换**：编译器通常在程序执行之前将源代码完全编译成机器代码。这意味着编译过程和执行过程是分开的。

3. **效率**：由于编译器将代码转换为机器代码，因此编译过的程序通常运行得更快。

4. **不支持交互式编程**：传统的编译型语言不支持解释型语言的交互式编程特性。

总结

尽管 Python 解释器和编译器在处理代码的方式上有所不同，它们都是程序员用来将高级语言转换成机器能理解和执行的形式的工具。Python 的解释性质使得它非常适合快速开发和交互式探索，但这也可能导致执行效率低于编译型语言。



**编码方式**

默认情况下，Python3 源码文件以 **UTF-8** 编码，所有字符串都是 unicode 字符串。

当然你也可以为源码文件指定不同的编码：

\# -*- coding: cp-1252 -*-

**行与缩进**

对于python而言，代码缩进是一种语法，python没有分隔代码块的语句或符号(“{}”)，而是缩进和冒号

缩进的空白数量是可变的，但是所有代码块语句必须包含相同的缩进空白数量

**多行语句**

Python 通常是一行写完一条语句，但如果语句很长，我们可以使用反斜杠 **\** 来实现多行语句，例如：

total = item_one + \

​    item_two + \

​    item_three

 

# 变量

变量就是代表或引用某值 的名字，是一种可变的量。X=98

变量使用注意事项

# 命名原则

## 标识符

- 第一个字符必须以字母（a-z, A-Z）或下划线 **_** 。
- 标识符的其他的部分由字母、数字和下划线组成。
- 标识符对大小写敏感，count 和 Count 是不同的标识符。
- 标识符对长度无硬性限制，但建议保持简洁（一般不超过 20 个字符）。
- 禁止使用保留关键字，如 if、for、class 等不能作为标识符。

### 保留关键字

| **函数定义** | lambda   | 创建匿名函数                   |
| ------------ | -------- | ------------------------------ |
| **模块导入** | import   | 导入模块                       |
|              | from     | 从模块导入特定部分             |
|              | as       | 为导入的模块或对象创建别名     |
| **作用域**   | global   | 声明全局变量                   |
|              | nonlocal | 声明非局部变量（用于嵌套函数） |
| **异步编程** | async    | 声明异步函数                   |
|              | await    | 等待异步操作完成               |
| **其他**     | assert   | 断言，用于测试条件是否为真     |
|              | pass     | 空语句，用于占位               |
|              | with     | 上下文管理器，用于资源管理     |
|              | yield    | 从生成器函数返回值             |

 

## 模块名：

小写字母、单词之间用下划线”_”分割，ad_stats.py

## 类名:

首字母大写:AdStats

## 普通变量：

小写字母，单词之间用下划线“_“分割: this_is_a_var

## 实例变量：

下划线”_”开头。小写字母，单词之间用下划线”_”分割，不会被语句from module import * 加载

## 普通函数：

小写字母，单词之间用下划线“_“分割

例如get_name()

## 私有函数：

以两个下划线“_“开头，小写字母。单词之间用下划线”_“分割，

例如：__get_name(),外部访问会报错

# 注释

Python中单行注释以 **#** 开头，

多行注释可以用多个 **#** 号，还有 **'''** 和 **"""**：

\# 第一个注释 

\# 第二个注释

 ''' 第三注释 第四注释 '''

 """ 第五注释 第六注释 """ 

注意的是，三个双引号也可以是字符串

**拓展说明**

在 Python 中，多行注释是由三个单引号 **'''** 或三个双引号 **"""** 来定义的，而且这种注释方式并不能嵌套使用。

当你开始一个多行注释块时，Python 会一直将后续的行都当作注释，直到遇到另一组三个单引号或三个双引号。

**嵌套多行注释会导致语法错误。**

例如，下面的示例是不合法的：

**实例**

'''
 这是外部的多行注释
 可以包含一些描述性的内容
 
   '''
   这是尝试嵌套的多行注释
   会导致语法错误
   '''
 '''

在这个例子中，内部的三个单引号并没有被正确识别为多行注释的结束，而是被解释为普通的字符串。

这将导致代码结构不正确，最终可能导致语法错误。

如果你需要在注释中包含嵌套结构，推荐使用单行注释（以#开头）而不是多行注释。

 

**记住：**空行也是程序代码的一部分。

# 赋值

Python 中的变量不需要声明。每个变量在使用前都必须赋值，变量赋值以后该变量才会被创建。

在 Python 中，变量就是变量，它没有类型，我们所说的"类型"是变量所指的内存中对象的类型。

等号（=）用来给变量赋值。

等号（=）运算符左边是一个变量名,等号（=）运算符右边是存储在变量中的值。例如：

 

1、 基础赋值。将某一个值赋给变量的操作被称为赋值（assignment）

X=98

2、 多重赋值和多元赋值

可以进行同时给多个变量赋予相同内容的操作，即多重赋值。

a=b=c=100

多元赋值，赋值时只需用逗号将变量和值隔开即可，例如：a,b,c=1,2,3

可以通过 **type()** 函数查看变量的类型：

此外还可以用 isinstance 来判断：

**实例**

\>>> a = 111
 \>>> isinstance(a, int)
 True
 \>>>

isinstance 和 type 的区别在于：

- type()不会认为子类是一种父类类型。
- isinstance()会认为子类是一种父类类型。

Python3 中，bool 是 int 的子类，True 和 False 可以和数字相加， **True==1****、False==0** 会返回 **True**，但可以通过 **is** 来判断类型。

\>>> 1 is True

<python-input-12>:1: SyntaxWarning: "is" with 'int' literal. Did you mean "=="?

 1 is True

False

\>>> 0 is False

<python-input-13>:1: SyntaxWarning: "is" with 'int' literal. Did you mean "=="?

 0 is False

False

***什么会出现 SyntaxWarning？\***

*Python 检测到你在用 is 比较一个字面量整数（如 1）和 True，这通常是代码错误（因为 is 比较的是身份，而不是值）。*

*Python 建议你使用 == 来比较值是否相等，除非你确实想检查是否是同一个对象。*

 

input

**等待用户输入**

执行下面的程序在按回车键后就会等待用户输入：

**实例(Python 3.0+)**

\#!/usr/bin/python3 input("\n\n按下 enter 键后退出。")

**同一行显示多条语句**

Python 可以在同一行中使用多条语句，语句之间使用分号 **;** 分割，以下是一个简单的实例：

**实例(Python 3.0+)**

\#!/usr/bin/python3 import sys; x = 'runoob'; sys.stdout.write(x + '\n')

**print 输出**

**print** 默认输出是换行的，如果要实现不换行需要在变量末尾加上 **end=""**：

**import 与 from...import**

在 python 用 **import** 或者 **from...import** 来导入相应的模块。

将整个模块(somemodule)导入，格式为： **import somemodule**

从某个模块中导入某个函数,格式为： **from somemodule import somefunction**

从某个模块中导入多个函数,格式为： **from somemodule import firstfunc, secondfunc, thirdfunc**

将某个模块中的全部函数导入，格式为： **from somemodule import \***

\#!/usr/bin/python3

第一行注释标的是指向 python 的路径，告诉操作系统执行这个脚本的时候，调用 /usr/bin 下的 python 解释器。

此外还有以下形式（推荐写法）：

\#!/usr/bin/env python3

这种用法先在 env（环境变量）设置里查找 python 的安装路径，再调用对应路径下的解释器程序完成操作

关于注释，也可以使用 **''' '''** 的格式在三引号之间书写较长的注释；

**''' '''** 还可以用于在函数的首部对函数进行一个说明：

 

# 函数

函数是一种方法，可以用来实现特定的功能。如果想要使用这个功能， 只需要对该函数进行调用即可

## 内建函数

Python自带的函数

 

## 创建函数

创建并使用函数可以减少程序中重复的代码，使更抽象和清晰

def 函数名称

def say_hello():

​    print(“hi”)

say_hello()

括号内可以填入参数，也可以不填，或填入多个参数，用逗号隔开即可。如果需要返回参数，，可以在需要返回的内容前加return

def name(value a,value b):

​    语句

​    return c,d..

name(a,b)

# 数据类型

 

在内存中存储的数据可以有多种类型

1、 数字

2、 字符串

3、 列表

4、 元组

5、 字典

6、 集合

 

必须有明确的数据类型，程序才能分配给常量、变量精确的存储大小，才能进行精确或高效率的运算

## 数字

整数、浮点数、复数

整数(int)以十进制数字的字符串写法出现。只有一种int，表示为长整型。

浮点数

实数在python中称作浮点数，如果参与运算的两个数其中有一个为浮点数，则运算结果亦为浮点数。只要有小数点如12.0，则结果仍然把他看作浮点数

布尔型 

True和Fales，布尔型在本质上用整型1，0分别存储，条件语句和循环语句都是用布尔表达式作为条件

**注意:** 在 Python 中，所有非零的数字和非空的字符串、列表、元组等数据类型都被视为 True，只有 **0****、空字符串、空列表、空元组**等被视为 False。因此，在进行布尔类型转换时，需要注意数据类型的真假性。

 

 

复数

实部+虚部，虚部以j或者J结尾

当你指定一个值时，Number 对象就会被创建：

var1 = 1

var2 = 10

您也可以使用del语句删除一些对象引用。

**del** 语句的语法是：

del var1[, var2[, var3[...., varN]]]

您可以通过使用 **del** 语句删除单个或多个对象。例如：

del var

del var_a, var_b

 

在交互模式中，最后被输出的表达式结果被赋值给变量 **_** 

 

4、在混合计算时，Python会把整型转换成为浮点数。

**海象运算符的优点：**

- 海象运算符（:=）允许在表达式内部进行赋值，这可以减少代码的重复，提高代码的可读性和简洁性。
- 在上述例子中，传统写法需要单独一行来赋值 n，然后在 if 语句中进行条件检查。而使用海象运算符的写法可以在 if 语句中直接进行赋值和条件检查。

\>>> 9//2

4

\>>> -9//2

-5

\>>> 9//-2

-5

\>>> -9//-2

4

符号与被除数保持一致，若被除数为负值，必须记得让其余数为正

| and  | x  and y | 布尔"与" - 如果  x 为 False，x and y 返回 x 的值，否则返回 y 的计算值。 | (a  and b) 返回 20。     |
| ---- | -------- | ------------------------------------------------------------ | ------------------------ |
| or   | x  or y  | 布尔"或" - 如果 x 是 True，它返回 x 的值，否则它返回 y 的计算值。 | (a  or b) 返回 10。      |
| not  | not  x   | 布尔"非" - 如果  x 为 True，返回 False 。如果 x 为 False，它返回  True。 | not(a  and b) 返回 False |

 

 

/   除 - x 除以 y   结果永远是小数

 

 

C 语言用 && 做逻辑与，用 & 做按位与。

Python 用 and 做逻辑与，用 & 做按位与。

## 序列

在python中，包含 6种内建序列

有三种基本序列类型：list, tuple 和 range 对象。 为处理 [二进制数据](https://docs.python.org/zh-cn/3/library/stdtypes.html#binaryseq) 和 [文本字符串](https://docs.python.org/zh-cn/3/library/stdtypes.html#textseq) （字符串str、**字节数组 (Bytearray)，** **字节 (Bytes)**）

序列中也可以包含其它序列

序列的操作包括：索引(indexing)、分片（slicing）、加乘、以及检查成员资格（in），除此之外，还有计算长度，找出最小和最大元素的内建函数

 

### 字符串

字符串是由数字、字母、下划线组成的一串字符，表示文本的数据类型。

是一个有序字符的集合。所有标准的序列操作都适用于字符串，但字符串不可变。

name=”lilei”

paragraph=”””asda

saf”””

字符串可以是单引号、双引号和三引号来创建。但是三引号（’’’和““”）可以输出多行的长字符串

加了引号的数字是字符串

索引与切片

使用索引’’[]”可以获取特定元素，使用切片操作“[:]”可以提取对应的子字符串。

1、从左到右默认从0开始，最大范围是字符串长度少1（因为从0开始，但是数字符串是从1开始的）

2、从右往左索引默认是-1开始，最大范围是字符串开头

- 字符串切片 **str[start:end]**，其中 start（包含）是切片开始的索引，end（不包含）是切片结束的索引。
- 字符串的切片可以加上步长参数 step，语法格式如下：**str[start:end:step]**

 

按字面意义级联字符串，如 **"this " "is " "string"** 会被自动转换为 **this is string**。

 

转义

转义符 **\**。

反斜杠可以用来转义，使用 **r** 可以让反斜杠不发生转义。 如 **r"this is a line with \n"** 则 **\n** 会显示，并不是换行。

与 C 字符串不同的是，Python 字符串不能被改变。向一个索引位置赋值，比如 **word[0] = 'm'** 会导致错误。

如果字符串中也要用到单引号

1、 使用其他引号

2、 使用反斜线进行转义

Sentence=’Let \’s go!’

 \n可以用来换行。字符串的末尾不能是反斜线。

 

转换工具。

num=15

int(“num”)

str(num)

修改字符串

字符串本身不可变，但是我们可以通过分片与合并这样的操作来建立新的字符串。

sen=”spammy”

错误的：sen[3:5]=xx

TypeError: 'str' object does not support item assignment

sen=sen[:3]+’xx’+sen[5:]

如果想替换一个字符的话，使用字符串的replace方法实现

注意：

| **方式**           | **调用的方法** | **目的**       | **输出内容**                             |
| ------------------ | -------------- | -------------- | ---------------------------------------- |
| **直接输入变量名** | **__repr__()** | 调试、明确表示 | 显示转义序列（如 **\n**, **\t**）        |
| **使用 print()**   | **__str__()**  | 展示、友好阅读 | **解释**并执行转义序列（真正换行、制表） |

 

字符串的使用

访问字符串的值

python里没有字符这个类型，而是使用长度为1的字符串来表示这个概念

无论是索引还是切片，返回的都是**字符串**。

字符串的操作符

检查符：in，not in

检查符可以用来判断一个字符或者一个子串是否出现在另一个字符串中。检验结果以布尔值 的形式返回。

连接符+

可以用来连接字符串

加上空格，s1+’ ’+s2

用*可以将一个序列重复n次

len

min返回最小值

max返回最大值

读取用户输入 input(“请输入>”)括号内可填提示输入的文字

 

#### Python 字符串格式化

Python 支持格式化字符串的输出 。尽管这样可能会用到非常复杂的表达式，但最基本的用法是将一个值插入到一个有字符串格式符 %s 的字符串中。

在 Python 中，字符串格式化使用与 C 中 sprintf 函数一样的语法。

**实例(Python 3.0+)**

\#!/usr/bin/python3 print ("我叫 %s 今年 %d 岁!" % ('小明', 10))

**f-string** 格式化字符串以 **f** 开头，后面跟着字符串，字符串中的表达式用大括号 {} 包起来，它会将变量或表达式计算后的值替换进去，实例如下：

**实例**

\>>> name = 'Runoob'
 \>>> f'Hello {name}' # 替换变量
 'Hello Runoob'
 \>>> f'{1+2}'     # 使用表达式
 '3'
 
 \>>> w = {'name': 'Runoob', 'url': 'www.runoob.com'}
 \>>> f'{w["name"]}: {w["url"]}'
 'Runoob: [www.runoob.com](http://www.runoob.com)'

**2. str.format() 方法**

Python 2.6 引入的更强大的格式化方式。

**基本语法：** **"****字符串 {占位符}".format(值1, 值2, ...)**

**示例：**

python

name = "Bob"

age = 30

 

*# 按位置参数*

print("Hello, {}! You are {} years old.".format(name, age))

*# Hello, Bob! You are 30 years old.*

 

*# 按索引（可重复使用）*

print("{0} is {1} years old. Good job, {0}!".format(name, age))

*# Bob is 30 years old. Good job, Bob!*

 

### 列表

列表内容需要放在方括号”[]”中，中间用“，“相隔。

1、 是任意对象（六个标准数据类型和用户自定义对象）的有序集合

2、 可以进行分片和合并

3、 可变长度、异构以及人已潜逃

4、 可变序列

5、 对象引用数组

#### 真正的实现方式

Python列表的切片赋值是在原地修改列表，其底层实现要高效得多。大致过程如下：

 

1. 内存布局

列表在内存中存储为：

 

一个指针数组，指向各个元素对象

 

一个分配容量（allocated size），通常比实际长度大

例如：s = [1, 2, 3] 可能的内存布局：

元素指针: [ptr1, ptr2, ptr3, None, None] # 分配了5个位置，只用了3个

长度: 3

容量: 5

2. 切片赋值 s[3:3] = [4] 的过程

步骤1：计算需要移动的元素数量

 

切片 [3:3] 长度为0，不需要删除任何元素

 

需要插入1个新元素

 

步骤2：检查容量是否足够

 

当前长度=3，容量=5，足够插入1个元素

 

如果容量不够，会先扩容（通常按一定比例，如1.125倍）

 

步骤3：移动元素（如果需要）

 

由于是在末尾插入，不需要移动现有元素

 

步骤4：插入新元素

 

直接在索引3的位置放入新元素 4

 

更新长度计数器：3 → 4

append添加元素

del删除列表的元素

 

列表脚本操作符——+和*

in

迭代

列表函数和方法

函数

len(list)

max(list)

min(list)

list(seq)将元组转换为列表

方法

list.append(obj)

list.count(obj)

list.extend(seq)

list.index(obj)

list.pop(obj=list[-1])

list.remove(obj)

list.reverse()

 

list.sort([func])

增删查找

grades=[“abv”,11]

### 元组

元组由简单的对象组构成，是一种不可变徐连，元组与列表相似，但是不能在原处修改。用“()”中断一系列项。虽然元组不支持任何方法调用，但是可以嵌入到任何类别的对象。元组可以在映射（和集合的成员）作为键来使用，列表不行。元组作为很多内建函数和方法的返回值存在，也就是说，你必须对元组进行处理。

t=(10,20,30,”hms”)

tup1 = ()  # 空元组

tup2 = (20,) # 一个元素，需要在元素后添加逗号

如果你想创建只有一个元素的元组，需要注意在元素后面添加一个逗号，以区分它是一个元组而不是一个普通的值，这是因为在没有逗号的情况下，Python会将括号解释为数学运算中的括号，而不是元组的表示。

如果不添加逗号，如下所示，它将被解释为一个普通的值而不是元组：

not_a_tuple = (42)

这样的话，not_a_tuple 将是整数类型而不是元组类型。

string、list 和 tuple 都属于 sequence（序列）。

 

 

| **类型** | **可变性** | **示例**              |
| -------- | ---------- | --------------------- |
| 列表     | ✅ 可变     | **[1,  2, 3]**        |
| 字节数组 | ✅ 可变     | **bytearray(b'abc')** |
| 元组     | ❌ 不可变   | **(1,  2, 3)**        |
| 字符串   | ❌ 不可变   | **'hello'**           |
| 范围     | ❌ 不可变   | **range(5)**          |
| 字节     | ❌ 不可变   | **b'hello'**          |
| 数字     | 不可变     | **123**               |
| 字典     | 可变       |                       |
| 集合     | 可变       |                       |

 

## 字典

字典是一种无序列表，用“{}”创建。字典中的每个成员由两部分组成：一部分是键，一部分是值。用冒号相连。key:value,用逗号分隔。

 

字典是另一种可变容器模型，且可存储任意类型对象，字典是python中唯一内建的映射类型，映射是指通过名字（键）来引用值 的数据结构

 

Grades={“liei”:”98”}

字典中的键是唯一的，是不可变类型，如数字，字符串、元组，如果重复的话最后一个键值对会替换 前面的，但值不唯一，且可以是任何数据类型(即可以是)。

访问字典中的值，dict[key]=value

修改删除字典元素

dict[key]=new_value

del dict[key]

dict.clear()

函数

cmp(dict1,dict2)

len(dict)

str(dict)

方法

dict.clear()

dict.copy()

dict.fromkeys(seq[,val])

dict.get(ket,default=None) 如果值不在字典中返回default的值

dict.items()

dict.keys()

dict.setdefault(key,default=None)与get类似，但是如果键不在于字典中，会添加键的值并设为defalut

dict.update(dict2)

dict.values()

dict.pop(key[,default])

dict.popitem()

 

TypeError: dict.get() takes no keyword arguments：在Python中，**dict.get()** 方法的参数是**位置参数**，而不是关键字参数。

**关键点：/ 符号的含义**

帮助信息中的 **/** 符号是理解这个问题的关键！

**/ 的作用**

在Python的函数定义中，**/** 表示：**在它之前的参数必须是位置参数**。

所以：

python

get(self, key, default=None, /)

这意味着：

- **self**, **key**, **default** 这些参数都**必须作为位置参数传递**
- **不能**使用关键字参数的形式（如 **default=None**）

## 集合

由内置类型set定义，将所有项元素放在花括号内 {}“，”以逗号分隔，a={10,20,30}

集合可以分成两类，一类是可变集合，即可以原地修改；一类是不可变集合，即不可原地修改。集合可以有任意数量的元素，它们可以是不同类型。但是，集合不能有可变元素，例如列表，集合，或字典。

集合之间可以进行数学集合运算。

在 Python 中，集合使用大括号 **{}** 表示，元素之间用逗号 **,** 分隔。

另外，也可以使用 **set()** 函数创建集合。

**注意：**创建一个空集合必须用 **set()** 而不是 **{ }**，因为 **{ }** 是用来创建一个空字典。

创建格式：

parame = {value01,value02,...}

或者

set(value)

 

## 参数类型

### 位置参数 (Positional Arguments)

位置参数是指调用函数时通过参数的位置顺序来传递值的参数。，值的顺序必须与函数定义时参数的顺序一致。

### 关键字参数 (Keyword Arguments)

**关键字参数**是指调用函数时通过**参数名=值**的形式来传递值的参数。顺序不重要，因为你是通过名字来指定的。

位置参数必须在关键字参数之前，即example(1, 2, c=3, d=4)

### 默认参数

用于定义函数，为参数提供默认值，调用函数时可传可不传该默认参数的值（注意：所有位置参数必须出现在默认参数前，包括函数定义和调用）

\# 正确的默认参数定义方式--> 位置参数在前，默认参数在后

def print_hello(name, sex=1):

### 可变参数

定义函数时，有时候我们不确定调用的时候会传递多少个参数(不传参也可以)。此时，可用包裹(packing)位置参数，或者包裹关键字参数，来进行参数传递，会显得非常方便。

**函数定义**

**1、包裹位置传递**

def func(*args):

  ....

 

\# func()

\# func(a)

\# func(a, b, c)

我们传进的所有参数都会被args变量收集，它会根据传进参数的位置合并为一个元组(tuple)，args是元组类型，这就是包裹位置传递

**2、包裹关键字传递**

def func(**kargs):

  ....

 

\# func(a=1)

\# func(a=1, b=2, c=3)

kargs是一个字典(dict)，收集所有关键字参数

### 解包裹参数

*和**，也可以在**函数调用**的时候使用，称之为解包裹(unpacking)

 

1、在传递元组时，让元组的每一个元素对应一个位置参数

def print_hello(name, sex):

  print name, sex

 

\# args = ('tanggu', '男')

\# print_hello(*args)，相当于传入print_hello(‘tanggu’,’男’)

2、在传递词典字典时，让词典的每个键值对作为一个关键字参数传递给函数

def print_hello(name,sex):

  print name,sex

 

\# kargs = {'name': 'tanggu', 'sex'：'男'}

\# print_hello(**kargs)，相当于传入print_hello(name='tanggu', sex='男')

也就是说，在定义的时候有*号是把传入的参数打包成一个元组/字典

传参时有*号是把传入的元组/字典解包为一个个参数

可以看到，这两个是Python中的可变参数。*args 表示任何多个无名参数，它是一个tuple；**kwargs 表示关键字参数，它是一个dict。并且同时使用*args和**kwargs时，必须*args参数列要在**kwargs前，像foo(a=1, b='2', c=3, a', 1, None, )这样调用的话，会提示语法错误“SyntaxError: non-keyword arg after keyword arg”。

def foo(x,*args,a=4,**kwargs):　　#使用默认参数时，注意默认参数的位置要在args之后kwargs之前

  print(x)

  print(a)

  print(args)

  print(kwargs)

 

foo(1,5,6,7,8,y=2,z=3) #调用函数，不修改默认参数

1  #x的值

4  #a的值

(5, 6, 7, 8)  #*args的值

{'y': 2, 'z': 3}  ##kwargs的值

def foo(x,a=4,*args,**kwargs):　　##注意：当需要修改默认参数时，要调整默认参数的位置，要放在args之前即可，但不可放在开头。

  print(x)

  print(a)

  print(args)

  print(kwargs)

 

foo(1,9,5,6,7,8,y=2,z=3)  #调用函数，修改默认参数a为9

1  #x的值

9  #被修改后a的值

(5, 6, 7, 8)  #args的值

{'y': 2, 'z': 3}  #kwargs的值

### 位置参数、默认参数、可变参数的混合使用

基本原则是：先位置参数，默认参数，包裹位置，包裹关键字(定义和调用都应遵循)

 

小结：

位置参数：

调用函数时所传参数的位置必须与定义函数时参数的位置相同

关键字参数：

使用关键字参数会指定参数值赋给哪个形参，调用时所传参数的位置可以任意

*位置参数：可接受任意数量的位置参数(元组)；只能作为最后一个位置参数出现，其后参数均为关键字参数

**关键字参数：可接受任意数量的关键字参数(字典)；只能作为最后一个参数出现

默认参数：默认参数的赋值只会在函数定义的时候绑定一次，默认值不会再被修改

知道*args和`**kwarg是什么了吧。还有一个很漂亮的用法，就是创建字典：

  def kw_dict(**kwargs):

​    return kwargs

  print kw_dict(a=1,b=2,c=3) == {'a':1, 'b':2, 'c':3}

其实python中就带有dict类，使用dict(a=1,b=2,c=3)即可创建一个字典了。

## bytes 类型

在 Python3 中，bytes 类型表示的是不可变的二进制序列（byte sequence）。

与字符串类型不同的是，bytes 类型中的元素是整数值（0 到 255 之间的整数），而不是 Unicode 字符。

bytes 类型通常用于处理二进制数据，比如图像文件、音频文件、视频文件等等。在网络编程中，也经常使用 bytes 类型来传输二进制数据。

创建 bytes 对象的方式有多种，最常见的方式是使用 b 前缀：

此外，也可以使用 bytes() 函数将其他类型的对象转换为 bytes 类型。bytes() 函数的第一个参数是要转换的对象，第二个参数是编码方式，如果省略第二个参数，则默认使用 UTF-8 编码：

x = bytes("hello", encoding="utf-8")

与字符串类型类似，bytes 类型也支持许多操作和方法，如切片、拼接、查找、替换等等。同时，由于 bytes 类型是不可变的，因此在进行修改操作时需要创建一个新的 bytes 对象。例如：

**实例**


 x = b"hello"
 y = x[1:3] # 切片操作，得到 b"el"
 z = x + b"world" # 拼接操作，得到 b"helloworld"

需要注意的是，bytes 类型中的元素是整数值，因此在进行比较操作时需要使用相应的整数值。例如：

**实例**

x = b"hello"
 **if** x[0] == ord("h"):
   **print**("The first element is 'h'")

其中 ord() 函数用于将字符转换为相应的整数值。

有时候，我们需要对数据内置的类型进行转换，数据类型的转换，一般情况下你只需要将数据类型作为函数名即可。

 

 

## Python 数据类型转换可以分为两种：

- 隐式类型转换 - 自动完成
- 显式类型转换 - 需要使用类型函数来转换

**隐式类型转换**

在隐式类型转换中，Python 会自动将一种数据类型转换为另一种数据类型，不需要我们去干预。

以下实例中，我们对两种不同类型的数据进行运算，较低数据类型（整数）就会转换为较高数据类型（浮点数）以避免数据丢失。

**实例**

num_int = 123
 num_flo = 1.23
 
 num_new = num_int + num_flo
 
 **print**("num_int 数据类型为:",type(num_int))
 **print**("num_flo 数据类型为:",type(num_flo))
 
 **print**("num_new 值为:",num_new)
 **print**("num_new 数据类型为:",type(num_new))

以上实例输出结果为：

num_int 数据类型为: <class 'int'>

num_flo 数据类型为: <class 'float'>

num_new: 值为: 124.23

num_new 数据类型为: <class 'float'>

代码解析：

- 实例中我们对两个不同数据类型的变量 num_int 和 num_flo 进行相加运算，并存储在变量 num_new 中。
- 然后查看三个变量的数据类型。
- 在输出结果中，我们看到 num_int 是 整型（integer） ， num_flo 是 浮点型（float）。
- 同样，新的变量 num_new 是 浮点型（float），这是因为 Python 会将较小的数据类型转换为较大的数据类型，以避免数据丢失。

 print(num_int+num_str)

TypeError: unsupported operand type(s) for +: 'int' and 'str'

从输出中可以看出，整型和字符串类型运算结果会报错，输出 TypeError。 Python 在这种情况下无法使用隐式转换。

但是，Python 为这些类型的情况提供了一种解决方案，称为显式转换。

**显式类型转换**

在显式类型转换中，用户将对象的数据类型转换为所需的数据类型。 我们使用 int()、float()、str() 等预定义函数来执行显式类型转换。

**int()** 强制转换为整型：

 

# 条件判断

if语句

以布尔值的方式显示结果，即如果if和冒号中间的条件为真，那么后面的语句块执行

else语句

为if语句提供了另一种选择，如果if判定为假，执行else语句

elif语句

else if的简写

直到有一个符合条件就不继续往下

# 运算符

常用运算符

算数运算符

比较（关系）预算夫

赋值运算符

逻辑运算符

身份运算符

比较两个对象的内存位置

 

is 运算符任一侧的变量指向相同对象，则返回True，否则返回False

is not

| **运算符** | **描述**                                     | **实例**                                                     |
| ---------- | -------------------------------------------- | ------------------------------------------------------------ |
| is         | is  是判断两个标识符是不是引用自一个对象     | **x  is y**,  类似 **id(x)  == id(y)** , 如果引用的是同一个对象则返回 True，否则返回 False |
| is  not    | is  not 是判断两个标识符是不是引用自不同对象 | **x  is not y** ， 类似 **id(x)  != id(y)**。如果引用的不是同一个对象则返回结果 True，否则返回 False。 |

 

*is 与 == 区别：*

*is 用于判断两个变量引用对象是否为同一个， == 用于判断引用变量的值是否相等。*

\>>>a = [1, 2, 3] >>> b = a >>> b is a True >>> b == a True >>> b = a[:] >>> b is a False >>> b == a True

 

成员运算符

运算符优先级

 

a True b False

and a and b False

or a or b True

not a False

&按位与

^| 按位异或和常规的“OR”

# 循环

 将一个语句重复执行多次就是循环

while循环

while语句用于循环执行程序，以处理重复的相同任务

while 判断条件：

​    执行语句……

执行语句可以是单个语句或者语句块

判断条件可以是任何表达式，任何非零或非空（None）的值均为True。当判断条件False循环结束。

 

while语句可以用else，当循环条件为false时执行

 

死循环，while的判断条件永远为True

for循环

for循环可以遍历任何序列和其它可迭代对象（可以按次序获取的对象）的集合，例如列表或者字符串

for 可重复变量 in 序列：

 statement(s)

else语句会在循环正常执行完（即for不是通过break跳出而中断）执行

break

用于退出循环，即循环条件没有False条件或者序列还没被完全递归完，停止执行循环语句。

如果使用嵌套循环，break语句将停止执行最深层的寻魂，并执行下一行代码。

‘判断条件“还可以是个常值，表示循环必定成立。

跳出循环

continue

用来告诉python跳过当前循环的剩余语句，然后继续进行下一轮循环

空语句：pass 一般用作占位语句

循环嵌套

代码块的缩进保持一致

 

推导式

**列表推导式**

列表推导式格式为：

[表达式 for 变量 in 列表] 

[out_exp_res for out_exp in input_list]

 

或者 

 

[表达式 for 变量 in 列表 if 条件]

[out_exp_res for out_exp in input_list if condition]

 new_names = [name.upper()**for** name **in** names **if** len(name)>3]

**字典推导式**

字典推导基本格式：

{ key_expr: value_expr for value in collection }

 

或

 

{ key_expr: value_expr for value in collection if condition }

\>>> newdict = {key:len(key) **for** key **in** listdemo}

 

**集合推导式**

集合推导式基本格式：

{ expression for item in Sequence }

或

{ expression for item in Sequence if conditional }

**实例**

\>>> a = {x **for** x **in** 'abracadabra' **if** x **not** **in** 'abc'}

**元组推导式（生成器表达式）**

元组推导式可以利用 range 区间、元组、列表、字典和集合等数据类型，快速生成一个满足指定需求的元组。

元组推导式基本格式：

(expression for item in Sequence )

或

(expression for item in Sequence if conditional )

元组推导式和列表推导式的用法也完全相同，只是元组推导式是用 **()** 圆括号将各部分括起来，而列表推导式用的是中括号 **[]**，另外元组推导式返回的结果是一个生成器对象。

例如，我们可以使用下面的代码生成一个包含数字 1~9 的元组：

**实例**

\>>> a = (x **for** x **in** range(1,10))
 \>>> a
 <generator object <genexpr> at 0x7faf6ee20a50> # 返回的是生成器对象
 
 \>>> tuple(a)    # 使用 tuple() 函数，可以直接将生成器对象转换成元组
 (1, 2, 3, 4, 5, 6, 7, 8, 9)

异常

**语法错误**

Python 的语法错误或者称之为解析错，是初学者经常碰到的，如下实例

\>>> **while** True **print**('Hello world')
  File "<stdin>", line 1, **in** ?
   **while** True **print**('Hello world')
           ^
 SyntaxError: invalid syntax

这个例子中，函数 print() 被检查到有错误，是它前面缺少了一个冒号 **:** 。

语法分析器指出了出错的一行，并且在最先找到的错误的位置标记了一个小小的箭头。

**异常**

即便 Python 程序的语法是正确的，在运行它的时候，也有可能发生错误。运行期检测到的错误被称为异常。

大多数的异常都不会被程序处理，都以错误信息的形式展现在这里:

异常以不同的类型出现，这些类型都作为信息的一部分打印出来: 例子中的类型有 ZeroDivisionError，NameError 和 TypeError。

错误信息的前面部分显示了异常发生的上下文，并以调用栈的形式显示具体信息。

 

# 类

类是用来描述具有相同的属性和方法的对象的集合

它定义了该集合中每个对象所共有的属性和方法。

所有的对象都属于一个类。称为类的实例，对象是类的实例。

创建类

class name():#命名时首字母大写，要用驼峰命名法。

class Student():

​    def say_hi(self):

​       print(“Hi”)

self 指一个实例自己，而不是整个类

创建实例对象

类的实例化类似函数调用方式，通过__init__方法接收参数

def __init__(self,name):

​    self.name=name

 

lilie=Student(“hnmeimei”)

Python内置类属性

__dict__类的属性

__doc__ 类的文档字符串

__name__ 类名

__module__ 类定义所在的模块（类的全名是”__main__.className”,如果类位于一个导入模块mymod中，那么className.__module__等于mymod）

__bases__类的所有父类构成元素（包含了一个由所有父类组成的元组）

您可以通过在类定义的第一行添加一个字符串来建立文档字符串（docstring）。

class Student:

  """

类文档字符串 

  """

  def __init__(self, name, age):

​    self.name = name

​    self.age = age

 

\# 访问文档字符串

print("Student.__doc__:", Student.__doc__)

class Student:

  """

  学生类 - 管理学生信息

 

  属性:

​    name (str): 学生姓名

​    age (int): 学生年龄

​    student_id (str): 学号

 

  方法:

​    display_info(): 显示学生信息

​    update_age(new_age): 更新年龄

  """

 

  StudentCount = 0

 

  def __init__(self, name, grade):

​    self.name = name

​    self.grade = grade

​    Student.StudentCount += 1

 

  def displayCount(self):

​    print("Total Student %d" % Student.StudentCount)

 

  def displayStudent(self):

​    print("Name : ", self.name, ", Grade: ", self.grade)

 

print("Student.__doc__", Student.__doc__)

print("Student.__name__", Student.__name__)

print("Student.__module__", Student.__module__)

print("Student.__bases__", Student.__bases__)

print("Studen.__dict__", Student.__dict__)

 

Student.__doc__ 

  类文档字符串

 

Student.__name__ Student

Student.__module__ __main__

Student.__bases__ (<class 'object'>,)

Studen.__dict__ {'__module__': '__main__', 'StudentCount': 0, '__init__': <function Student.__init__ at 0x0000024738495940>, 'displayCount': <function Student.displayCount at 0x0000024738495DC0>, 'displayStudent': <function Student.displayStudent at 0x0000024738495E50>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}

类的继承

继承完全可以理解成类之间的类型和子类型关系。如果你已经有了一个类，而又想建立一个非常类似的类。

class 子类名（父类名）:

1在继承中父类的构造（__init__（））方法不会被自动调用，它需要在其子类的构造中亲自专门调用。在调用父类的方法时，需要加上父类的类名前缀，且需要带上self参数变量。类中调用普通函数时并不需要带上self参数

3、 python总是先查找对应类型的方法，如果它不能在子类中找到对应方法，他才开始到父类中逐个查找。

如果继承多个类，多重继承

继承的父类列表跟在类名之后

class 子类名（父类1[.父类2,….]）

 

 



# 装饰器

回忆：函数名同样表示地址。程序由一个或者多个函数构成。每个函数包含若干条语句，编译以后对应一组指令。程序执行的时候，系统会为函数分配一段连续的内存空间来存放函数的指令序列。函数名即为函数第一条指令的地址（函数指针）。调用函数实际上是根据这个指针去访问执行函数。

**一、使用函数定义装饰器**

\# 定义装饰器

def log_decorator(func):

  def wrapper(*args, **kwargs):

​    print(f"Calling function {func.__name__} with arguments: {args}, {kwargs}")

​    result = func(*args, **kwargs)

​    print(f"Function {func.__name__} returned: {result}")

​    return result

  return wrapper

 

\# 使用装饰器

@log_decorator

def add(a, b):

  return a + b

add(3, 4)

1、相当于先是log_decorator(add),返回了一个wrapper(实际上返回的是wrapper函数的地址)，并赋给add，即add=log_decoractor(func)。因此实行add，本质上是实行wrapper函数，即wrapper（3，4）
