1、在Python中实现工厂有几种方式?
参考:《Python面向对象编程指南》
答:
a 定义一个函数,返回不同类的对象;
b 定义一个类,包含了创建对象的方法。这是完整的工厂设计模式,正如设计模式书中提到的,在类似Java这样的语言里,工厂类层次结构是必需的,因为语言本身并不支持可以脱离类而单独存在的函数。
2、python中常用的哈希库有哪些?分别有什么作用?
参考:《Python面向对象编程指南》
答:
Python中有两个哈希库。其中,hashlib可以提供密码级别的哈希函数,zlib模块包含两个高效的哈希函数:adler32()和crc32()。对于相对简单的值,我们不使用这些内置的函数,对于复杂的或者很大的值,这些内置的函数可以提供很大的帮助。
3、python中等价性比较有哪几个层次?
参考:《Python面向对象编程指南》
答:
哈希值相等:这意味两个对象可能相等。哈希值是判断两个对象有可能相等的快捷方式。如果哈希值不同,两个对象不可能相等,也不可能是同一个对象。
比较结果相等:这意味着两个对象的哈希值已经是相等的,这个比较用的是==运算符。如果结果相等,那么两个对象有可能是同一个。
IDD相等:这意味着两个对象是同一个对象。它们的哈希值相同,并且使用==的比较结果相等,这个比较用的是is运算符。
4、什么情况下,需要使用__eq__()和__hash__()方法来定义相等性测试和哈希值?
参考:《Python面向对象编程指南》
答:
(1) 不可变对象:这些是不可以修改的无状态类型对象,例如tuple、namedtuple和frozenset。我们针对这种情况有两个选择。
a 不用自定义__hash__()和__eq__()。这意味着直接使用继承而来的行为。这种情况下,__hash__()返回一个简单的函数代表对象的ID值,然后__eq__()比较对象的ID值。默认相等性测试的行为有时候比较反常。我们的应用程序可能会需要Card(1,Clubs)的两个实例来测试相等性和计算哈希值,但是默认情况下这不会发生。
b 自定义__hash__()和__eq__()。请注意,这种自定义必须是针对不可变对象。
(2) 可变对象:这些都是有状态的对象,它们允许从内部修改。设计时,我们有一个选择如下。自定义__eq__(),但是设置__hash__为None。这些对象不可以用作dict的键和set中的项目。
5、在数通和核心网领域的python使用者不可避免的会接触到bytes()函数,那么根据bytes()参数不通,行为有什么差别?
参考:《Python面向对象编程指南》
答:
bytes(integer):返回一个不可变的字节对象,这个对象包含了给定数量的0x00值。
bytes(string):这个版本会将字符串编码为字节。其他的编码和异常处理的参数会定义编码的具体过程。
bytes(something):这个版本会调用something.__bytes__()创建字节对象。这里不用编码或者错误处理参数。
6、__del__()最常见的用途是什么?
参考:《Python面向对象编程指南》
答:
确保文件被关闭。
通常,包含文件操作的类都会有类似下面这样的代码。__del__ = close这会保证__del__()方法同时也是close()方法。
7、__new__方法最主要的用途是什么?
参考:《Python面向对象编程指南》
答:
初始化不可变对象。
__new__()方法中允许创建未初始化的对象。这允许我们在__init__()方法被调用之前先设置对象的属性。由于不可变类的__init__()方法很难重载,因此__new__方法提供了一种扩展这种类的方法。
8、__new__()方法的是如何实现的?
参考:《Python面向对象编程指南》
答:
return super().__new__(cls )将调用基类的__new__()方法创建对象。这个工作最终委托给了object.__new__(),这个方法创建了一个简单的空对象。除了cls以外,其他的参数和关键字最终都会传递给__init__()方法,这是Python定义的标准行为。
9、默认情况下,创建任何类内部的属性都支持哪些操作?
参考:《Python面向对象编程指南》
答:
创建新属性。
为已有属性赋值。
获取属性的值。
删除属性。
10、关于特性有几种基本设计模式?
参考:《Python面向对象编程指南》
答:
主动计算(Eager Calculation):每当更新特性值时,其他相关特性值都会立即被重新计算。
延迟计算(Lazy calculation):仅当访问特性时,才会触发计算过程。
11、一个抽象基类具有哪些特性?
参考:《Python面向对象编程指南》
答:
抽象意味着这些类中不包括我们需要的所有方法的定义。为了让它成为一个真正有用的子类,我们需要提供一些方法定义。
基类意味着其他类会把它当作基类来使用。
抽象类本身提供了一些方法的定义。更重要的是,抽象基类为缺失的方法函数提供了方法签名。子类必须提供正确的方法来创建符合抽象类定义的接口的具体类。
12、抽象基类在哪些情况下会被使用到?
参考:《Python面向对象编程指南》
答:
当我们自定义类时,使用抽象基类作为基类。
我们在一个方法中使用抽象基类来确保一种操作是可行的。
我们在诊断信息或者异常中使用抽象基类来指出一种操作为什么不能生效。
13、collections.abc模块提供了很多抽象基类,这些抽象基类中只包含一个特殊方法的基类有哪些?
参考:《Python面向对象编程指南》
答:
Container基类要求子类实现__contains__()方法,这个特殊方法实现了in运算符。
Iterable基类要求子类实现__iter__()方法。for语句、生成器表达式和iter()函数都需要使用这个方法。
Sized基类要求子类实现__len__()方法。len()函数需要使用这个方法,它也很稳妥地实现了__bool__()方法,但是这个方法不是必需的。
Hashable基类要求子类实现__hash__()方法。hash()函数需要使用这个方法,如果这个方法被实现了,就意味着当前对象是不可变的。
14、python中常用的6种集合函数以及他们的功能?
参考:《Python面向对象编程指南》
答:
namedtuple()函数会创建允许包含可命名属性的tuple类,我们可以使用这个函数而不是额外完整地定义一个仅仅为属性值命名的类。
deque(注意这种不规则的拼写方式)是一个双端队列,
一个类似list的集合,但是可以在任何一段快速地进行增加和弹出操作。可以用这个类的其中一部分属性来创建常规的栈或队列。
在一些情况下,我们可以使用ChainMap,而不是合并不同的映射。这是一个将多个映射连接起来的方法。一个OrderedDict集合是会保持所有元素原始插入顺序的一种映射。
defaultDict(注意这种不规则的拼写方式)是dict的一个子类,它内部使用一个工厂函数为所有没有值的键提供默认值。
Counter也是一个dict的子类,它可以被用来统计对象,进而创建频率表。但是,它实际上是一个更复杂的数据结构,通常我们称为多重集合(multiset)或者包(bag)。
15、当使用容器和集合时,设计原则有哪几个步骤?
参考:《Python面向对象编程指南》
答:
1.考虑序列、映射和集合的内置版本。
2.考虑collections模块中的库扩展和一些其他的集合类型,例如heapq、bisect和array。
3.考虑组合使用现有的类定义。在许多情况下,一个tuple对象的list或者是包含list的dict就已经提供了必需的功能。
4.考虑扩展前面提到的某个类来提供额外的方法或者属性。
5.考虑用封装一个现有结构的方式作为提供额外方法或者属性的另一个途径。
6.最后,考虑实现一个新的数据结构。通常,有很多现成的资料可供我们参考。可以从维基百科的文章开始阅读,例如:http://en.wikipedia.org/wiki/List_of_data_structures。