10月16日面向对象内置方法

发布时间 2023-10-16 16:02:58作者: songjunwan

面向对象里的部分内置方法

1._ _ str _ _内置方法的使用:

具体例子如下:
首先是不使用这个内置方法的情况

#普通情况
class ceshi:
    pass
f = ceshi()
print(f)#这里输出的是内存地址,但是我想要的不是内存地址

上面输出对象里面的结果是内存地址但是我需要的不是内存地址,这时候就能体现_ _str _ _的作用了

#利用str的方法来实现将内存地址变成我想要的
class ceshi:
    def __str__(self):
        # print('大把大把的钱')这个内置方法里面不能用print进行输出
        return '大把大把的钞票'
f = ceshi()
print(f)

同还有一个特别的思考点

#特别点就是这个内置方法是自己调用的
class ceshi:
    def __str__(self):
        # print('大把大把的钱')这个内置方法里面不能用print进行输出
        return '大把大把的钞票'
f = ceshi()
print(f)#我这里的输出和下面的调用方式结果是一样的
print(f.__str__())#这里是我的实例对象来调用

结果如图

通过结果的内容发现通过实例对象来调用这个内置方法,和直接输出这个实例对象的结果是一样的,这就说明这个内置方法在生成实例对象时它就绑定给了实例对象。

总结一下这个方法实际最大的作用就是用在调试以及给对象添加新的信息,它的输出方式要用到return,同时在生成实例对象时这个方法里面的内容就会绑定到实例对象里面(只要生成的实例对象都是同一个类,同时这个类里面有这个内置方法,那么它们都会被绑定这个内置方法)

2._ _ repr _ _ 内置方法的使用

具体的使用看下面的代码

#2.__repr__跟str类似
class ceshi:
    def __init__(self, shuju):
        self.shuju = shuju

    def __repr__(self):
        return f'ceshi{self.shuju}'

obj = ceshi(6666)
print(obj)#它是将对象直接输出(它将准确对象以及对象准确的数据以字符串的形式进行打印)
print(obj.__repr__())#这里是用实例对象来调用内置方法

结果为

上面的结果说明了这个方法在生成实例对象的时候聚绑定给了这个对象

总接一下:这个方法和_ _ str _ 的方法区别不大,可以这么理解, _ _ str _ _传到实例对象有多少个实例对象就有多少个一样的信息,而 _ _ repr _ _ 的方法是每个生成的实例对象它们添加的新的数据是有不一样的

拿手机为例子:_ _ repr _ _ 就是设计手机包装以及提供详细信息, _ _ str _ _ 就是广告描述来介绍这个手机,因为我的用户(不同的实例对象看着一样的广告)肯定要看广告才能知道这个手机,而 _ _ repr _ _ 在于这个手机的独特点(每个用户的手机肯定有不一样的点比如颜色什么的)

3.点拦截方法

总共有三个内置方法: _ _ setattr _ _ , _ _ delattr _ _ , _ _ getattr _ _

这三个内置方法的名字一看和反射的方法很像但是它们三个是内置方法

第一个:_ _ getattr _ _

作用是取对象的属性时,该对象没有这个属性就会去内置方法 _ _ getattr _ _内部去找

class Foo:
    def __init__(self, name):
        self.name = name
    def __getattr__(self, item):#当要获取的对象不存在时才会被触发
        print('此类里面没有你要的属性')

f = Foo('nick')
print(f.name)#这里有name这个属性所以不会进到__getattr__的方法内
print(f.age)#因为这个对象没有age这个属性所以就会到__getattr__方法里去找

结果如图

上面出现了None这个结果是因为它是内置方法所以要有返回值,而我没有给它设置返回值(在这个方法里用return来返回内容)

第二个:_ _ setattr _ _

它的作用是给实例对象给赋值时,这实例对象的类没有这个属性的位置参数所以就会到 _ _ setattr _ _方法内

#如果我给对象赋值但是它的类没有这个属性,就会进到__setattr__内置方法内
class Foo:
    def __init__(self, name):#这里的位置参数只有name这个位置参数没有age这个位置参数
        self.name = name
    def __setattr__(self, key, value):
        print('没有没有')
        


stu = Foo('han')
stu.age = 888#我要给这个实例对象添加年龄的属性

结果如图

这个结果有一个特别的地方就是我的 _ _ setattr _ _ 方法里面我只输出了一下,但是我的结果出现了两次一样的结果这是什么情况呢?

出现这个情况就需要这么想了,当你给name传参时是不是也在外面赋值,但是类里面的name没有值,这也变相的说明了就算这个类里面有这个属性的位置参数,我要是没有在内部给它赋值的话,就会出现这个情况,这个可以判断里面内部里面有没有这个属性的值,没有就会进入这个方法内。

下面的代码图就能看到具体的情况

解决办法就是在里面给属性赋值即可

第三个:_ _ delattr _ _

它的作用:删除对象中的属性,会进入 _ _ delattr _ _方法内

#删除对象中的属性,会进入 _ _ delattr _ _方法内
class student:
    def __init__(self, name, age, height):
        self.name = name
        self.age = age
        self.height = height
    def __delattr__(self, item):
        print('成功删除')

stu = student('nick', 18, 182)
del stu.age#这里我要将age这个属性删去,但是我的类里面有__delattr__这个内置方法
print(stu.__dict__)

结果如图

这个结果图说明了,我要删除实例对象属性时我的删除被它拦了下来,进入了这个内置方法的内部里面使用它的方法以及内容。

这三个方法的小结:

第一个方法(_ _ getattr _ _):假设你问你的父母今天吃什么(属性),而他们不知道吃什么,这时候可以回应你他们的想法,这个想法是一个默认的想法。

第二个方法(_ _ setattr _ _):如果你给收银员一张钞票(尝试设置属性值),他会检查这个钞票有没有防伪码(内部的属性)如果有就会收,如果没有会退回来

第三个方法(_ _ delattr _ _ ):假设你要求你的同学将一个糖果(属性)从盒子里扔掉,但是他看这个糖果挺好的就没有扔掉留了下来,让你在决定一下是否扔掉。

4.写一个类继承字典的内置方法

这里先提一点一切皆对象的思想

dic = dict(name = 'zjb', age = 18)

上面代码中的dict其实也是一个实例对象它也是有python自己编辑设计好的,那么我就可以生成一个类来继承这个类

class Mydict(dict):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)


di=Mydict(name = 'han', age = 17)#这里我生成一个字典对象
print(di['name'])#这就可以输出我设置的值了

上面代码就实现了这个内置。

但是我想要它的输出、添加方式和其它的实例对象一样直接对象名.属性或方法来输出和修改。这里就体现点拦截的作用了

首先我让它可以直接对象名.属性来查看属性的值

class Mydict(dict):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
    def __getattr__(self, item):
        return self[item]#这里的self相当于我的对象名而item是它的属性


di=Mydict(name = 'han', age = 17)#这里我生成一个字典对象
print(di.name)#这就实现了它的值实际是getattr的返回值

这里就体现 _ _ getattr _ _这个内置方法的重要性了,因为我的这个类继承了字典的格式要是没有这个内置方法,我直接以对象名.属性是会报没有该属性名,但是有了它我就可以在它里面设计返回值的格式是字典的格式就能调用了。简单理解就是我直接查看对象的属性没有,然后来到这个方法,这个方法的返回值被我设定成立字典形式就可以直接查看数据了。

现在来用另一个内置方法来添加新的属性


通过 _ _ setattr _ _这个内置方法我就实现了我需要的添加方法了。

现在我将删除也添加进去

#写一个类继承字典的内置方法
class Mydict(dict):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
    #获取属性
    def __getattr__(self, item):
        return self[item]#这里的self相当于我的对象名而item是它的属性
    #添加属性
    def __setattr__(self, key, value):
        self[key] = value#这里的key就是字典里的键(属性名),value就是键的值

    #删除属性
    def __delattr__(self, item):
        del self[item]#这里的self是要被删除的对象名,而后面的item是它的值
#生成对象
di=Mydict(name = 'han', age = 17)#这里我生成一个字典对象
#添加新属性
di.aihao = '打游戏'#这里就可以直接添加了
di['aihao2'] = '摸鱼王'#这我以字典的形式来添加也是可以的
#获取新属性
print(di.aihao)
print(di['aihao2'])
#删除属性
del di.age#我将对象里面的年龄的属性给删除了
#打印列表数据
print(di)#这里打印这个字典

结果如图

上面就实现了字典的设计了,字典也是一个对象,这也说明了一切皆对象

对象加括号调用的方法_ _ call _ _

_ _ call _ _ 对象加括号会调用它的方法

class Foo:
    def __call__(self, *args, **kwargs):
        print('4444')
f = Foo()
f()

结果如图