1. 请问 list1[0] 和 list1[0:1] 一样吗?
答:不一样,list1[0] 返回第0个元素的值,list1[0:1] 返回一个只含有第0个元素的列表
2. 为什么要设计str
、None
这样的不变对象呢?
答:因为不变对象一旦创建,对象内部的数据就不能修改,这样就减少了由于修改数据导致的错误。此外,由于对象不变,多任务环境下同时读取对象不需要加锁,同时读一点问题都没有。我们在编写程序时,如果可以设计一个不变对象,那就尽量设计成不变对象。
3. 解释args和*kw的区别
答:
-
*args
是可变参数,args接收的是一个tuple; -
**kw
是关键字参数,kw接收的是一个dict。
4. 三引号字符串通常我们用于做什么使用?
答:
三引号字符串不赋值的情况下,通常当作跨行注释使用
5. 函数调用是由哪种数据结构实现的?
答:函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。
6. 我们根据列表、元祖和字符串的共同特点,把它们三统称为什么?
答:序列,因为他们有以下共同点:
- 都可以通过索引得到每一个元素
- 默认索引值总是从0开始(当然灵活的Python还支持负数索引)
- 可以通过分片的方法得到一个范围内的元素的集合
- 有很多共同的操作符(重复操作符、拼接操作符、成员关系操作符)
7. 你还能复述出“迭代”的概念吗?
答: 所谓迭代,是重复反馈过程的活动,其目的通常是为了接近并到达所需的目标或结果。每一次对过程的重复被称为一次“迭代”,而每一次迭代得到的结果会被用来作为下一次迭代的初始值。
8. 什么是形参?什么是实参?
答:
- 形参指的是函数创建和定义过程中小括号里的参数,
- 而实参指的是函数在调用过程中传递进去的参数。
9. 使用help(print)查看print()这个BIF有哪些默认参数?分别起到什么作用?
答:
>>> help(print)
Help on built-in function print in module builtins:
print(...)
print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file: a file-like object (stream); defaults to the current sys.stdout.
# 文件类型对象,默认是sys.stdout(标准输出流)
sep: string inserted between values, default a space.
# 第一个参数如果有多个值(第一个参数是收集参数),各个值之间默认用空格(space)隔开
end: string appended after the last value, default a newline.
# 打印最后一个值之后默认参数一个新行标识符(‘\n’)
flush: whether to forcibly flush the stream.
# 是否强制刷新流
10. 解释一下BIF中的 filter 和 map
答:
-
filter(function or None,iterable):两个参数为函数和可迭代的序列,函数定义了过滤的规则,默认过滤出真的部分。
>>> list(filter(lambda x : x % 2, range(10))) [1, 3, 5, 7, 9] >>> list(filter(None,[1, 2, 3, 4, 5, 6, 7, 8, 9, 0, False, True])) [1, 2, 3, 4, 5, 6, 7, 8, 9, True]
-
map(function or None,iterable):同filter()的两个参数相同,这个内置函数的作用是:将序列的每一个元素作为函数的参数进行运算加工,直到可迭代序列的每个元素都加工完毕,返回所有加工后的元素构成的新序列。
>>> list(map(lambda x : x * 2, range(10))) [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
11. 递归在编程上的形式是如何表现的呢?
答:在编程上,递归表现为函数调用本身这么一个行为。
12. 递归必须满足哪两个基本条件??
答:
- 1.函数调用自己
- 2.函数设置了正确的返回值
13. 请聊一聊递归的优缺点
答:
- 优点:
- 递归的基本思想是把规模大的问题转变成规模小的问题组合,从而简化问题的解决难度(例如汉诺塔游戏)。
- 有些问题使用递归使得代码简洁易懂(例如你可以很容易的写出前中后序的二叉树遍历的递归算法,但如果要写出相应的非递归也可以做到。)
- 缺点:
- 由于递归的原理是函数调用自个儿,所以一旦大量的调用函数本身空间和时间消耗是“奢侈的
- 初学者很容易错误的设置了返回条件,导致递归代码无休止调用,最终栈溢出,程序崩溃。
14. 如何用递归写出汉诺塔问题?
答:
# encoding: utf-8
def hanoi(n, x, y, z):
if n == 1:
print (x, ' --> ', z)
else:
# 将前 n - 1 个盘子从x移动到y上
hanoi(n-1, x, z, y)
# 将最后一个盘子从x移动到z上
print (x, ' --> ', z)
# 将前 n - 1 个盘子从y移动到z上,完成
hanoi(n-1, y, x, z)
print hanoi(4, 'X', 'Y', 'Z')
15. 当你听到小伙伴们在谈论“映射”、“哈希”、“散列”或者“关系数组”的时候,事实上他们就是在讨论什么呢?
答:字典,都是一个概念。
16. Python的字典是否支持一键(Key)多值(Value)?
答:不支持,对相同的键再次赋值会将上一次的值直接覆盖。
In [60]: dict1 = {1:'one', 1: 'two'}
In [61]: dict1
Out[61]: {1: 'two'}
17. Python对键(Key)和值(Value)有没有类型限制?
答:
Python对键的要求相对要严格一些,要求它们必须是可哈希(Hash)的对象,不能是可变类型(包括变量、列表、字典本身等)。但是Python对值是没有任何限制的,它们可以是任意的Python对象。
如果不清楚哈希原理以及字典的存放原理的童鞋,推荐阅读下小甲鱼帮你整理的这篇文章:你知道Python的字典(Dict)是如何存储的吗?
18. 请问集合的唯一作用是什么呢?
答:集合几乎所有的作用就是确保里边包含的元素的唯一性,就像世界上没有两片完全相同的树叶一样,集合内不可能存在两个相同的元素!
19. 如果你希望创建的集合是不变的,应该怎么做?
答:frozenset()
20. 打开一个文件我们使用open()函数,通过设置文件的打开模式,决定打开的文件具有那些性质,请问默认的打开模式是什么呢?
答:open()函数默认的打开模式是' rt',即可读、文本的模式打开。
21. 尽管Python有所谓的“垃圾回收机制”,但对于打开了的文件,在不需要用到的时候我们仍然使用f. close()将文件对象“关闭”,这是为什么呢?
答:Python拥有垃圾收集机制,会在文件对象的引用计数降至零的时候自动关闭文件,所以在Python编程里,如果忘记关闭文件并不会带来什么危险。
但并不是说就可以不要关闭文件,如果你对文件进行了写入操作,那么你应该在完成写入之后进行关闭文件。因为Python可能会缓存你写入文件中的数据,如果这中间断电了神马的,那些缓存的数据根本就不会写入到文件中。所以,为了安全起见,要养成使用完文件后立刻关闭的优雅习惯。
22. 如何获得文件对象(f)当前文件指针的位置?
答:f.tell()即可。
23. pickle的实质是什么?
答:pickle的实质就是利用一些算法将你的数据对象“腌制”成二进制文件,存储在磁盘上,当然也可以放在数据库或者通过网络传输到另一台计算机上。
24. 使用pickle的什么方法存储数据?
答:pickle.dump(data, file) # 第一个参数是待存储的数据对象,第二个参数是目标存储的文件对象,注意要先使用'wb'的模式open文件哦。
25. 使用pickle的什么方法读取数据?
答:pickle.load(file) # 参数是目标存储的文件对象,注意要先使用'rb'的模式open文件哦。
26. 使用pickle能不能保存".txt"类型的文件?
答:可以,不过打开后是乱码,因为是以二进制的模式写入的。
27. 结合你自身的编程经验,总结下异常处理机制的重要性?
答:由于环境的不确定性和用户操作的不可以预知性都可能导致程序出现各种问题,因此异常机制最重要的无非就是:增强程序的健壮性和用户体验,尽可能的捕获所有预知的异常并写好处理的代码,当异常出现的时候,程序自动消化并恢复正常(不至于崩溃)。
28. 一个 try 语句可以和多个 except 语句搭配吗?为什么?
答:可以。因为 try 语句块中可能出现多类异常,利用多个 except 语句可以分别捕获并处理我们感兴趣的异常。
29. 你知道如何统一处理多类异常吗?
答:在 except 后边使用小括号“()”把多个需要统一处理的异常括起来:
try:
int('abc')
sum = 1 + '1'
f = open('我是一个不存在的文档.txt')
print(f.read())
f.close()
except (OSError, TypeError, ValueError) as reason:
print('出错啦T_T\n错误原因是:' + str(reason))
输出:
出错啦T_T
错误原因是:invalid literal for int() with base 10: 'abc'
30. 对象中的属性和方法,在编程中实际是什么?
答:变量(属性)和函数(方法)。
31. 类和对象是什么关系呢?
答:类和对象的关系就如同模具和用这个模具制作出的物品之间的关系。一个类为它的全部对象给出了一个统一的定义,而它的每个对象则是符合这种定义的一个实体,因此类和对象的关系就是抽象和具体的关系。
32. 请用一句话概括面向对象的几个特征?
答:
- 封装:对外部隐藏对象的工作细节
- 继承:子类自动共享父类之间数据和方法的机制
- 多态:可以对不同类的对象调用相同的方法,产生不同的效果
33. self参数的作用是什么?
答:绑定方法,据说有了这个参数,Python再也不会傻傻分不清是哪个对象在调用方法了,你可以认为在方法中的self其实就是实例对象的唯一标志。
34. 如果我们不希望对象的属性或方法被外部直接引用,我们可以怎么做?
答:
-
我们可以在属性或方法名字前边加上双下划线,这样子从外部是无法直接访问到,会显示AttributeError错误。
-
Python事实上是采用一种叫“name mangling”技术,将以双下划线开头的变量名巧妙的改了个名字而已,我们仍然可以在外部通过“_类名 __变量名”的方式访问。
35. 类在实例化后哪个方法会被自动调用?
答:__init __
方法会在类实例化时被自动调用,我们称之为魔法方法,你可以重写这个方法,为对象定制初始化方案。
36. super函数有什么“超级”的地方?
答:super函数超级之处在于你不需要明确给出任何基类的名字,它会自动帮你找出所有基类以及对应的方法。由于你不用给出基类的名字,这就意味着你如果需要改变类继承关系,你只要改变class语句里的父类即可,而不必在大量代码中修改所有被继承的方法。
37. 什么时候用组合,什么时候用继承?
答:
- 根据实际应用场景确定。简单的说,组合用于“有一个”场景中,继承用于“是一个”场景中。
- 例如,水池里有一个乌龟,天上有一只鸟,地上有一个小甲鱼,这些适合使用组合。丝瓜是瓜,女人是人,鲨鱼是鱼,这些就应该使用继承。
38. 类对象是在什么时候产生?
答:当你这个类定义完的时候,类定义就变成类对象,可以直接通过“类名.属性”或者“类名.方法名()”引用或使用相关的属性或方法。
39. 如果对象的属性跟方法名字相同,会怎样?
答:如果对象的属性跟方法名相同,属性会覆盖方法。
In [23]: class C:
...: def x(self):
...: print('Xman')
...:
In [24]: c = C()
In [25]: c.x()
Xman
In [26]: c.x = 1
In [27]: c.x
Out[27]: 1
In [28]: c.x()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-28-03cbc961c440> in <module>
----> 1 c.x()
TypeError: 'int' object is not callable
40. 请问以下类定义中哪些是类属性,哪些是实例属性?
class C:
num = 0
def __init__(self):
self.x = 4
self.y = 5
C.count = 6
答:num和count是类属性(静态变量),x和y是实例属性。大多数情况下,你应该考虑使用实例属性,而不是类属性(类属性通常仅用来跟踪与类相关的值)。
41. 是哪个特征让我们一眼就能认出这货是魔法方法?
答:魔法方法总是被双下划线包围,例如__init__
。
42. 类实例化对象所谓用的第一个方法是什么?
答:
-
__new__
是在一个对象实例化的时候所调用的第一个方法。 - 它跟其他魔法方法不同,它的第一个参数不是self,而是这个类(cls),而其他参数会直接传递给__ int__()方法的。
43. .什么时候我们需要在类中明确写出__ init__()方法?
答:当我们的实例对象需要有明确的初始化步骤的时候,你可以在__ init__方法中部署初始化的代码。
44. 请问__new__()
方法是负责什么任务?
答:__new__()
方法主要是在一个对象实例化时返回一个实例对象,通常是参数cls这个类的实例化对象,当然你也可以返回其他对象。
45. __del__()
魔法方法什么时候会被自动调用?
答:
-
如果说
__init__()
和__new__()
方法是对象的构造器的话,那么Python也提供了一个析构器,叫做__del__()
方法。 -
当对象将要被销毁的时候,这个方法就会被调用。
-
但一定要注意,并非del x就相当于自动调用
x.__ del__()
方法,__ del__()方法是当垃圾回收机制回收这个对象的时候调用的。
46. 自从Python 2.2以后,对类和类型进行了统一,做法就是将int()、float()、str()、list()、tuple()这些BIF转换为工厂函数。请问所谓的工厂函数,其实是什么原理?
答:工厂函数,其实就是一个类对象。当你调用他们的时候,事实上就是创建一个相应的实例对象。
# a和b是工厂函数(类对象)int的实例对象
>>> a = int('123')
>>> b = int('345')
>>> a + b
468
47. 当实例对象进行加法操作时,会自动调用什么魔法方法?
答:对象a和b相加时(a+b),Python会自动根据对象a的__ add__()魔法方法进行相加操作。
48. 给出以下算数运算符对应的魔法方法:
运算符 | 对应的魔法方法 | 中文注释 |
---|---|---|
+ | __ add__(self, other) | 加法 |
- | __ sub__(self, other) | 减法 |
* | __ mul__(self, other) | 乘法 |
/ | __ truediv__(self, other) | 真除法 |
// | __ floordiv__(self, other) | 整数除法 |
% | __ mod__(self, other) | 取余除法 |
divmod(a, b) | __ divmod__(self, other) | 把除数和余数运算结果结合 |
** | __ pow__(self, other[,modulo]) | self的other次方再对modulo取余 |
<< | __ lshift__(self, other) | 按位左移 |
>> | __ rshift__(self, other) | 按位右移 |
& | __ and__(self, other) | 按位与操作 |
^ | __ xor__(self, other) | 按位异或操作(同为0,异为1) |
丨 | __ or__(self, other) | 按位或操作(有1则1) |
网友评论