第十周作业-面向对象进阶

1. 集合(set)元素去重的判断依据是什么

在调用set()时,每加入一个元素会调用__hash__方法得到一个哈希值,如果该值与集合中其它元素的哈希值不同则直接判断不重复并加入集合;如果哈希值有冲突,则再调用__eq__方法判断两个值是否相等,结果为False时也加入集合。

2. 总结本周视频讲解魔术方法的作用及什么情况会执行到该方法

运算符相关的魔术方法:

方法 意义
__new__ 实例化一个对象,该方法需要返回一个对象,如果该值不是cls的实例,则不会调用__init__方法,该方法永远时静态方法
__str__ 使用print、str、format函数时调用该方法,返回一个字符串,如果没有定义则调用__repr__方法,如果都没有定义则返回object类定义的该方法(返回一个内存地址信息)
__repr__ 使用内建函数repr()对一个对象获取字符串表达,返回一个字符串
__bytes__ 内建函数bytes()调用,返回一个bytes对象
__bool__ 内建函数bool()返回布尔值,如果没有定义此函数则调用__len__函数,长度非0为真,如果都没定义则返回真
__lt__ 比较运算符重载,进行<操作时调用
__le__ 比较运算符重载,进行<=操作时调用
__eq__ 比较运算符重载,进行==操作时调用,可以判断不等于
__gt__ 比较运算符重载,进行>操作时调用,可以判断小于
__ge__ 比较运算符重载,进行>=操作时调用,可以判断小于等于
__ne__ 比较运算符重载,进行!=操作时调用
__add__ 算数运算符重载,进行+操作时调用
__sub__ 算数运算符重载,进行-操作时调用
__mul__ 算数运算符重载,进行*操作时调用
__truediv__ 算数运算符重载,进行/操作时调用
__mod__ 算数运算符重载,进行%操作时调用
__floordiv__ 算数运算符重载,进行//操作时调用
__pow__ 算数运算符重载,进行**操作时调用
__divmod__ 算数运算符重载,进行divmod操作时调用
__iadd__ 运算符重载,进行+=操作时调用
__isub__ 运算符重载,进行-=操作时调用
__imul__ 运算符重载,进行*=操作时调用
__itruediv__ 运算符重载,进行/=操作时调用
__imod__ 运算符重载,进行%=操作时调用
__ifloordiv__ 运算符重载,进行//=操作时调用
__ipow__ 运算符重载,进行**=操作时调用
__sub__ 运算符重载,进行/=操作时调用

容器相关的魔术方法:

方法 意义
__len__ 内建函数len(),返回>=0的整数
__iter__ 迭代容器对象时调用,返回一个新的迭代器对象
__contains__ in成员运算符,没有实现则调用__iter__遍历
__getitem__ 实现self[key]访问。序列对象,key接受整数为索引,或者切片。对于set和dict,key为hashable。key不存在引发KeyError异常
__setitem__ __getitem__ 的访问类似,是设置值的方法
__missing__ 字典或其子类使用__getitem__()调用时,key不存在执行该方法

反射相关的魔术方法:
运行时,runtime,区别于编译时,指的是程序被加载到内存中执行的时候。
反射,reflection,指的是运行时获取类型定义信息。
一个对象能够在运行时,像照镜子一样,反射出其类型信息。
简单说,在Python中,能够通过一个对象,找出其type、class、attribute或method的能力,称为反射或者自省。
具有反射能力的函数有type()、isinstance()、callable()、dir()、getattr()

内建函数 意义
getattr(object,name[, default]) 通过name返回object的属性值。当属性不存在,将使用default返回,如果没有default,则抛出AttributeError。name必须为字符串
setattr(object,name, value) object的属性存在,则覆盖,不存在,新增
hasattr(object,name) 判断对象是否有这个名字的属性,name必须为字符串
魔术方法 意义
__getattr__() 当通过搜索实例、实例的类及祖先类查不到属性,就会调用此方法
__setattr__() 通过 . 访问实例属性,进行增加、修改都要调用它
__delattr__() 当通过实例来删除属性时调用此方法
__getattribute__ 实例所有的属性调用都从这个方法开始

实例属性查找顺序为:
实例调用__getattribute__() --> instance.__dict__ --> instance.__class__.__dict__ --> 继承的祖先类(直到object)的__dict__ --> 调用__getattr__()

3. 结合本周所学内容,实现如下类:

   class Ob:
     pass
   执行以下操作:
   a = Ob('tom')
   b = Ob('tom')
   print('a: ', a)
   a[0] = 'a'
   print('a:', a)
   a * 3
   print('len: ', len(a))
   del a[1]
   print('a: ', a)
   print('set: ', {a, b})
   其输出如下:
   a: ['1', '2']
   a: ['a', '2']
   len:  6
   a: ['a', 'a', '2', 'a', '2']
   set: {<Ob name=tom items=['a', 'a', '2', 'a', '2']>}
class Ob:
    def __init__(self, name):
        self.name = name
        self.items = ['1', '2']

    def __str__(self): # 解决print中的显示
        return str(self.items)

    def __repr__(self): # 解决集合中的展示
        return '<{} name={} items={}>'.format(self.__class__.__name__, self.name, self.items)

    def __setitem__(self, key, value): # 解决以列表下标方式设置值
        self.items[key] = value

    def __mul__(self, other): # *运算符重载
        self.items *= other

    def __len__(self): # 显示长度
        return len(self.items)

    def __delitem__(self, key): # 删除元组元素
        self.items.pop(key)

    def __hash__(self): # 与__eq__方法结合在集合中去重
        return id(self.name)

    def __eq__(self, other):
        return self.name == other.name


a = Ob('tom')
b = Ob('tom')
print('a: ', a)
a[0] = 'a'
print('a:', a)
a * 3
print('len: ', len(a))
del a[1]
print('a: ', a)
print('set: ', {a, b})

结果如图:
image

posted @ 2021-12-09 19:07  Atlas-777  阅读(15)  评论(0)    收藏  举报