一、 Python基础语法

1. 可变与不可变对象

  • 题目:Python中什么是可变对象和不可变对象?请分别举例。
  • 考察点:对内存模型的理解。
  • 答案
    • 不可变对象:内存内容不可改变,修改变量会指向新的内存地址。如:int, float, str, tuple
    • 可变对象:内存内容可以改变,修改变量不会改变内存地址。如:list, dict, set

2. 列表与元组的区别

  • 题目listtuple 的区别是什么?分别用在什么场景?
  • 考察点:基本数据结构的特性。
  • 答案:列表可变(可增删改),元组不可变。元组通常用于存储异构数据(如数据库一条记录),且由于不可变性,可作为字典的键;列表用于存储同质数据,需要频繁增删改的场景。

**3. 参数传递

  • 题目:下面代码的输出是什么?为什么?

    def func(a, b=[]):
        b.append(a)
        return b
    
    print(func(1))
    print(func(2))
    
  • 考察点:默认参数的陷阱。

  • 答案:输出 [1][1, 2]默认参数 b=[] 只在函数定义时被初始化一次。后续调用如果不传 b,使用的都是同一个列表对象。

4. *args**kwargs 的作用

  • 题目:在函数定义中,*args**kwargs 是什么意思?
  • 考察点:不定长参数的使用。
  • 答案
    • *args:用于接收多余的位置参数,打包成元组(tuple)。
    • **kwargs:用于接收多余的关键字参数,打包成字典(dict)。

二、 数据结构与算法

**5. 列表去重

  • 题目:给定一个列表 lst = [1, 2, 2, 3, 4, 4, 5],如何快速去重并保持原来的顺序?
  • 考察点:集合的特性和排序。
  • 答案
    # 方法一 (Python 3.7+ 字典保持插入顺序)
    list(dict.fromkeys(lst))
    # 方法二 (传统方法)
    seen = set()
    result = [x for x in lst if not (x in seen or seen.add(x))]
    

**6. 字典排序

  • 题目:有一个字典 {'A': 3, 'B': 1, 'C': 2},如何根据值(value)进行升序排序?
  • 考察点:高阶函数 sorted 和 lambda 表达式的使用。
  • 答案
    sorted(dict.items(), key=lambda item: item[1])
    # 结果: [('B', 1), ('C', 2), ('A', 3)]
    

三、 高级特性

**7. 装饰器:装饰器本质上是一个函数,它接受一个函数作为参数,返回一个新的函数。

  • 题目:写一个简单的装饰器,用于计算函数的执行时间。
  • 考察点:闭包和装饰器语法。
  • 答案
    import time
    def timer(func):
        def wrapper(*args, **kwargs):
            start = time.time()
            result = func(*args, **kwargs)
            print(f"耗时: {time.time() - start}秒")
            return result
        return wrapper
    
    @timer
    def test():
        time.sleep(1)
    

**8. 生成器 vs 迭代器

迭代器:
	惰性计算:迭代器一次只生成一个元素,不一次性生成所有元素
	只能前进:迭代器只能向前移动,不能后退
	节省内存
	包括_iter_ 和_next_ 方法
  • 题目:解释什么是生成器?它和迭代器有什么关系?yield 关键字的作用是什么?
  • 考察点:惰性求值、内存优化。
  • 答案:生成器是迭代器的一种。函数中使用了 yield 即成为生成器。它允许函数在每次 yield 时暂停并记住状态,下次从该位置继续执行,用于节省内存(处理大数据流)和表示无限序列。

**9. 深拷贝与浅拷贝

  • 题目:在Python中,import copy; copy.copy(x)copy.deepcopy(x) 有什么区别?
  • 考察点:对象引用的理解。
  • 答案
    • 浅拷贝:拷贝父对象,但不会拷贝父对象内部的子对象,新旧对象共享子对象。
    • 深拷贝:完全拷贝父对象及其子对象,新旧对象完全独立。
      你想聚焦在Python中理解深拷贝和浅拷贝的区别,我会用Python的代码和新手能看懂的逻辑,把这个知识点讲透——核心还是「是否复制嵌套的引用类型」。

一、Python中浅拷贝(Shallow Copy)

浅拷贝只会复制对象的「表层结构」,对于对象内部的嵌套元素(比如列表里的列表、字典里的列表),依然共享同一个内存地址,修改嵌套元素会影响原对象。

1. 浅拷贝的常见实现方式
  • 列表:list.copy()、切片 arr[:]
  • 字典:dict.copy()
  • 通用:copy 模块的 copy.copy()
2. 代码示例(最典型的嵌套列表)
import copy

# 原对象:外层列表 + 嵌套列表(引用类型)
original = [1, 2, [3, 4]]

# 方式1:列表自带的浅拷贝
shallow1 = original.copy()
# 方式2:切片浅拷贝
shallow2 = original[:]
# 方式3:copy模块的浅拷贝
shallow3 = copy.copy(original)

# 测试1:修改「表层基础类型」→ 原对象不受影响
shallow1[0] = 100
print("原对象:", original)       # [1, 2, [3, 4]]
print("浅拷贝1:", shallow1)     # [100, 2, [3, 4]]

# 测试2:修改「嵌套的引用类型」→ 原对象跟着变(核心坑点)
shallow2[2].append(5)
print("原对象:", original)       # [1, 2, [3, 4, 5]]
print("浅拷贝2:", shallow2)     # [1, 2, [3, 4, 5]]

二、Python中深拷贝(Deep Copy)

深拷贝会递归复制对象的「所有层级」,包括嵌套的引用类型,拷贝后的对象和原对象完全独立,修改任何层级的元素都不会影响原对象。

1. 深拷贝的唯一核心方式

必须用 copy 模块的 copy.deepcopy()(Python没有内置的深拷贝语法糖)。

2. 代码示例
import copy

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

# 深拷贝:递归复制所有层级
deep = copy.deepcopy(original)

# 测试:修改嵌套元素 → 原对象完全不受影响
deep[2].append(5)
print("原对象:", original)       # [1, 2, [3, 4]]
print("深拷贝:", deep)           # [1, 2, [3, 4, 5]]

三、Python特有的避坑点(新手必看)

  1. 只有「可变对象」才需要区分深浅拷贝
    • 不可变对象(int、str、tuple):因为无法修改内部值,拷贝本质都是引用传递,深浅拷贝无差异。
    a = (1, 2)  # 元组是不可变对象
    b = copy.copy(a)
    c = copy.deepcopy(a)
    print(a is b)  # True → 同一个对象
    print(a is c)  # True → 同一个对象
    
  2. 深拷贝的性能成本
    深拷贝需要递归遍历所有层级,对于嵌套极深、数据量大的对象(比如多层嵌套的大字典),速度会比浅拷贝慢很多,非必要不滥用。
  3. 特殊对象的深拷贝限制
    对于文件句柄、网络连接、类实例的方法等「不可序列化对象」,deepcopy 可能无法完全拷贝,或拷贝后失效,需额外处理。

总结

  1. 浅拷贝copy.copy()/列表copy/切片):只复制表层,嵌套引用类型共享,修改嵌套元素会影响原对象,速度快、占用内存少。
  2. 深拷贝copy.deepcopy()):递归复制所有层级,完全独立,修改任何元素都不影响原对象,速度慢、占用内存多。
  3. Python关键:只有列表、字典等可变对象的嵌套结构,才需要区分深浅拷贝;不可变对象(int/str/tuple)无差异。

四、 并发编程

**10. GIL是什么?

  • 题目:解释Python中的GIL(全局解释器锁)。它对多线程程序有什么影响?
  • 考察点:对Python核心机制的理解。
  • 答案:GIL是CPython解释器中的一个互斥锁,它确保任何时候只有一个线程执行Python字节码。这使得CPU密集型的多线程程序无法真正利用多核优势;但对于I/O密集型程序,由于线程经常等待I/O(此时会释放GIL),多线程依然能显著提升效率。

五、 编程实践

**11. 合并两个字典

  • 题目:在Python 3.5+ 中,如何简洁地合并两个字典 dict1dict2
  • 考察点:Python版本特性。
  • 答案
    merged = {**dict1, **dict2}
    # Python 3.9+ 还可以使用: dict1 | dict2
    

**12. 反转字符串

  • 题目:给定一个字符串 “hello world”,请将其反转。
  • 考察点:切片技巧。
  • 答案
    s = "hello world"
    reversed_s = s[::-1]  # 结果: "dlrow olleh"
    

**13. 异常处理

  • 题目try-except-else-finally 中,elsefinally 分别在什么情况下执行?
  • 考察点:异常处理流程。
  • 答案
    • else:当try块中没有抛出异常时执行。
    • finally:无论是否发生异常,都会执行(通常用于清理资源,如关闭文件)。

**14. 上下文管理器

  • 题目:如何使用 with 语句打开文件?相比于直接 open()close() 有什么好处?
  • 考察点:资源管理。
  • 答案
    with open('file.txt', 'r') as f:
        content = f.read()
    
    好处:即使文件操作过程中发生异常,with 语句也能确保文件被正确关闭,避免资源泄露。

六、 面向对象

**15. __init____new__ 的区别

  • 题目:解释 __new____init__ 在类实例化过程中的作用。
  • 考察点:对象创建与初始化的底层机制。
  • 答案
    • __new__:是一个静态方法,负责创建实例(分配内存),返回实例对象。它先执行。
    • __init__:是一个实例方法,负责初始化实例(赋值属性),修改__new__创建的对象。它后执行。
      你想搞清楚Python中__init____new__的核心区别,这是理解Python类实例化过程的关键——简单说,__new__负责创建对象(造空壳),__init__负责初始化对象(填内容),这是新手最容易混淆的两个魔术方法。

一、核心区别(先记结论,再看代码)

特性 __new__(cls, *args, **kwargs) __init__(self, *args, **kwargs)
作用 创建类的实例(返回一个空对象),是「构造方法」 初始化实例的属性(给空对象赋值),是「初始化方法」
第一个参数 cls(类本身) self__new__创建好的实例)
返回值 必须返回一个实例(通常是super().__new__(cls) 无返回值(默认None,写return会报错)
调用时机 实例创建时最先调用(比__init__早) __new__返回实例后才调用(给实例赋值)
适用场景 单例模式、修改不可变对象(str/tuple/int)的创建逻辑 给实例初始化属性(99%的场景只用这个)

二、代码示例(新手能直接跑)

1. 基础示例:看调用顺序和参数
class Person:
    # __new__:创建实例,第一个参数是类本身
    def __new__(cls, name, age):
        print(f"__new__被调用:创建{cls}类的实例")
        # 调用父类的__new__创建空实例(必须返回,否则__init__不会执行)
        instance = super().__new__(cls)
        return instance  # 返回创建好的空实例
    
    # __init__:初始化实例,第一个参数是__new__返回的实例
    def __init__(self, name, age):
        print(f"__init__被调用:初始化{self}实例的属性")
        self.name = name  # 给实例赋值
        self.age = age

# 创建实例:先执行__new__,再执行__init__
p = Person("张三", 18)
print(p.name, p.age)  # 张三 18

# 输出结果:
# __new__被调用:创建<class '__main__.Person'>类的实例
# __init__被调用:初始化<__main__.Person object at 0x10xxx>实例的属性
# 张三 18
2. 关键场景1:__new__不返回实例,__init__不会执行
class Test:
    def __new__(cls):
        print("__new__执行,但不返回实例")
        # 故意不返回实例
        return None
    
    def __init__(self):
        print("__init__执行")  # 永远不会打印

t = Test()  # 只输出:__new__执行,但不返回实例
print(t)    # None(因为__new__返回None)
3. 关键场景2:单例模式(__new__的经典用法)

单例模式要求一个类只能创建一个实例,核心就是重写__new__控制实例创建:

class Singleton:
    # 用类属性保存唯一实例
    _instance = None

    def __new__(cls):
        # 如果实例不存在,才创建;否则返回已有的实例
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

# 测试:两次创建的是同一个实例
s1 = Singleton()
s2 = Singleton()
print(s1 is s2)  # True(地址相同,是同一个对象)
4. 关键场景3:不可变对象的修改(__init__做不到)

str、tuple是不可变对象,初始化后无法修改,要定制创建逻辑只能用__new__

class CustomStr(str):
    # 定制字符串:创建时自动转大写
    def __new__(cls, value):
        # 先处理值,再创建实例
        new_value = value.upper()
        return super().__new__(cls, new_value)

# 测试:创建时自动转大写
s = CustomStr("hello")
print(s)  # HELLO

三、新手必记的核心要点

  1. 99%的场景只用__init__:日常写类,只需要重写__init__初始化属性,__new__由Python默认处理,不用管。
  2. __new__是类方法,__init__是实例方法__new__接收cls(类),__init__接收self(实例)。
  3. __new__决定是否创建实例,__init__只负责初始化:如果__new__返回None__init__永远不会执行。
  4. 单例模式是__new__最常用的场景:这是面试高频考点,一定要掌握上面的单例代码。

总结

  1. __new__是「构造方法」,负责创建实例(返回空对象),参数是cls,适用于单例、定制不可变对象;
  2. __init__是「初始化方法」,负责填充实例属性(无返回值),参数是self,日常开发99%的场景只用它;
  3. 调用顺序:先执行__new__创建实例,返回实例后才执行__init__初始化。

七、 陷阱与细节

**16. ==is 的区别

  • 题目a == ba is b 有什么区别?
  • 考察点:值比较与引用比较。
  • 答案
    • ==:比较两个对象的是否相等。
    • is:比较两个对象的id(内存地址)是否相同,即是否是同一个对象。

**17. 负索引与切片

  • 题目:对于一个列表 a = [0, 1, 2, 3, 4, 5]a[-1]a[-2:]a[::-1] 分别输出什么?
  • 考察点:Python灵活的索引机制。
  • 答案
    • a[-1] -> 5
    • a[-2:] -> [4, 5]
    • a[::-1] -> [5, 4, 3, 2, 1, 0]

**18. 类变量与实例变量

  • 题目:写出下面代码的输出:

    class Person:
        tags = ["person"]  # 类变量
    
    p1 = Person()
    p2 = Person()
    p1.tags.append("student")
    print(p2.tags)
    
  • 考察点:类属性与实例属性的交互。

  • 答案:输出 ['person', 'student']。因为 tags 是类变量,所有实例共享同一个列表。通过 p1.tags 修改会影响 p2.tags。如果赋值 p1.tags = ["new"],则 p1 会新建一个实例属性,不再影响类变量。

Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐