
> Life is short, you need Python
>——Bruce Eckel
<!-- more -->
## 解释器与虚拟机
[都是解释执行,为什么跑java的叫虚拟机,而python ruby等只能叫解释器?](https://www.zhihu.com/question/647430973/answer/3440440306)?
[lua](https://www.zhihu.com/search?q=lua&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra=%7B%22sourceType%22%3A%22answer%22%2C%22sourceId%22%3A3440440306%7D) 也是脚本语言,人家 lua 的就叫虚拟机。
区别不是什么解释执行的问题,而是概念本身就很清晰明确。虚拟机,它为什么叫虚拟机?这才是你应该思考的问题。虚拟机,它本身就是对物理机的一个虚拟,就是在模拟 CPU 指令和执行的过程,虚拟机一般分为 [寄存器](https://www.zhihu.com/search?q=%E5%AF%84%E5%AD%98%E5%99%A8&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra=%7B%22sourceType%22%3A%22answer%22%2C%22sourceId%22%3A3440440306%7D) 虚拟机和栈虚拟机,这也是对物理机的模拟。Lua 就是寄存器虚拟机,Java 是栈虚拟机,一个是模拟寄存器操作,一个是模拟栈操作。
如果你运行时没有这一套机制,模仿指令和指令操作,你凭什么叫虚拟机?
一般的解释器,它没有这套机制,是直接执行 [ast](https://www.zhihu.com/search?q=ast&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra=%7B%22sourceType%22%3A%22answer%22%2C%22sourceId%22%3A3440440306%7D),称作解释器,是实至名归的。
当然了,国外教材写得好的地方,就在于人家把前因后果,来龙去脉解释得清清楚楚。Python 和 [Ruby](https://www.zhihu.com/search?q=Ruby&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra=%7B%22sourceType%22%3A%22answer%22%2C%22sourceId%22%3A3440440306%7D) 一开始就是我上面说的,直接解释执行 ast,所以它确实就是解释器,这个命名没问题。但是随着时间发展,[解释器](https://www.zhihu.com/search?q=%E8%A7%A3%E9%87%8A%E5%99%A8&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra=%7B%22sourceType%22%3A%22answer%22%2C%22sourceId%22%3A3440440306%7D) 性能太差了,越来越不满足性能要求,为了提升性能,它们最终都发展成了虚拟机,其实内部早就引入虚拟机那一套机制,虚拟机指令和指令操作。但是他们内部命名没有改,还是沿用了之前的名字,称作解释器。
所以结论就是,Python 这些只是挂着解释器名称的虚拟机
## 基础语法
### 代码块和控制结构的表示
Java 使用大括号({})来表示代码块,例如:
```java
for (int i = 0; i < 5; i++) {
System.out.println("Java");
}
```
Python 使用缩进来表示代码块,通常是四个空格,例如:
```python
for i in range(5):
print("Python")
```
#### 条件语句
Java 中的条件语句使用 if-else 结构,例如:
```java
int num = 10;
if (num > 0) {
System.out.println("Positive");
} else {
System.out.println("Negative");
}
```
Python 中的条件语句使用 if-else 结构,但没有括号,并且使用缩进来表示代码块,例如:
```python
num = 10
if num > 0:
print("Positive")
else:
print("Negative")
```
#### 循环结构
Java 中的常见循环结构是 for 循环和 while 循环,例如:
```java
for (int i = 0; i < 5; i++) {
System.out.println(i);
}
int i = 0;
while (i < 5) {
System.out.println(i);
i++;
}
```
Python 中的常见循环结构是 for 循环和 while 循环,例如:
```python
for i in range(5):
print(i)
i = 0
while i < 5:
print(i)
i += 1
```
### 变量和类型声明
Java 是一种静态类型语言,需要在变量声明时指定其类型,例如:
```java
int num = 10;
String name = "Java";
```
Python 是一种动态类型语言,变量的类型可以根据赋值自动推断,例如:
```python
num = 10
name = "Python"
```
#### 类型注解
在 Java 中,可以使用类型注解来提供额外的类型信息,以帮助编译器进行类型检查和类型推断,例如:
```java
import java.util.List;
public class Main {
public static void main(String[] args) {
List<@NonNull String> names = new ArrayList<>();
names.add("John");
names.add(null); // 编译器会报错,不允许添加null值
}
}
```
在 Python 中,从 Python 3.5 开始引入了类型注解的支持,可以使用类型注解来提供变量和函数的类型信息,例如:
```python
from typing import List
def greet(name: str) -> str:
return "Hello, " + name
names: List[str] = ["John", "Jane"]
```
类型注解是可选的,不是强制要求的。在 Python 中,仍然可以编写没有类型注解的代码。但是,类型注解可以提供更好的代码可读性和可维护性,特别是在大型项目或多人协作的情况下。
类型注解可以使用 Python 3.5 引入的函数注解语法来实现,也可以使用类型注解库如 typing 库来提供更丰富的类型注解功能。以下是一个使用类型注解的示例:
```python
for i in range(5):
print("Python")
```0
### 函数
#### 定义
Java 中定义函数需要使用关键字 void(表示无返回值)或指定返回类型,并使用 return 语句返回值,例如:
```python
for i in range(5):
print("Python")
```1
Python 中定义函数使用关键字 def,不需要指定返回类型,并使用 return 语句返回值,例如:
```python
for i in range(5):
print("Python")
```2
#### 静态方法和类方法
在 Java 中,可以使用 static 关键字定义静态方法和静态变量,静态方法可以直接通过类名调用,例如:
```python
for i in range(5):
print("Python")
```3
在 Python 中,可以使用@staticmethod 装饰器定义静态方法,静态方法可以通过类名或实例调用,例如:
```python
for i in range(5):
print("Python")
```4
#### 默认参数
在 Java 中,方法的参数没有默认值,每次调用方法都需要显式传递参数,例如:
```python
for i in range(5):
print("Python")
```5
在 Python 中,方法的参数可以指定默认值,如果调用方法时没有传递对应参数,则使用默认值,例如:
```python
for i in range(5):
print("Python")
```6
#### 函数调用和参数传递
##### 值传递方式
Java 中的参数传递方式是值传递,也就是说,当你将一个参数传递给一个函数时,函数会得到一个参数的副本,而不是参数本身。这意味着在函数内部修改参数的值不会影响传递给函数的原始值。
Python 中的参数传递方式是引用传递,也就是说,当你将一个参数传递给一个函数时,函数会得到一个指向参数的引用,而不是参数本身。这意味着在函数内部修改参数的值会影响传递给函数的原始值。
例如,在 Java 中,以下代码将打印出 "10":
```python
for i in range(5):
print("Python")
```7
而在 Python 中,以下代码将打印出 "20":
```python
for i in range(5):
print("Python")
```8
##### 对象传递方式
在 Java 中,对象是通过引用传递的,即传递的是对象的引用而不是对象本身,例如:
```python
for i in range(5):
print("Python")
```9
在 Python 中,对象的传递方式是值传递,但对于可变对象(如列表、字典等),传递的是对象的引用,例如:
```java
int num = 10;
if (num > 0) {
System.out.println("Positive");
} else {
System.out.println("Negative");
}
```0
#### 匿名函数
在 Java 中,可以使用接口和匿名类来实现类似于匿名函数的功能,例如:
```java
int num = 10;
if (num > 0) {
System.out.println("Positive");
} else {
System.out.println("Negative");
}
```1
在 Python 中,可以使用 Lambda 表达式来创建匿名函数,例如:
```java
int num = 10;
if (num > 0) {
System.out.println("Positive");
} else {
System.out.println("Negative");
}
```2
#### 函数式编程
在 Java 中,函数式编程的支持较为有限,但可以使用 Lambda 表达式和 Stream API 来实现一些函数式编程的特性,例如:
```java
int num = 10;
if (num > 0) {
System.out.println("Positive");
} else {
System.out.println("Negative");
}
```3
在 Python 中,函数式编程是一种核心特性,支持函数作为一等公民,可以使用 Lambda 表达式、高阶函数和内置函数等来实现函数式编程的特性,例如:
使用 Lambda 表达式和内置函数进行函数式编程
```java
int num = 10;
if (num > 0) {
System.out.println("Positive");
} else {
System.out.println("Negative");
}
```4
### 数据结构
#### 基本数据类型
Java 中有 byte,short,int,long,float,double,是按照占用空间和空间存储来严格划分
python 中就 int 和 float,代表一切了,这有点像 js 中的风格,业内称为弱引用
#### 类型
在 Python 中,内置了列表(List)、集合(Set)和字典(Dictionary)等集合类型,可以直接使用,例如:
列表 - Java 中的数组、列表
元组 - Java 中的列表,但是是[不可变的](不可变的.md)的
字典 - Java 中的 map
set - Java 中的 set
```java
int num = 10;
if (num > 0) {
System.out.println("Positive");
} else {
System.out.println("Negative");
}
```5
#### 数组和列表
Java 中的数组是固定长度的,需要在声明时指定大小,并且只能存储相同类型的元素,例如:
```java
int num = 10;
if (num > 0) {
System.out.println("Positive");
} else {
System.out.println("Negative");
}
```6
在 Python 中,列表是动态长度的数据结构,可以根据需要动态添加或删除元素,例如:
```java
int num = 10;
if (num > 0) {
System.out.println("Positive");
} else {
System.out.println("Negative");
}
```7
列表切片
在 Java 中,可以使用 List.subList() 方法来获取子列表,例如:
```java
int num = 10;
if (num > 0) {
System.out.println("Positive");
} else {
System.out.println("Negative");
}
```8
在 Python 中,可以使用切片(Slice)操作来获取子列表,例如:
```java
int num = 10;
if (num > 0) {
System.out.println("Positive");
} else {
System.out.println("Negative");
}
```9
#### 字典操作
在 Java 中,可以使用 Map 接口和相关的实现类来操作字典,例如获取、添加、删除和遍历字典的操作比较繁琐。
在 Python 中,字典的操作更加简洁和方便,可以直接使用字典的方法进行操作,例如:
```python
num = 10
if num > 0:
print("Positive")
else:
print("Negative")
```0
#### 迭代器
在 Java 中,可以使用迭代器(Iterator)来遍历集合(如 List、Set 等),例如:
```python
num = 10
if num > 0:
print("Positive")
else:
print("Negative")
```1
在 Python 中,可以使用迭代器和生成器来遍历可迭代对象,例如:
```python
num = 10
if num > 0:
print("Positive")
else:
print("Negative")
```2
#### 生成器
在 Python 中,可以使用生成器(Generator)来实现迭代器,使用 yield 关键字定义生成器函数,例如:
```python
num = 10
if num > 0:
print("Positive")
else:
print("Negative")
```3
#### 列表推导式和集合推导
在 Java 中,没有直接的语法来创建列表或集合的推导式,需要使用循环和条件语句来实现。
在 Python 中,可以使用列表推导式和集合推导式来快速创建列表或集合,例如:
```python
num = 10
if num > 0:
print("Positive")
else:
print("Negative")
```4
### 字符串操作
Java 中的字符串是不可变的,使用 + 操作符进行字符串拼接,例如:
```python
num = 10
if num > 0:
print("Positive")
else:
print("Negative")
```5
Python 中的字符串是可变的,可以使用 + 操作符或 +=运算符进行字符串拼接,例如:
```python
num = 10
if num > 0:
print("Positive")
else:
print("Negative")
```6
### 模块和导入
在 Java 中,代码通常组织在包(package)中,需要使用 import 语句导入其他包或类,例如:
```python
num = 10
if num > 0:
print("Positive")
else:
print("Negative")
```7
在 Python 中,代码通常组织在模块(module)中,使用 import 语句导入其他模块或函数,例如:
```python
num = 10
if num > 0:
print("Positive")
else:
print("Negative")
```8
在 Python 中,```java
for (int i = 0; i < 5; i++) {
System.out.println(i);
}
int i = 0;
while (i < 5) {
System.out.println(i);
i++;
}
```5 是一个目录(directory),但为了让 Python 解释器能够识别它并从中导入模块,它也被组织成一个 Python 包(package)。要将一个目录转换为 Python 包,你需要在该目录中包含一个名为 ```java
for (int i = 0; i < 5; i++) {
System.out.println(i);
}
int i = 0;
while (i < 5) {
System.out.println(i);
i++;
}
```6 的文件。这个文件可以是空的,它的存在标志着该目录是一个 Python 包,这样你就可以使用类似 ```java
for (int i = 0; i < 5; i++) {
System.out.println(i);
}
int i = 0;
while (i < 5) {
System.out.println(i);
i++;
}
```7 这样的导入语句。
因此,虽然 ```java
for (int i = 0; i < 5; i++) {
System.out.println(i);
}
int i = 0;
while (i < 5) {
System.out.println(i);
i++;
}
```8 是一个目录,添加 ```java
for (int i = 0; i < 5; i++) {
System.out.println(i);
}
int i = 0;
while (i < 5) {
System.out.println(i);
i++;
}
```9 文件后,它也起到了 Python 包的作用,使得目录内的所有模块都可以按照包的结构进行导入和组织。这种做法常见于 Python 项目中,特别是那些需要组织大量代码和模块的大型项目。这样的结构有助于维护测试代码的清晰和可管理性,尤其是当项目规模扩大,测试范围增加时。
### 特殊方法(魔术方法)
在 Java 中,没有像 Python 中的特殊方法(也称为魔术方法),这些方法以双下划线开头和结尾,用于实现对象的特定行为(如迭代、比较、运算符重载等)。
在 Python 中,特殊方法允许类自定义对象的行为,例如 **init**() 用于初始化对象,**str**() 用于返回对象的字符串表示等。
例如,在 Python 中定义一个类并重写特殊方法的示例:
```python
num = 10
if num > 0:
print("Positive")
else:
print("Negative")
```9
在 Python 中,以下是一些常见的以 __ 开头和以 __ 结尾的特殊方法:
**init**():对象初始化方法,在创建对象时自动调用。
**str**():返回对象的字符串表示,可以通过 str() 函数或 print() 函数调用。
**repr**():返回对象的可打印字符串表示,可以通过 repr() 函数调用。
**len**():返回对象的长度,可以通过 len() 函数调用。
**getitem**():通过索引获取对象的元素,可以通过[]运算符调用。
**setitem**():通过索引设置对象的元素,可以通过[]运算符调用。
**delitem**():通过索引删除对象的元素,可以通过 del 关键字和[]运算符调用。
**iter**():返回一个迭代器对象,用于支持对象的迭代。
**next**():返回迭代器的下一个元素,用于支持对象的迭代。
**enter**() 和 **exit**():用于定义上下文管理器,管理资源的获取和释放。
**call**():使对象可以像函数一样被调用。
### 注释
在 Java 中,注释有单行注释(//)和多行注释(/*... */),例如:
```java
for (int i = 0; i < 5; i++) {
System.out.println(i);
}
int i = 0;
while (i < 5) {
System.out.println(i);
i++;
}
```0
在 Python 中,注释使用井号(#、'''、"""),例如:
```java
for (int i = 0; i < 5; i++) {
System.out.println(i);
}
int i = 0;
while (i < 5) {
System.out.println(i);
i++;
}
```1
### 异常类型
在 Java 中,异常类型需要在方法签名中声明或捕获,例如:
```java
for (int i = 0; i < 5; i++) {
System.out.println(i);
}
int i = 0;
while (i < 5) {
System.out.println(i);
i++;
}
```2
在 Python 中,异常类型不需要在方法签名中声明,可以在 except 块中捕获特定的异常类型,例如:
```java
for (int i = 0; i < 5; i++) {
System.out.println(i);
}
int i = 0;
while (i < 5) {
System.out.println(i);
i++;
}
```3
#### Python 常见的异常
ZeroDivisionError:除(或取模)零异常
IndexError:序列中没有此索引
KeyError:映射中没有这个键
NameError:未声明/初始化对象(没有属性)
SyntaxError:Python 语法错误
ValueError:传入无效的参数
#### Traceback 模块
打印异常信息:traceback.pringt_exc()
## IO
python 的比较简单
```java
for (int i = 0; i < 5; i++) {
System.out.println(i);
}
int i = 0;
while (i < 5) {
System.out.println(i);
i++;
}
```4
| r | 打开文件以进行读取(默认)。如果文件不存在,抛出异常。|
|----|--------------------------------------------------|
| w | 打开文件以进行写入,如果文件存在则将其截断至零长度,如果文件不存在则创建新文件。|
| a | 打开文件以进行追加;任何写入的数据将自动添加到文件的末尾。如果文件不存在,则创建新文件进行写入。|
| r+ | 打开文件进行读取和写入。文件指针放在文件的开头。如果文件不存在,抛出异常。|
| w+ | 打开文件进行读取和写入,相当于 w 模式,但也允许读取操作。|
| a+ | 打开文件进行读取和追加;与 a 相似,但文件打开后可进行读取。如果文件不存在,则创建新文件。|
| x | 专为创建新文件而设计,如果文件已存在,返回 FileExistsError。|
| b | 以二进制模式打开文件,而不是文本模式。此模式可以添加到其他模式中,如 rb、wb 或 ab+。|
| t | 以文本模式打开文件(默认)。此模式可以添加到其他模式中,如 rt 或 xt。|
## 参考资料
原文链接:https://blog.csdn.net/qq_42440234/article/details/133107955