第6章 习题答案
1. 简述类和对象的含义及关系。
答:类和对象的关系就如同模具和用这个模具制作出的物品之间的关系。一个类为它的全部对象给出了统一的定义,而他的每个对象则是符合这种定义的一个实体,因此类和对象的关系就是抽象和具体的关系。
2. 按照以下提示尝试定义一个Person类并生成类实例对象。
属性:姓名(默认姓名为“张三”)。
方法:打印姓名。
提示:方法中对属性的引用形式需加上self,如self.name。
答:代码如下所示
class Person:
name = '张三'
def printName(self):
print(self.name)
3. 如果我们不希望对象的属性或方法被外部直接引用,我们可以怎么做,请举例说明。
答:我们可以在属性或方法的名字前面加上双下划线,这样子从外部是无法直接访问到,会显示AttributeError错误。
>>>class Person:
__name = 'WTY'
def getName(self):
return self.__name
>>>p = Person()
>>>p.__name
AttributeError: 'Person' object has no attribute '__name'
>>>p.getName()
'WTY'
4. 什么情况下我们需要在类中明确写出__init__方法?
答:当我们的实例对象需要有明确的初始化步骤的时候,你可以在__init__方法中部署初始化的代码。
5.__del__方法什么时候被调用?
答:Python提供了一个析构器,叫做__del__方法,当对象将要被销毁的时候,这个方法就会被调用。但一定要注意的是,并非del x就相当于自动调用x.__del__(),__del__方法是当垃圾回收机制回首这个对象的时候调用的。
6.我们都知道在Python中,两个字符串相加会自动拼接字符串,但遗憾的是两个字符串相减却抛出异常。现在我们要求定义一个Nstr类,支持字符串的相减操作:A-B,即从A中去除所有B的子字符串。请编写相应的程序。
示例:
>>> a = Nstr('I love Python!iiiiiiii')
>>> b = Nstr('i')
>>> a - b
'I love Python! '
答:只需要重载__sub__方法即可。
class Nstr(str):
def __sub__(self, other):
return self.replace(other,'')
7.请问以下代码的作用是什么?这样写正确吗?(如果不正确,请改正。)
def __setattr__(self,name,value):
self.name = value + 1
答:这段代码试图在对象的属性发生赋值操作的时候,将实际的值+1赋值给相应的属性。但这么写是错误的,因为每当属性被赋值的时候,__setattr__()会被调用,而里面的self.name = value + 1语句又会再次触发__setattr__()调用,导致无线递归。
代码应该这样写:
def __setattr__(self,name,value):
self.__dict__[name] = value + 1
8.要求写一个方法:当访问一个不存在的属性时,不报错且提示“该属性不存在!”(提示:应用getattr()方法。)
答:代码如下所示
>>> class Demo :
def __getattr__(self,name) :
return '该属性不存在!'
>>> demo = Demo()
>>>demo.x
'该属性不存在!'
9.按照以下要求,定义一个类实现摄氏度到华氏度的转换。(转换公式:华氏度 = 摄氏度×1.8 + 32。)
要求:我们希望这个类尽量简练地实现功能,如下:
>>> print(C2F(32))
89.6
答:为了尽量简练的实现功能,我们将采取“偷龙换凤”的小技巧。在类进行初始化之前,通过“掉包”arg参数,让实例对象直接返回计算后的结果。
具体代码如下所示:
class C2F(float):
"摄氏度转换为华氏度"
def __new__(cls, arg=0.0):
return float.__new__(cls,arg * 1.8 + 32)
10.定义一个类继承于int类型,并实现一个特殊功能:当传入的参数是字符串的时候,返回该字符串中所有字符的ASCII码的和(使用ord()获得一个字符的ASCII码值)。
实现如下:
>>> print(Nint(123))
123
>>> print(Nint(1.5))
1
>>> print(Nint('A'))
65
>>> print(Nint('Aa'))
162
答:代码如下所示
class Nint(int):
def __new__(cls,arg=0):
if isinstance(arg,str):
total = 0
for each in arg:
total += ord(each)
arg = total
return int.__new__(cls,arg)
11.定义一个单词(Word)类继承字符串,重写比较操作符,当两个Word类对象进行比较时,根据单词的长度来比较大小。要求:实例化时如果传入的是带空格的字符串,则取第一个空格前的单词作为参数。
答:可以通过重载__new__方法来实现(因为字符串是不可变类型),可以重写__gt__、__lt__、__ge__、__le__方法来定义Word类在比较操作中的表现。代码如下所示:
class Word(str):
'''存储单词的类,定义比较单词的几种方法'''
def __new__(cls,word):
#注意我们必须用到__new__方法,因为str是不可变类型
#所以我们必须在创建的时候将它初始化
if ' ' in word:
print("Value contains space. Truncating to first space.")
word = word[:word.index(' ')]#单词是一个空格之前的所有字符
return str.__new__(cls,word)
def __gt__(self,other):
return len(self) > len(other)
def __lt__(self,other):
return len(self) < len(other)
def __ge__(self,other):
return len(self) >= len(other)
def __le__(self,other):
return len(self) <= len(other)