python 基础(一)
·
1. python是及时性语言还是编译型语言,有什么区别?
回答
- Python 是一种解释型语言。
- 解释型语言的特点是代码在运行时逐行解释执行,而不是提前编译成机器码。
- Python 的源代码会先被编译成字节码(bytecode),然后由 Python 虚拟机(PVM)解释执行。这个过程对用户透明。
解释型语言 vs 编译型语言
| 特性 | 解释型语言 | 编译型语言 |
|---|---|---|
| 执行过程 | 源代码 -> 解释器逐行解释执行 | 源代码 -> 编译器生成机器码 -> 直接执行 |
| 执行速度 | 较慢,因为需要逐行解释 | 较快,直接运行机器码 |
| 跨平台性 | 高,依赖解释器 | 低,需为目标平台重新编译 |
| 调试方便性 | 容易调试,错误定位直观 | 调试较复杂,错误可能出现在编译阶段 |
代码示例:
python
# Python 是解释型语言,代码逐行解释执行
# Python 是解释型语言,代码逐行解释执行
print("Hello, World!") # 这行代码会被解释器直接执行
x = 10
y = x + 5
print(y) # 输出结果为 15
如果某一行代码出错,解释器会立即报错,而不会继续执行后续代码。例如:
print("Start")
print(1 / 0) # 这里会抛出 ZeroDivisionError
print("End") # 这行代码不会被执行
输出:
Start
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ZeroDivisionError: division by zero
2. 什么是动态类型语言?Python 中变量是如何存储的?
回答
-
动态类型语言:
- 动态类型语言是指变量的类型是在运行时确定的,而不是在编译时确定的。
- 在 Python 中,你不需要显式声明变量的类型,解释器会根据赋值的内容自动推断类型。
-
变量存储机制:
- Python 中的变量本质上是一个指向对象的引用(指针)。
- 变量本身并不存储数据,而是存储了一个指向内存中实际对象的地址。
- 当变量被赋值时,实际上是将该变量指向一个新的对象。
示例:
# 动态类型示例
x = 10 # x 是一个整数
print(type(x)) # 输出:<class 'int'>
x = "Hello" # x 现在是一个字符串
print(type(x)) # 输出:<class 'str'>
# 变量存储机制
a = [1, 2, 3] # a 指向一个列表对象
b = a # b 和 a 指向同一个列表对象
b.append(4) # 修改 b 会影响 a
print(a) # 输出:[1, 2, 3, 4]
# 使用 id() 查看对象的内存地址
print(id(a)) # 输出 a 的内存地址
print(id(b)) # 输出 b 的内存地址,和 a 相同
- 总结:
type()函数可以查看变量的当前类型。id()函数可以查看变量所指向的对象的内存地址。
3. Python 的垃圾回收机制是什么?(引用计数、分代回收等)
Python 的垃圾回收机制主要基于以下三种技术:
-
引用计数:
- 每个对象都有一个引用计数器,记录有多少变量引用了该对象。
- 当引用计数降为 0 时,对象会被立即销毁并释放内存。
-
标记清除(Mark and Sweep):
- 用于解决循环引用的问题(即两个或多个对象互相引用,导致引用计数无法降为 0)。
- 垃圾回收器会定期扫描内存,标记不可达的对象,并清理它们。
-
分代回收(Generational Garbage Collection):
- 将对象分为三代(Generation 0, 1, 2),新创建的对象属于第 0 代。
- 每次垃圾回收时,优先扫描年轻代(第 0 代),如果对象存活下来,则晋升到更高代。
- 这种机制提高了垃圾回收的效率,减少了不必要的扫描。
代码示例:
import sys
# 引用计数示例
a = [1, 2, 3]
print(sys.getrefcount(a)) # 输出:2(一次是 a,另一次是 getrefcount 的参数)
b = a
print(sys.getrefcount(a)) # 输出:3(a 和 b 都指向同一个对象)
del b
print(sys.getrefcount(a)) # 输出:2(b 被删除后,引用计数减少)
# 循环引用示例
class Node:
def __init__(self, name):
self.name = name
self.next = None
def set_next(self, next_node):
self.next = next_node
node1 = Node("Node 1")
node2 = Node("Node 2")
node1.set_next(node2)
node2.set_next(node1)
# 此时 node1 和 node2 形成了循环引用
del node1
del node2
# 即使删除了 node1 和 node2,它们的内存可能仍未释放
# 因为 Python 的垃圾回收器会定期清理循环引用
- 总结:
- 使用
sys.getrefcount()可以查看对象的引用计数。 - 循环引用会导致对象无法被引用计数机制清理,但 Python 的垃圾回收器可以通过标记清除和分代回收机制解决这个问题。
- 使用
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)