当前位置: 首页 > article >正文

Python常见面试题的详解13

1. 以下X是什么类型

X= (i for i in range(10))

  • 要点
  1. 在 Python 中,变量的类型取决于其赋值的对象。
  2. 下面代码中的 (i for i in range(10)) 是一个生成器表达式。生成器表达式是一种简洁的创建生成器的方式,它类似于列表推导式,但使用圆括号而非方括号。

  3. 生成器是一种特殊的迭代器,它不会一次性生成所有的值,而是在需要时逐个生成,这在处理大量数据时可以节省内存。

python

X = (i for i in range(10))
print(type(X))
  • 示例

生成器的优势在于其惰性求值的特性。例如,当需要处理一个非常大的数据集时,如果使用列表存储所有数据,可能会导致内存溢出。而使用生成器,可以在每次迭代时才计算和获取一个值,大大减少了内存的使用。

python

# 使用列表存储 1 到 1000000 的整数
import sys
list_data = [i for i in range(1000000)]
print(f"列表占用的内存大小: {sys.getsizeof(list_data)} 字节")

# 使用生成器生成 1 到 1000000 的整数
generator_data = (i for i in range(1000000))
print(f"生成器占用的内存大小: {sys.getsizeof(generator_data)} 字节")

2. 用一行代码将 1 - N 的整数列表以 3 为单位分组

  • 要点

要实现将 1 到 N 的整数列表以 3 为单位进行分组,可利用 Python 的列表推导式和 range 函数来完成。

  1. 列表推导式 [list(range(i, min(i + 3, N + 1))) for i in range(1, N + 1, 3)] 是核心实现。

  2. range(1, N + 1, 3) 用于生成从 1 开始,步长为 3 的整数序列,这些整数作为每个分组的起始值。

  3. range(i, min(i + 3, N + 1)) 生成每个分组的具体整数序列,使用 min 函数确保最后一个分组不会超出 N 的范围。

python

N = 15
result = [list(range(i, min(i + 3, N + 1))) for i in range(1, N + 1, 3)]
print(result)
  • 示例

可以将此功能封装成一个函数,以便在不同场景下重复使用:

python

def group_integers(N, group_size=3):
    return [list(range(i, min(i + group_size, N + 1))) for i in range(1, N + 1, group_size)]

N = 20
print(group_integers(N))

3. 说明yield 的作用和用法

  • 要点
  1. yield 是 Python 中用于创建生成器函数的关键字。
  2. 包含 yield 语句的函数 count_up_to 被称为生成器函数。当调用生成器函数时,不会立即执行函数体,而是返回一个生成器对象。

  3. 每次调用生成器对象的 __next__() 方法(在 for 循环中会自动调用)时,函数会执行到 yield 语句处,返回 yield 后面的值,并暂停执行。下次再调用时,从暂停的位置继续执行。

python

def count_up_to(n):
    num = 1
    while num <= n:
        yield num
        num += 1

gen = count_up_to(5)
for num in gen:
    print(num)
  • 示例

生成器还可以与 send() 方法结合使用,实现双向数据传递。

python

def generator():
    value = yield
    while True:
        value = yield value * 2

gen = generator()
next(gen)  # 启动生成器
result = gen.send(5)
print(result)

4. 什么是魔法方法

  • 要点

魔法方法是 Python 中以双下划线开头和结尾的方法,它们在特定情况下会被 Python 解释器自动调用,用于实现类的特殊行为。

  1. __init__ 是初始化方法,在创建对象时自动调用,用于初始化对象的属性。

  2. __str__ 方法返回对象的字符串表示,当使用 print() 函数或 str() 函数时会调用该方法。

  3. __len__ 方法返回对象的长度,当使用 len() 函数时会调用该方法。

python

class MyClass:
    def __init__(self, value):
        self.value = value

    def __str__(self):
        return f"MyClass with value: {self.value}"

    def __len__(self):
        return len(str(self.value))

obj = MyClass(12345)
print(obj)
print(len(obj))
  • 示例

除了上述常见的魔法方法,还有许多其他有用的魔法方法,如 __add__ 用于实现对象的加法运算,__eq__ 用于比较对象是否相等,以下代码实现自定义加法运算。

python

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)

    def __str__(self):
        return f"Vector({self.x}, {self.y})"

v1 = Vector(1, 2)
v2 = Vector(3, 4)
v3 = v1 + v2
print(v3)

5. 面向对象中如何实现只读属性

  • 要点

在面向对象编程中,有时需要将某些属性设置为只读,以防止外部代码意外修改这些属性的值。

  1. 使用 @property 装饰器将方法转换为属性,使得可以像访问普通属性一样访问该方法的返回值。

  2. 由于没有定义对应的 setter 方法,这些属性成为只读属性,外部代码无法直接修改其值。

python

class Circle:
    def __init__(self, radius):
        self._radius = radius

    @property
    def radius(self):
        return self._radius

    @property
    def area(self):
        import math
        return math.pi * self._radius ** 2

circle = Circle(5)
print(circle.radius)
print(circle.area)
# 以下代码会报错,因为 radius 是只读属性
# circle.radius = 10
  • 示例

如果需要在设置属性值时进行一些验证或其他操作,可以定义 setter 方法。

python

class Circle:
    def __init__(self, radius):
        self._radius = radius

    @property
    def radius(self):
        return self._radius

    @radius.setter
    def radius(self, value):
        if value < 0:
            raise ValueError("Radius cannot be negative")
        self._radius = value

    @property
    def area(self):
        import math
        return math.pi * self._radius ** 2

circle = Circle(5)
circle.radius = 3  # 可以正常设置
# circle.radius = -1  # 会抛出 ValueError 异常

6. 如何理解面向对象

  • 要点

面向对象编程是一种重要的编程范式,理解其核心概念对于编写高质量的代码非常关键。

  1. 类(Class):是对象的蓝图或模板,定义了对象的属性和方法。例如 Animal 类定义了动物的基本属性 name 和方法 speak

  2. 对象(Object):是类的实例,通过类创建出来。dogcat 分别是 Dog 类和 Cat 类的对象。

  3. 继承(Inheritance):允许一个类(子类)继承另一个类(父类)的属性和方法。Dog 类和 Cat 类继承自 Animal 类,继承了 name 属性和 speak 方法。

  4. 多态(Polymorphism):不同的对象对同一消息(方法调用)可以做出不同的响应。dog.speak()cat.speak() 调用相同的方法名,但返回不同的结果。

python

# 定义一个基类 Animal
class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        pass

# 定义一个子类 Dog,继承自 Animal
class Dog(Animal):
    def speak(self):
        return f"{self.name} says Woof!"

# 定义一个子类 Cat,继承自 Animal
class Cat(Animal):
    def speak(self):
        return f"{self.name} says Meow!"

dog = Dog("Buddy")
cat = Cat("Whiskers")

print(dog.speak())
print(cat.speak())
  • 示例

面向对象编程还有一个重要概念是封装,即隐藏对象的内部实现细节,只对外提供必要的接口。

python

class BankAccount:
    def __init__(self, balance=0):
        self.__balance = balance  # 使用双下划线将属性封装

    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount
            return True
        return False

    def withdraw(self, amount):
        if amount > 0 and amount <= self.__balance:
            self.__balance -= amount
            return True
        return False

    def get_balance(self):
        return self.__balance

account = BankAccount(100)
account.deposit(50)
account.withdraw(20)
print(account.get_balance())

7. 如何用正则匹配出 IP

  • 要点

在处理文本数据时,有时需要从文本中提取 IP 地址,可以使用正则表达式来实现。

  1. 正则表达式 \b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b 用于匹配合法的 IP 地址。

  2. \b 是单词边界,确保匹配的是完整的 IP 地址。

  3. (?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?) 用于匹配 0 到 255 之间的数字。

python

import re

text = "The IP address is 192.168.1.1 and 10.0.0.1"
pattern = r'\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b'
ips = re.findall(pattern, text)
print(ips)
  • 示例

可以将正则匹配 IP 地址的功能封装成一个函数,以便在不同场景下使用。

python

import re

def find_ips(text):
    pattern = r'\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b'
    return re.findall(pattern, text)

text = "Some text with IPs like 172.16.0.1 and 192.168.0.100"
print(find_ips(text))

8. i = “abbbbcccc”,用正则匹配为 abcccc,不管有多少 b,只出现一次

  • 要点
  1. re.sub() 函数用于替换字符串中匹配正则表达式的部分。

  2. 正则表达式 ab+ 表示匹配一个 a 后面跟着一个或多个 b

  3. 将匹配到的部分替换为 ab,从而实现将多个 b 替换为一个 b 的目的。

python

import re

i = "abbbbcccc"
result = re.sub(r'ab+', 'ab', i)
print(result)
  • 示例

如果需要处理多个字符串,可以将该功能封装成一个函数。

python

import re

def replace_multiple_b(strings):
    return [re.sub(r'ab+', 'ab', s) for s in strings]

strings = ["abbbbcccc", "abbbddd", "abcccc"]
print(replace_multiple_b(strings))

9. 如何实现字符串查找和替换

  • 要点

在 Python 中,有多种方法可以实现字符串的查找和替换操作,包括使用字符串方法和正则表达式。

  1. 字符串方法 find() 用于查找子字符串的起始索引,如果未找到则返回 -1;replace() 用于替换字符串中的指定子字符串。

  2. 正则表达式的 search() 方法用于在字符串中查找第一个匹配的位置;sub() 方法用于替换字符串中所有匹配的部分。

python

# 使用字符串方法进行查找和替换
s = "hello world"
index = s.find("world")
print(index)
new_s = s.replace("world", "python")
print(new_s)

# 使用正则表达式进行查找和替换
import re
text = "The quick brown fox jumps over the lazy dog"
match = re.search(r'fox', text)
if match:
    print(match.start())
new_text = re.sub(r'fox', 'cat', text)
print(new_text)
  • 示例

可以根据具体需求选择合适的方法。如果只是简单的查找和替换,字符串方法通常更简单高效;如果需要更复杂的匹配规则,如模糊匹配、大小写不敏感匹配等,则使用正则表达式更合适。以下可以实现大小写不敏感的正则替换。

python

import re

text = "Hello World, hello Python"
new_text = re.sub(r'hello', 'Hi', text, flags=re.IGNORECASE)
print(new_text)

10. 写出开头匹配字母和下划线,末尾是数字的正则表达式

  • 要点
  1. ^ 表示字符串的开头,确保匹配从字符串的起始位置开始。

  2. [a-zA-Z_] 匹配任意字母或下划线。

  3. .* 匹配任意数量的任意字符。

  4. [0-9] 匹配任意数字。

  5. $ 表示字符串的结尾,确保匹配到字符串的末尾。

python

import re

pattern = r'^[a-zA-Z_].*[0-9]$'
text = "abc123"
if re.match(pattern, text):
    print("匹配成功")
else:
    print("匹配失败")
  • 示例

可以将该正则表达式应用到批量字符串的匹配中。

python

import re

pattern = r'^[a-zA-Z_].*[0-9]$'
strings = ["abc123", "123abc", "_test456"]
for s in strings:
    if re.match(pattern, s):
        print(f"{s} 匹配成功")
    else:
        print(f"{s} 匹配失败")

友情提示:本文已经整理成文档,可以到如下链接免积分下载阅读

https://download.csdn.net/download/ylfhpy/90402553


http://www.kler.cn/a/554096.html

相关文章:

  • 解决 Nginx 代理后 HTTP 头部丢失的问题:以 access_token 为例
  • 【ISO 14229-1:2023 UDS诊断(会话控制0x10服务)测试用例CAPL代码全解析⑤】
  • rust学习五、认识所有权
  • unity学习47:寻路和导航,unity2022后版本如何使用 Navmesh 和 bake
  • 图解MySQL【日志】——Buffer Pool
  • Java Applet 学习笔记(详细版)
  • Redis 过期键(expires)机制详解
  • Linux 内存管理与文件页缓冲区
  • 【二分搜索 C/C++】洛谷 P1873 EKO / 砍树
  • Redis7——基础篇(二)
  • 前端504错误分析
  • leetcode-414.第三大的数
  • 影视大数据分析新范式:亮数据动态代理驱动的实时数据采集方案
  • 文心快码智能体不断发展,真正与AI协同工作
  • 数据治理中 大数据处理一般都遵循哪些原则
  • BDF(MD)
  • VSCode使用Cline插件集成OpenAI教程
  • C#中的MarshalByRefObject
  • Deepseek整合SpringAI
  • 接入DeepSeek后,智慧园区安全调度系统的全面提升