Python常见面试题的详解13
1. 以下X是什么类型
X= (i for i in range(10))
- 要点
- 在 Python 中,变量的类型取决于其赋值的对象。
-
下面代码中的
(i for i in range(10))
是一个生成器表达式。生成器表达式是一种简洁的创建生成器的方式,它类似于列表推导式,但使用圆括号而非方括号。 -
生成器是一种特殊的迭代器,它不会一次性生成所有的值,而是在需要时逐个生成,这在处理大量数据时可以节省内存。
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
函数来完成。
-
列表推导式
[list(range(i, min(i + 3, N + 1))) for i in range(1, N + 1, 3)]
是核心实现。 -
range(1, N + 1, 3)
用于生成从 1 开始,步长为 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
的作用和用法
- 要点
yield
是 Python 中用于创建生成器函数的关键字。-
包含
yield
语句的函数count_up_to
被称为生成器函数。当调用生成器函数时,不会立即执行函数体,而是返回一个生成器对象。 -
每次调用生成器对象的
__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 解释器自动调用,用于实现类的特殊行为。
-
__init__
是初始化方法,在创建对象时自动调用,用于初始化对象的属性。 -
__str__
方法返回对象的字符串表示,当使用print()
函数或str()
函数时会调用该方法。 -
__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. 面向对象中如何实现只读属性
- 要点
在面向对象编程中,有时需要将某些属性设置为只读,以防止外部代码意外修改这些属性的值。
-
使用
@property
装饰器将方法转换为属性,使得可以像访问普通属性一样访问该方法的返回值。 -
由于没有定义对应的
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. 如何理解面向对象
- 要点
面向对象编程是一种重要的编程范式,理解其核心概念对于编写高质量的代码非常关键。
-
类(Class):是对象的蓝图或模板,定义了对象的属性和方法。例如
Animal
类定义了动物的基本属性name
和方法speak
。 -
对象(Object):是类的实例,通过类创建出来。
dog
和cat
分别是Dog
类和Cat
类的对象。 -
继承(Inheritance):允许一个类(子类)继承另一个类(父类)的属性和方法。
Dog
类和Cat
类继承自Animal
类,继承了name
属性和speak
方法。 -
多态(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 地址,可以使用正则表达式来实现。
-
正则表达式
\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 地址。 -
\b
是单词边界,确保匹配的是完整的 IP 地址。 -
(?: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
,只出现一次
- 要点
-
re.sub()
函数用于替换字符串中匹配正则表达式的部分。 -
正则表达式
ab+
表示匹配一个a
后面跟着一个或多个b
。 -
将匹配到的部分替换为
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 中,有多种方法可以实现字符串的查找和替换操作,包括使用字符串方法和正则表达式。
-
字符串方法
find()
用于查找子字符串的起始索引,如果未找到则返回 -1;replace()
用于替换字符串中的指定子字符串。 -
正则表达式的
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. 写出开头匹配字母和下划线,末尾是数字的正则表达式
- 要点
-
^
表示字符串的开头,确保匹配从字符串的起始位置开始。 -
[a-zA-Z_]
匹配任意字母或下划线。 -
.*
匹配任意数量的任意字符。 -
[0-9]
匹配任意数字。 -
$
表示字符串的结尾,确保匹配到字符串的末尾。
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