面试专栏22
01 什么是断言(assert)?应用场景? 02 解决哈希冲突的算法有哪几种?分别有什么特点? 03 介绍一下try except的用法和作用? 04 常用字符串格式化有哪几种 05 用尽量简洁的方法将二维数组合并成一维数组 06 python的可变类型和不可变类型的区别 07 如何实现['1','2','3']变成[1,2,3] 08 什么是反射,以及应用场景 09 对列表[3,1,-4,-2]按照绝对值排序 10 super的作用
01 什么是断言(assert)?应用场景?
断言(assert)是编程中的一个概念,用于确保程序中某个特定的条件一定为真。如果该条件为假,程序会抛出一个错误或异常。断言主要用于在开发和测试阶段捕获预期之外的情况,确保代码的逻辑正确性。 断言的工作机制是这样的:当断言条件为真时,程序继续执行;当断言条件为假时,程序会抛出一个断言错误或异常,并终止执行。
应用场景
:
开发中的调试
:当开发者认为某个条件应该总是为真时,可以使用断言来检查。如果在后续开发中该条件被违反,断言会立即发出警告,帮助开发者快速定位问题。
单元测试
:在编写单元测试时,断言可以用来检查代码的输出是否符合预期。
验证前提条件
:例如,某个函数可能要求其输入参数满足特定条件。使用断言可以确保这些条件得到满足。
避免明显的逻辑错误
:在某些情况下,如果代码的某部分到达了不应该到达的地方,可以使用断言进行提示。
文档
:断言可以作为代码文档的一部分,明确说明函数或方法的预期行为和约束。
02 解决哈希冲突的算法有哪几种?分别有什么特点?
哈希冲突(Hash Collision)是指当两个或多个不同的输入数据在经过哈希函数处理后产生相同的输出哈希值的情况。解决哈希冲突是哈希表设计中的一个重要问题。以下是一些常用的解决哈希冲突的方法以及它们的特点:
开放寻址法(Open Addressing)
工作原理
:当冲突发生时,选择另一个空的位置存放该数据。
特点
:
所有的元素都存储在哈希表中。
当表开始变得越来越满时,冲突的概率增加,从而降低了效率。
常用的开放寻址策略有线性探测(Linear Probing)、二次探测(Quadratic Probing)和双重哈希(Double Hashing)。
链地址法(Chaining)
工作原理
:每个表项都维持一个链表,所有映射到同一个哈希值的元素都存储在这个链表中。
特点
:
相对简单,易于实现。
哈希表中的每个位置都可能存储多个元素,这样冲突的处理变得相对容易。
与开放寻址法相比,链地址法在表变得满时的性能下降相对较小。
再哈希法(Rehashing)
工作原理
:使用多个哈希函数。当第一个哈希函数产生冲突时,尝试使用第二个哈希函数,依此类推。
特点
:
可以降低冲突的概率。
需要维护多个哈希函数,可能增加了计算的复杂性。
双哈希(Double Hashing)
工作原理
:与再哈希法类似,但双哈希是开放寻址法的一种,使用两个哈希函数进行探测。
特点
:
当第一个哈希函数产生冲突时,第二个哈希函数决定如何探测下一个位置。
提供了比线性和二次探测更好的性能。
扩容法
工作原理
:当哈希表达到一定的填充度时,将哈希表的大小翻倍,并重新哈希所有的数据。
特点
:
可以降低冲突的概率,提高查询的效率。
需要额外的重新哈希开销,可能导致某些操作的延迟增大。
03 介绍一下try except的用法和作用?
ry 和 except 是 Python 中的关键字,它们用于异常处理。异常是程序执行期间发生的事件,该事件会影响程序的正常流程。通过使用 try 和 except,你可以捕获并响应特定的异常,而不让程序崩溃或默认地终止。
作用
:
错误处理
:允许程序在发生错误时继续运行,而不是完全崩溃。
诊断问题
:提供对异常的详细信息,帮助开发者理解和修复问题。
资源管理
:确保在发生异常时,资源(如文件或网络连接)被适当地关闭或释放。
04 常用字符串格式化有哪几种
使用百分号(%)
这是较早的 Python 版本中常用的格式化方式。每个格式字符串都以 % 开始,后跟一个或多个字符,这些字符确定了数据的表示方式。
str.format() 方法
这是一种更现代的字符串格式化方法,使用 {} 作为占位符,然后使用 format() 方法将值传递给字符串。
f-string(格式化字符串文字)
这是 Python 3.6 及更高版本中引入的新方法。通过在字符串前加 f 或 F,并在 {} 中直接嵌入表达式,可以非常方便地格式化字符串。
模板字符串(Template Strings)
通过 Python 的 string 模块,你可以使用模板字符串。这主要用于当字符串格式从外部源(如配置文件或数据库)获得时。
05 用尽量简洁的方法将二维数组合并成一维数组
two_dim_list = [[1, 2, 3], [4, 5], [6, 7, 8, 9]] one_dim_list = [item for sublist in two_dim_list for item in sublist] print(one_dim_list)
06 python的可变类型和不可变类型的区别
1. 不可变类型 (Immutable Types):
这些类型的对象一旦创建,其内容就不能被修改。但要注意的是,变量可以重新指向新的对象,但已存在的对象自身不会被改变。 常见的不可变类型有:
整型(int)
浮点型(float)
复数型(complex)
布尔型(bool)
字符串(str)
元组(tuple)
可变类型 (Mutable Types):
这些类型的对象在创建后,其内容是可以被修改的。 常见的可变类型有:
列表(list)
字典(dict)
集合(set)
07 如何实现['1','2','3']变成[1,2,3]
使用列表解析 str_list = ['1', '2', '3'] int_list = [int(i) for i in str_list] print(int_list)
08 什么是反射,以及应用场景
反射(Reflection)是指程序能够在运行时检查或修改其内部结构,特别是对象的类型和属性的能力。简单地说,反射使得代码可以“自省”或“查看并更改”它自己。在很多高级编程语言中,如 Java、C# 和 Python,都提供了一定的反射功能。
Python 中的反射
: Python 提供了以下内置函数来支持反射: getattr(obj, 'x'): 获取对象 obj 的 x 属性。
setattr(obj, 'x', v): 将对象 obj 的 x 属性设置为 v。
hasattr(obj, 'x'): 检查对象 obj 是否有一个名为 x 的属性。
delattr(obj, 'x'): 删除对象 obj 的 x 属性。
type(obj): 获取对象 obj 的类型。
isinstance(obj, Class): 检查 obj 是否是 Class 类或其子类的实例。
issubclass(A, B): 检查 A 是否是 B 的子类。
dir(obj): 获取对象 obj 的所有属性和方法。
应用场景
:
动态导入模块
:根据配置或条件动态地导入模块。
插件架构
:应用程序可以检查和加载第三方提供的插件。
对象序列化
:转换对象为其它格式,例如 JSON,以便存储或网络传输。
自动生成代码
:例如,ORM(对象关系映射)库可能会使用反射来从数据库模式生成对应的类。
测试和模拟
:在测试环境中,通过反射来模拟或替换某些组件。
自定义工具和IDEs
:例如,一个对象浏览器或调试器可能使用反射来显示对象的属性和方法。
09 对列表[3,1,-4,-2]按照绝对值排序
lst = [3, 1, -4, -2] sorted_lst = sorted(lst, key=abs) print(sorted_lst)
10 super的作用
super() 是 Python 中的一个内置函数,它在面向对象编程中尤为重要,主要用于调用基类(父类或超类)的方法。它常用于重载继承的方法,确保基类中的适当方法得到调用。 在 Python 中,一个常见的使用场景是在子类中重载了 __init__ 方法时,使用 super() 来确保父类的 __init__ 方法也被正确调用。
作用
:
避免硬编码类名
:使用 super() 可以避免直接使用父类的名称来调用其方法,这使得代码更加健壮,因为你可以更改父类的名称而不需要修改到每个调用它的地方。
支持多重继承
:在多重继承的情况下,super() 能确保每个父类的方法只被调用一次,避免了因重复调用而引起的问题。它遵循方法解析顺序(MRO)来确定调用的顺序。