Python 常见面试题

1. Python 直接赋值、浅拷贝和深度拷贝解析

  • 直接赋值:其实就是对象的引用(别名)。

  • 浅拷贝(copy):拷贝父对象,不会拷贝对象的内部的子对象。

  • 深拷贝(deepcopy): copy 模块的 deepcopy 方法,完全拷贝了父对象及其子对象。

  • 不可变对象类型(整数、浮点数、字符串、元组),没有被拷贝的说法,即便是用深拷贝,查看id的话也是一样的,如果对其重新赋值,也只是新创建一个对象,替换掉旧的而已


2. 可迭代对象、迭代器和生成器

2.1 可迭代对象

定义

  • 一个可迭代对象是实现了 __iter__() 方法。__iter__() 方法返回一个迭代器。
  • 常见的可迭代对象包括列表、元组、字典、集合和字符串等。

特点

  • 可迭代对象可以被用在 for 循环中,通过逐一访问其元素。
  • 可以使用 iter() 函数将可迭代对象转换为迭代器。

注意:能用 for 循环使用的对象,不一定是可迭代对象

from collections import Iterable, Iterator, Generator


class IterObj:

    def __init__(self):
        self.a = [3, 5, 7, 11, 13, 17, 19]

    def __getitem__(self, i):
        return self.a[i]


it = IterObj()
print(isinstance(it, Iterable))  # False
print(isinstance(it, Iterator))  # False
print(isinstance(it, Generator))  # False
print(hasattr(it, "__iter__"))  # False
print(iter(it))  # <iterator object at 0x10b231278>
for i in it:
    print(i)  # 将打印出3、5、7、11、13、17、19

2.2 迭代器

定义

  • 迭代器是实现了迭代器协议的对象,具体来说,就是实现了 __iter__()__next__() 方法的对象。
  • __iter__() 方法返回迭代器对象本身,__next__() 方法返回下一个元素,如果没有元素可返回,则抛出 StopIteration 异常。

特点

  • 迭代器用于逐个访问可迭代对象的元素,通常只遍历一次。
  • 可以使用 next() 函数获取迭代器的下一个元素。

2.3. 生成器

定义:

  • 生成器是使用 yield 关键字的函数,返回一个生成器对象,该对象是 Python 的迭代器。

特性:

  • 生成器是简化迭代器书写的语法糖。
  • 每次执行到 yield 时,生成器会返回一个值,并记住函数执行的状态(局部变量、指令指针等),在下次迭代时从暂停处继续执行。
  • 生成器非常适合处理大量数据或无限序列,因为它们在每次迭代时才生成数据,不会一次性将所有数据加载到内存中。

3. 正则表达式的match方法和search方法有什么区别?

3.1 re.match 方法

  • 功能: re.match 尝试从字符串的起始位置进行匹配。
  • 返回值: 如果匹配成功,返回一个 Match 对象;否则返回 None
  • 使用场景: 当你希望检查字符串是否以某个模式开头时,可以使用 re.match

3.2 re.search 方法

  • 功能: re.search 扫描整个字符串,并返回第一个成功匹配的位置。
  • 返回值: 如果匹配成功,返回一个 Match 对象;否则返回 None
  • 使用场景: 当你希望在整个字符串中搜索某个模式时,可以使用 re.search

4. 类变量

在 Python 中,类变量是类级别的属性,它们在类的所有实例之间共享。类变量在类定义体中定义,而实例变量在 __init__ 方法中定义。类变量在所有实例中共享相同的值,而实例变量是每个实例独有的。

4.1 类变量和实例变量的区别

  1. 类变量:在类定义体中定义,所有实例共享相同的值。
  2. 实例变量:在 __init__ 方法中定义,每个实例独有。
class MyClass:
    # 类变量
    class_variable = "I am a class variable"

    def __init__(self, instance_variable):
        # 实例变量
        self.instance_variable = instance_variable

# 创建类的实例
obj1 = MyClass("I am instance variable 1")
obj2 = MyClass("I am instance variable 2")

# 访问类变量
print(MyClass.class_variable)  # 输出: I am a class variable
print(obj1.class_variable)     # 输出: I am a class variable
print(obj2.class_variable)     # 输出: I am a class variable

# 访问实例变量
print(obj1.instance_variable)  # 输出: I am instance variable 1
print(obj2.instance_variable)  # 输出: I am instance variable 2

# 修改类变量
MyClass.class_variable = "New value"
print(obj1.class_variable)     # 输出: New value
print(obj2.class_variable)     # 输出: New value

# 修改实例变量
obj1.instance_variable = "Changed instance variable 1"
print(obj1.instance_variable)  # 输出: Changed instance variable 1
print(obj2.instance_variable)  # 输出: I am instance variable 2

4.2 类变量的继承

  • 子类会继承父类的类变量。
  • 当子类修改类变量时,这个修改只会影响子类本身,不会影响父类或其他子类。
  • 修改父类的类变量会影响那些没有修改过该类变量的子类。
class Parent:
    class_variable = "Parent variable"

class Child1(Parent):
    pass

class Child2(Parent):
    pass

print(Parent.class_variable)  # 输出: Parent variable
print(Child1.class_variable)  # 输出: Parent variable
print(Child2.class_variable)  # 输出: Parent variable

# 修改 Child1 的类变量
Child1.class_variable = "Child1 variable"
print(Parent.class_variable)  # 输出: Parent variable
print(Child1.class_variable)  # 输出: Child1 variable
print(Child2.class_variable)  # 输出: Parent variable

# 修改 Parent 的类变量
Parent.class_variable = "Modified Parent variable"
print(Parent.class_variable)  # 输出: Modified Parent variable
print(Child1.class_variable)  # 输出: Child1 variable
print(Child2.class_variable)  # 输出: Modified Parent variable

5. __init__和__new__方法有什么区别?

5.1 __new__ 方法

  • 作用__new__ 是一个静态方法,用于创建并返回一个新的实例。它在对象实例化的过程中第一个被调用。
  • 参数__new__ 方法至少接受一个参数 cls,表示要实例化的类。
  • 返回值:必须返回一个类的实例(通常是通过 super().__new__(cls) 调用来创建实例)。
  • 用途:通常在继承自不可变类型(如 intstrtuple)的类中使用,或在需要控制实例创建过程时使用。

5.2 __init__ 方法

  • 作用__init__ 是一个实例方法,用于初始化实例的属性。它在对象创建后被调用,通常用于设置对象的初始状态。
  • 参数__init__ 方法至少接受一个参数 self,表示要初始化的实例对象。
  • 返回值:不返回值(返回 None)。
  • 用途:用于为新创建的对象设置初始状态或属性值。

5.3 调用顺序

  1. __new__ 被调用以创建一个新实例。
  2. 新实例作为参数传递给 __init__,并进行初始化。

5.4 总结

  • __new__ 用于控制对象的创建过程,是一个类方法,返回一个新的实例。
  • __init__ 用于初始化对象的属性,是一个实例方法,不返回值。
  • __new____init__ 之前被调用。
  • 对于不可变类型的子类,通常需要重写 __new__ 方法,而对于一般的类,只需要重写 __init__ 方法来初始化对象。

6. 闭包

闭包必须满足以下三个条件:

  1. 必须有一个内嵌函数。
  2. 内嵌函数引用了外部函数中的变量。
  3. 外部函数返回内嵌函数。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值