8 面向对象高级

8 面向对象高级

8.1 常用内置函数

8.1.1 属性访问函数——# python的内置函数

例:class Person:一个

     def __init__(self,name,age):

        self.name=name

        self.age=age

     def eat(self):

         print(self.name,'正在吃饭')

yige=Person('一个',18)

hasattr

判断属性是否存在

print(hasattr(yige,'sex'))——False

getattr

得到属性值,没有则报错

print(getattr(yige,'name'))——一个

setattr

设置属性值

setattr(yige,'name','两个')

print(getattr(yige,'name'))——两个

delattr

删除属性

delattr(yige,'name')

print(hasattr(yige,'name'))——False

注意:属性名需要加上引号,attr 即attribute的缩写。

通过简单 if 判断就能避免属性不存在时,报错的问题,同时也可以设置属性值。

例:if hasattr(yige,'sex'):

     print(yige.sex)

else:

     setattr(yige,'sex','男')

print(yige.sex)

======

res=getattr(yige,'sex') if hasattr(yige,'sex') else setattr(yige,'sex','男')     #三目运算

print(yige.sex)

8.1.2 属性调用过程——# object方法

这里调用了一些内置的方法,也会产生同样的效果,这是因为那些函数本身就是调用的这些方法。

__getattribute__

print(yige.__getattribute__('name'))——一个

__setattr__

yige.__setattr__('name','两个')

print(yige.__getattribute__('name'))——两个

__delattr__

yige.__delattr__('name')

print(yige.__getattribute__(name))——报错,没有名字

当实例调用一个不存在的属性的时候,会发生报错,但是如果增加__getattr__方法,则不会报错,而是执行此方法内的内容。

例:class Person:

     def __init__(self,name,age):

        self.name=name

         self.age=age

     def eat(self):

         print(self.name,'正在吃饭')

     def __getattr__(self,item):  

         print('no attribute',item)

yige=Person('一个',18)   #实例

yige.sex——no attribute sex

8.1.3对象关系方法

issubclass

判断第一个类是不是后面类的子类

print(issubclass(Person,object))——True

isinstance

判断实例是否是这个类的实例,

或者判断数据是否是这个类型

print(isinstance(yige,Person))——True

print(isinstance((yige,int))——False

type

只能判断单个实例是否是属于这个类

print(type(yige)==Person)——True

print(isinstance(yige,(Person,int)))  

——False    #判断是否在两个类,加括号,用逗号隔开,两个类是or的关

8.2 魔法方法

8.2.1  __new__方法

Python中很多内置方法都是两个下划线在两边,中间是单词名字,并且这样的方法名字有一定的特殊的含义,把这种方法都称之为魔法方法。

比如__new__方法,就是最开始调用的一个方法,会在初始化之前自动调用。

例:class Earth:

    def __new__(cls):

        print('new')

def __init__(self):

        print('init')

e = Earth() ——new

实例是__new__方法创建的,所以__new__会最先执行,因为我们重用的__new__把它的功能改成print('new'),所以不具备实例创建的功能,所以init并没有被调用,实例并没有被创建,如果我们想要继续创建实例,就需要调用object的__new__方法进行重用super().__new__(cls)。

例:class Earth:

    def __new__(cls):

        print('new')

        return super().__new__(cls)

    def __init__(self):

        print('init')

e = Earth() ——new  init

8.2.2 单例模式

例:class Phone:

    def __init__(self,name):

        self.name = name

xm = Phone('小米')

hw = Phone('华为')

print(xm.name)

print(hw.name)   #此时一个类对应两个实例

单例模式的意思是:类始终只有一个实例存在,不会同时出现多个实例。利用__new__方法,可以很方便的去实现一个类的单例模式。

例:class RootUtil:  

    def __new__(cls):       #重新定义new方法,cls就是一个类,是RootUtil

        if not hasattr(cls,'a'):

            cls.a= super().__new__(cls)   #重用new;定义一个属性a保存创建的实例

        return cls.a

    def __init__(self):

        self.name = 'rootUtil'

ru1 = RootUtil()    # print(ru1)输出的ru1,ru2地址值相同,操作的是同一个实例

ru2 = RootUtil()

print(ru1.name)

print(ru2.name)——#输出都是rootUtil

8.2.3 输出魔法方法

__str__ : 修改print打印时的样子

__repr__ : 修改直接打印时的样子

例:class RootUtil:  

    def __new__(cls):       

        if not hasattr(cls,'a'):

            cls.a= super().__new__(cls)

        return cls.a   

    def __init__(self):

        self.name = 'rootUtil'

    def __str__(self):     #修改print打印时的样子,即交互模式下直接输入print(ru1)

        return f'姓名:{self.name}'

def __repr__(self):    #修改直接打印时的样子,即交互模式下直接输入ru1

        return f'name:{self.name}'   

ru1 = RootUtil()

print(ru1.name)——rootUtil  #此时查看的是object的__str__

print(ru1)——姓名:rootUtil   #此时查看的是__str__,__repr__

print() 会先找__str__,如果没有,再看__repr__,object的__str__,所以当用__str__,__repr__时,使用print()会打印出输出内容。

8.3 协议

8.3.1 序列协议:列表和元组

序列协议即定义:__len__, __getitem__,__setitem__,__delitem__等协议,如果不需要改变,那就不要定义。

例:class IndexTuple:

     def __init__(self,*args):

         self.value = args     #元组

         self.index = tuple(enumerate(self.value))     # enumerate,枚举函数,可以得到

def __len__(self):          #获取长度          每个值及对应的索引

         return len(self.value)

     def __getitem__(self,key):   #索引

         return self.index[key][1]  

     def __repr__(self):         #获取元组

         return str(self.value)    #字符串强转    

my_t = IndexTuple(1,2,3)

print(len(my_t ))——3

print(my_t[1])  ——2         # my_t[1]此处索引是中括号,key=1,得到的值是2

print(my_t) ——(1,2,3)     # 得到元组类型

8.3.2 迭代器协议:列表和迭代对象

只要类实现了__iter__ 和 __next__ 方法,则这个类就是迭代器,因此只要实现这两个方法,则是可以迭代对象。

例:class Number:

    def __init__(self,end=10):  #迭代到9

        self.start = -1

        self.end = end

    def __iter__(self):   #使他能够迭代

        return self     #返回本身

    def __next__(self):   #获取下一个next

        self.start += 1

        if self.start >= self.end:

            raise StopIteration  # raise:引发异常,中止运行

        return self.start

nu = Number()

print(next(nu))——0

for i in Number(20):     #从0迭代到19

    print(i)

8.3.3 上下文协议:with关键字的使用

只要类里面定义__enter__和__exit__这两个方法,则可以通过with去使用此对象。

例:import time

class RunTime:

    def __enter__(self):

        self.start_time = time.time()

        return self.start_time   #先赋值,再return,不能直接return赋值

    def __exit__(self,exe_type,exc_val,exc_tb):  #三个参数值exe_type,exc_val,exc_tb必写,错误类型,错误值,错误位置,记住即可

        self.end_time = time.time()

        self.run_time = self.end_time - self.start_time

        print('程序运行时间',self.run_time)

with RunTime():

    for i in range(100000):

        pass       # 不做任何事情,站位语句

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值