Python基础第20天

点点圈 提交于 2020-03-23 06:04:00

                                                                                  面向对象进阶

一:isinstance(obj,cls)和issubclass(sub,super)

  1.    isinstance(obj,cls)检查是否obj是否是类 cls 的对象
class Foo:
    pass
f1=Foo()
print(isinstance(f1,Foo))

      2.   issubclass(sub, super)检查sub类是否是 super 类的派生类

class Foo:
    pass
f1=Foo()
print(isinstance(f1,Foo))

class Bar(Foo):
    pass

b1=Bar()
print(issubclass(Bar,Foo))
print(isinstance(b1,Foo))
print(type(b1))  #<class '__main__.Bar'>

二:getattribute

class Foo:
    def __init__(self,x):
        self.x=x

    def __getattr__(self, item):
        print('执行的是getattr')
    def __getattribute__(self, item):
        print('执行的是getattribute')
        raise AttributeError('抛出异常了')


f1=Foo(10)
f1.xxxxx
f1.x

属性有没有都会触发getattribute,当由于raise AttributeError('抛出异常了'),使得触发getattr

当__getattribute__与__getattr__同时存在,只会执行__getattrbute__,除非__getattribute__在执行过程中抛出异常AttributeError

三:item方法

  • __getitem__
  • __setitem__
  • __delitem__
class Foo:
    def __getitem__(self, item):
        print('getitem',item)
        return self.__dict__[item]

    def __setitem__(self, key, value):
        print('setitem')
        self.__dict__[key]=value


    def __delitem__(self, key):
        print('delitem')
        self.__dict__.pop(key)

f1=Foo()
# print(f1.__dict__)
f1['name']='egon'
f1['age']=18
print(f1.__dict__)
#
del f1['name']
print(f1.__dict__)
print(f1['age'])

item 方法适用于字典触发,而  .形式适用于attr属性触发方法

四:改变对象的字符串显示

class Foo:
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def __str__(self):  #str(f1)-->f1.__str__,print()触发
        return '名字是%s  年纪是%s'%(self.name,self.age)  #自己控制打印信息

f1=Foo('egon',18)
print(f1)  #<__main__.Foo object at 0x005B2510>;名字是egon  年纪是18
class Foo:
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def __str__(self):
        return '这是str'
    def __repr__(self):  #repr(f1)-->f1.__repr__,应用在解释器中
        return '名字是%s  年纪是%s'%(self.name,self.age)  #自己控制打印信息

f1=Foo('egon',18)
print(f1)  #str(f1)--->f1.__str__()---->f1.__repr___()

__str__ :由print触发 ===》obj.__str__()

__repr__:使用于交互式解释器====》obj.__repr__()

如果__str__没有定义,就使用__repr__来代替输出

notice : 这两种方法返回值必须是字符串,否则抛出异常

自定制格式化方法format

x='{0}{0}{0}'.format('dog')
print(x)#dogdogdog
class Data:
    def __init__(self,year,mon,day):
        self.year=year
        self.mon=mon
        self.day=day

d1=Data(2017,3,12)
x='{0.year}{0.mon}{0.day}'.format(d1)   #d1.format
y='{0.year}:{0.mon}:{0.day}'.format(d1)
z='{0.year}-{0.mon}-{0.day}'.format(d1)
print(x)
print(y)
print(z)#20173122017:3:12

  2017-3-12

format_dic={
    'ymd':'{0.year}{0.mon}{0.day}',
    'm-d-y':'{0.mon}{0.day}{0.year}',
    'y:m:d':'{0.year}{0.mon}{0.day}',
}
class Data:
    def __init__(self,year,mon,day):
        self.year=year
        self.mon=mon
        self.day=day
    def __format__(self, format_spec):
        print('我执行啦')
        print('--->',format_spec)
        if not format_spec or format_spec not in format_dic:
            format_spec='ymd'
        fm=format_dic[format_spec]
        return fm.format(self)
d1=Data(2017,3,12)
print(format(d1,'ymd'))
print(format(d1,'m-d-y'))
print(format(d1,'m:d:y'))
print(format(d1,'m-d:y'))

五:__slots__   :定义类变量,效果由类产生的属性不在具有__dict__属性

    属性很少的类,但是实例很多,为了节省内存可以使用__slots__取代实例的__dict__

class Foo:
    __slots__=['name','age']#  属性字典的形式{'name':None,'age':None}
    __slots__ = 'name'  # {'name':None,'age':None}

f1=Foo()
# print(f1.__dict__)  #报错,取消了__dict__
print(f1.__slots__)  #['name', 'age']

f2=Foo()
print(f2.__slots__)
f2.name='alex'
f2.age=19
print(f2.name)
print(f2.age)
#f1与f2都没有属性字典__dict__了,统一归__slots__管,节省内存

六:

1.  __doc__  改属性无法被继承,文档注释

class Foo:
    '我是描述信息'
    pass
print(Foo.__doc__)

class Foo:
    '我是描述信息'
    pass

class Bar(Foo):
    pass
print(Bar.__doc__)  #改属性无法继承给子类
print(Foo.__doc__)

2.  __module__表示当前操作的对象在那个模块

    __class__表示当前操作的对象的类是什么

from lib.aa import C
c1=C()
print(c1.name)
print(c1.__module__)
print(c1.__class__)

#aa.py
class C:
    def __init__(self):
        self.name='SB'

3.   __del__析构方法  当对象在内存中被释放时,自动触发执行,只在实例被删除时触发

class Foo:
    def __init__(self,name):
        self.name=name

    def __del__(self):
        print('wozhixing')

f1=Foo('alex')
# del f1
# print('---------------->')  #先执行后打印  



del f1.name  #只有实例被删除时才触发,所以先打印,然后再删除 这里的实例是f1
print('---------------->')  #先打印后删除

4.    __call__对象后面加括号,触发执行

class Foo:
    def __call__(self, *args, **kwargs):
        print('实例执行啦')

f1=Foo()
f1()  #Foo下的__cal__
Foo()#abc下的__cal__

5.   迭代器协议

class Foo:
    def __init__(self,n):
        self.n=n
    def __iter__(self):  #把一个对象变成可迭代对象
        return self

    def __next__(self):
        if self.n == 13:
            raise StopIteration('终止了')
        self.n+=1
        return self.n


f1=Foo(10)
print(iter(f1))
#第一种方法
for i in f1:  #f1.__iter__() == iter(f1)
    print(i)
    
 #第二种方法:  
print(f1.__next__())
print(f1.__next__())
print(f1.__next__())
print(f1.__next__())

例子:菲波那切数列实现

class Fib:
    def __init__(self):
        self._a=1
        self._b=1

    def __iter__(self):
        return self
    def __next__(self):
        if self._a > 100:
            raise StopIteration('终止了')
        self._a,self._b=self._b,self._a + self._b
        return self._a

f1=Fib()
print(next(f1))
print(next(f1))
print(next(f1))
print(next(f1))
print(next(f1))
print(next(f1))
print('==================================')
for i in f1:
    print(i)#

1
2
3
5
8
13
==================================
21
34
55
89
144

 

 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!