第4章 类与面向对象
4.1 对象比较:is 与 ==
is比较的是两个变量是否指向同一个对象,表示相同。
==比较的是两个变量所指向的对象是否具有相同的值(内容相同),表示相等。
a = [1, 2, 3] b = a c = [1, 2, 3] d = [a] e = [b] f = [c] print(f‘a == b: {a == b}‘) print(f‘a == c: {a == c}‘) print(f‘a is b: {a is b}‘) print(f‘a is c: {a is c}‘) print(f‘d == e: {d == e}‘) print(f‘d == f: {d == f}‘) print(f‘d is e: {d is e}‘) print(f‘d is f: {d is f}‘) ‘‘‘ 输出结果 a == b: True a == c: True a is b: True a is c: False d == e: True d == f: True d is e: False d is f: False ‘‘‘
4.2 字符串转换(每个类都需要__repr__)
python中内置的str和repr函数可以将对象转字符串,它们分别调用的是对象的__str__和__repr__方法,通常是使用str或者repr而不是直接调用对象的__str__和__repr__。
在格式化字符串的时候如果指定了!r则是按__repr__输出字符串
自定义类如果没有实现__str__或__repr__方法,默认转字符串输出的是包含类名和对象实列id的字符串。
默认情况下,如果没有定义__str__,则__str__调用的是__repr__方法,因此定义了__repr__总是能正常的转换成字符串。
class Car: def __init__(self, color, mileage): self.color = color self.mileage = mileage def __repr__(self): return (f‘{self.__class__.__name__}(‘ f‘{self.color!r}, {self.mileage!r})‘) def __str__(self): return f‘a {self.color} car‘ car = Car(‘red‘, ‘37281‘) print(car) # 按str输出 print(‘{!r}‘.format(car)) # 按repr输出 ‘‘‘ 默认的输出结果 <__main__.Car object at 0x000001CEB075C2E8> <__main__.Car object at 0x000001CEB075C2E8> ‘‘‘ ‘‘‘ 自定义了__str__和__repr__方法的输出结果 a red car Car(‘red‘, ‘37281‘) ‘‘‘ ‘‘‘ 把自定义的__str__注释后的输出结果 Car(‘red‘, ‘37281‘) Car(‘red‘, ‘37281‘) ‘‘‘
通常情况下,__str__的结果侧重于可读性,面向用户;而__repr__的结果侧重于无歧义,面向开发人员。
import datetime today = datetime.date.today() print(str(today)) # 输出普通人可理解的字符串 print(repr(today)) # 输出更专业的字符串,并且此结果可直接创建对象,恢复对象的状态(通常情况我们自定义类不用做地这么麻烦) ‘‘‘ 输出结果 2021-08-29 datetime.date(2021, 8, 29) ‘‘‘
python2中__str__返回的是字节,而__unicode__返回的是字符串(它对应内置函数unicode)。
# --encoding=utf8-- class Car(object): def __init__(self, color, mileage): self.color = color self.mileage = mileage def __repr__(self): return ‘{}({!r}, {!r})‘.format( self.__class__.__name__, self.color, self.mileage) def __unicode__(self): return u‘a {self.color} car‘.format(self=self) def __str__(self): return unicode(self).encode(‘utf-8‘) car = Car(‘red‘, ‘37281‘) print(car) # 按str输出 print(‘{!r}‘.format(car)) # 按repr输出 ‘‘‘ 默认的输出结果 a red car Car(‘red‘, ‘37281‘) ‘‘‘
4.3 自定义异常
定义自己的异常类型能让代码清楚地表达出自己的意图,并易于调试。
要从Python内置的Exception类或特定的异常类(如ValueError或KeyError)派生出自定义异常。
可以使用继承来根据逻辑对异常分组,组成层次结构。
4.4 克隆对象
创建的浅副本不会克隆子对象,因此副本和原对象并不完全独立。
对象的深副本将递归克隆子对象。副本完全独立于原对象,但创建深副本的速度较慢。
使用copy模块,copy.copy(x)进行浅复制,copy.deepycopy(x)进行深复制。
对于内置的容器,只需要使用list、dict、set这样的工厂函数就能创建浅副本,这样更据Python特色。