python3基础19

day19
类的函数 issubclass(子类, 父类) 判断一个类是否继承自其他的类
封装  (以__开头的属性为私有属性)
多态(只有动态没有静态)
面向对象的三大特征
多继承
多继承的问题(标识符冲突)
多继承的 MRO(Method Resolution Order)问题
(__mro__用来记录类的方法查找顺序)
函数重写 overwrite
对象转字符串函数 1.repr(x)  2. str(x)
               覆盖父类继承 __repr__,__str__
               重新定义新的__repr__,__str__方法

对象转字符串的重写方法:
      repr() 函数的重写方法:
          def __repr__(self):
            return 字符串
      str()函数重写方法:
          def __str__(self):
          return 字符串

内建函数重写(len, abs, reversed, round)
数值转换函数(int, complex, bool, float)
对象属性管理函数
   eg:
      class Dog:
         pass
      d = Dog()
      setattr(d, 'color', '白色')  #等同于d.color = '白色'
      hasattr(d, 'kins')    #False  判断有没有相应的属性
      getattr(d, 'color')   #'白色'
      getattr(d, 'kinds')  #报错
      getattr(d, 'kinds', '没有这个属性')  #没有这个属性
      delattr(d, 'color')  等同于del d.color
      dir(d)
迭代器:
class MyList:

    def __init__(self, iterable=()):
        self.data = [x for x in iterable]

    def __repr__(self):
        return 'MyList(%s)' % self.data

    def __iter__(self):
        '''此方法用于返回一个能访问self对象的迭代器'''
        print('__iter__被调用')
        return MyListIterator(self.data)  #创建迭代器并返回

class MyListIterator:
    '''此类用来描述能够访问MyListIterator类型的对象的迭代器'''
    def __init__(self, lst):
        self.data_lst = lst
        self.cur_index = 0  #迭代器访问起始位置

    def __next__(self):
        '''此方法用来实现迭代器协议'''
        print("__next__方法被调用")
        if self.cur_index >= len(self.data_lst):
            raise StopIteration

        r = self.data_lst[self.cur_index]
        self.cur_index += 1
        return r
  
############################################################
day19笔记

用于类的函数
  issubclass(cls,class__or__tuple)
  判断一个类是否继承自其他的类.如果此类cls是class或tuple中一个派生子类则返回True,否则返回False

示例:
class A:
    pass

class B(A):
    pass

class C(B):
    pass

issubclass(C,B)  #True
issubclass(B,A)  #True
issubclass(C,A)  #True
issubclass(A,C)  #False

issubclass(bool, int)  #True


封装 enclosure

 封装是指隐藏类的实现细节,让使用者不关心这些细节
 封装的目的是让使用者通过尽可能少的方法(或属性)操作对象

私有属性和方法
 python类中,以双下划线('__')开头,不以双下划线结尾的标识符
 为私有成员,私有成员只能使用该类的方法来进行访问和修改

 1.以__开头的属性为私有属性
 2.以__开头的方法为私有方法


示例见:enclosure.py

#此示例示意用私有属性和私有方法来实现封装
class A:
    def __init__(self):
        self.__p1 = 100  #p1为私有属性  等同于self._A__p1
        # self._p2 = 200
        # self.__p2__ = 200
    def show_info(self): 
        self.__p1 = 200        
        print(self.__p1) #此对象的实例方法可以访问和修改私有属性4
        self.__m()  #实例方法调用私有方法 5
    def __m(self):
        print("A类对象的__m方法被调用") #6

a = A()  #创建对象a        2
a.show_info()  #200        3
a.__m()  #出错,除A类的实例方法外,不能调用a对象的私有方法

# print(a.__p1)  #不允许访问私有属性,只能用实例方法来访问

# print(a._p2)   #非双下划线开头,可以访问非私有属性
# print(a.__p2__)  #只是双下划线开头的是私有属性

注: python的封装是假的封装(模拟的封装)


多态 polymorphic

 字面意思:'多种状态'
 多态是指有继承和派生关系的类中,调用基类对象的方法,实际能调动子类的覆盖方法的现象叫做多态

 状态:
  静态(编译时状态)----->>  python无静态
  动态(运行时状态)

 说明:
  1.多态调用方法与对象相关,不写类型相关
  2.pyhthon全部对象都只有'运行时状态(动态)'
    没有'C++语言'里的编译时状态(静态)
  

面向对象编程语言的特征:
  继承
  封装
  多态(执行子类覆盖版本的内容)


多继承 multipe inheritance

 多继承是指一个子类继承自两个或两个以上的基类

 语法:
  class 类名(基类名,基类名2,.....)
 说明:
  一个子类同时继承自多个父类,父类的方法可以同时被继承下来
  如果两个父类中有同名的方法,而在子类中又没有覆盖此方法,调用
  结果难以确定

 示例见:
  multipe_inherit.py

#此示例示意多继承
class Car:
    '''汽车类'''
    def run(self, speed):
        print('汽车以', speed, '公里/小时速度行驶')

class Plane:
    '''飞机类'''
    def fly(self, height):
        print('飞机以海拔', height, '米的高度飞行')

class PlaneCar(Car, Plane):
    '''PlaneCar类同时继承自汽车类和飞机类'''
p = PlaneCar()
p.fly(10000)
p.run(300)


 注:python中尽量使用单继承,避免使用多继承

多继承的问题(缺陷)
 标识符冲突的问题(要谨慎使用多继承)
 
 示例见:
  multipe_inherit2.py

#小张写了一个类A:
class A:
    def m(self):
        print("A.m()被调用")

#小李写了一个类B:
class B:
    def m(self):
        print("B.m()被调用")

#小王干觉小张和小李写的两个类自己都可以用
class AB(A, B):
    def m(self):
        print("AB.m()被调用")
ab = AB()
ab.m()  #请问调用谁?为什么?


多继承的 MRO(Method Resolution Order)问题
  pyhotn3的类的__mro__属性
    作用: 用来记录类的方法查找顺序

  示例见:
    mro.py

#菱形继承
class A:
    def go(self):
        print("A")
class B(A):
    def go(self):
        print("B")
        super().go()  #打印C     
class C(A):
    def go(self):
        print('C')
        

class D(B, C):
    def go(self):
        print("D")
        super().go()  #调用基类B
d = D()
d.go()


super()函数就是根据__mro__来调用上层的方法


练习一:
  写一个农民类,Peasant ,有方法:
      def farm(self, plant):
      ....
  写一个工人类Worker,有方法:
      def work(self, that):
      ....
  创建一个农民工为MigrantWorker,让此类的对象拥有上面两个类的全部方法

  person = MigrantWorker()
  person.farm('水稻') #正在种植水稻
  person.work('汽车') #正在制造汽车

  查看各个类的__mro__属性

函数重写 overwrite
 什么是函数重写
   在自定义的类内添加相应的方法,让自定义的类创建的实例能够
   使用内建函数进行操作


对象转字符串函数

 repr(x) 返回一个能够表示python对象的表达式字符串,通常
  eval(repr(obj)) == obj
 str(x) 通过给定的对象返回一个字符串(这个字符串通常供人阅读)

示例:
 s = 'I'm a Teacher'
 print(str(s))   #I'm a Teacher  #人可阅读的字符串
 print(repr(s))  #"I'm a Teacher" --->python语言识别的字符串

对象转字符串的重写方法:
  repr() 函数的重写方法:
      def __repr__(self):
        return 字符串
  str()函数重写方法:
      def __str__(self):
        return 字符串

str(obj)函数调用方法说明:
  1.str(obj) 函数先查找obj.__str__(方法),调用此方法返回结果
  2.如果obj.__str__()
    方法不存在,则调用obj.__repr__方法并返回结果
  3.如果obj.__repr__方法不存在,则调用objice类的__repr__实例显示
    <__main__.XXXX object at 0xXXXXXXX> 格式的字符串

示例见:
  mynumber.py


#此示例示意对象转字符串函数的重写方法
class Mynumber:

    def __init__(self, val):
        self.data = val   #在每个对象内部创建一个实例变量来绑定数据
    
    def __str__(self):
        print("__srt__方法被调用")
        return '自定义数字:%d' % self.data
    
    def __repr__(self):
        '''此方法返回的字符串一定是能表示self对象的表达式字符串'''
        print("__repr__方法被调用")
        return '自定义数字:%d' % self.data

n1 = Mynumber(100)
print("str(n1) =", str(n1))  #自定数字:100
#str(n1)等同于 n1.__str__()
print("repr(n1) =", repr(n1))  # Mynumber(100)  
#调用objice内的__repr__方法

n2 = Mynumber(200)
print("str(n2) =", str(n2))
#等同于
print(n2.__str__())
print(n2)   #在print内部会将n2用str(x)转为字符串在写到sys.stdout


内建函数重写
 方法名                    函数名

def __abs__(self):     abs(obj)  函数调用
def __len__(self):     len(obj)  函数调用
def __reversed__(self):     reverised(obj)  函数调用
def __round__(self):     round(obj)  函数调用

示例见:
 len_overwrite.py
class MyList:
    '''这是一个自定义的列表类型,
    此类型的对象用data属性绑定的列表来存储数据'''
    def __init__(self, iterable=()):
        self.data = [x for x in iterable]
    def __repr__(self):
        return 'MyList(%s)' % self.data
    def __len__(self):
        return len(self.data)
    def __abs__(self):
        # L = []
        # for x in self.data:
        #     x = abs(x)
        #     L.append(x)
        L = [abs(x) for x in self.data]
        return MyList(L)


myl = MyList([1, -2, 3, -4])
print(myl)  #MyList([1, -2, 3, -4])
print(len(myl)) #4   #len(L)  相当于 L.__len__()
print(abs(myl))  #MyList([1, 2, 3, 4])


数值转换函数的重写:
   方法名                    函数名
 def __complex__(self):   complex(obj) 函数调用
 def __int__(self):       int(obj) 函数调用
 def __float__(self):     float(obj) 函数调用
 def __bool__(self):      bool(obj) 函数调用

示例见:mynumber3.py


#此示例示意数值转化的重写 
class Mynumber:

    def __init__(self, val):
        self.data = val   #在每个对象内部创建一个实例变量来绑定数据

    
    def __repr__(self):
        print("__repr__方法被调用")
        return 'Mynumber:%d' % self.data

    def __int__(self):
        '''重写int(obj)函数'''
        return int(self.data)

    def __float__(self):
        print("__float__")
        return float(self.data)

n1 = Mynumber(100)
n = int(n1)
print(n)   #100
f = float(n1)
print(f)  #100.0

c = complex(n1) #当没有n1.__complex__()时会调用n1.__float__()
print(c)


布尔测试函数的重写
 格式:
  def __bool__(self):
     ...
 作用:
   用于bool(obj)函数取值
   用于if 语句真值表达式
   用于while语句的真值表达式
 说明:
  1.当自定义类内有__bool__(self)方法时,此方法返回作为bool(x)
    的返回值
  2.当不存在__bool__(self)方法时,返回__len__(self)
    方法返回值是否为非零来测试布尔值
  3.当不存在__len__(self)方法时,则直接返回True

示例:
  bool.py

class MyList:

    def __init__(self, iterable=()):
        self.data = [x for x in iterable]

    def __repr__(self):
        return 'MyList(%s)' % self.data

    def __len__(self):
        print("__len__方法被调用")
        return len(self.data)
    def __bool__(self):
        print('__bool__方法被调用')
        for x in self.data:
            if x:
                return True
        return False
        # return any(self.data)

myl = MyList([False, 0, 0.0])
print(bool(myl))
if myl:
    print(myl, '的布尔值为True')
else:
    print(myl, '的布尔值为False')

    

对象的属性管理函数:
  getattr(obj, name[,defalut])
  从一个对象用字符串name得到对象的属性,getattr(x, 'y')
  等同于x.y;当属性不存在时,如果给定defalut参数则返回defalut,
  如果没有给出defalut,则触发一个AttributeError错误

  hasattr(obj, name)
  用给定的name字符串返回obj是否有此属性,此种做法可以避免在getattr(obj, name)时引发错误

  setattr(obj, name, value)
  给对象obj的名为name的属性设置相应的值value, setattr(x, 'y', v)
  等同于 x.y = v

  delattr(obj, name)删除对象obj中的name属性del(x, 'y')
  等同于 del x.y


示例:
class Dog:
    pass
d = Dog()
setattr(d, 'color', '白色')  #等同于d.color = '白色'
hasattr(d, 'kins')    #False  判断有没有相应的属性
getattr(d, 'color')   #'白色'
getattr(d, 'kinds')  #报错
getattr(d, 'kinds', '没有这个属性')  #没有这个属性
delattr(d, 'color')  等同于del d.color
dir(d)


迭代器(高级)
 什么是迭代器?
  由iter(x) 函数返回,可以通过next(it)函数取值的对象就是迭代器


 迭代器协议:
   迭代器协议是指对象能够使用next()函数获取下一项数据,在没有下一项数   据时触发一个StopIteration异常来终止迭代的约定

 迭代器协议的实现方法:
   def __next__(self):
    ...
   注:此方法需要实现迭代器协议

 什么是可迭代对象?
   是指能用iter(obj) 函数返回迭代器的对象(实例)
   可迭代对象内部要定义__iter__(self)方法来返回迭代器对象
 示例见:
   myiterator.py  

#此示例示意将自定义的类MyList创建的对象成为可迭代对象
class MyList:

    def __init__(self, iterable=()):
        self.data = [x for x in iterable]

    def __repr__(self):
        return 'MyList(%s)' % self.data

    def __iter__(self):
        '''此方法用于返回一个能访问self对象的迭代器'''
        print('__iter__被调用')
        return MyListIterator(self.data)  #创建迭代器并返回

class MyListIterator:
    '''此类用来描述能够访问MyListIterator类型的对象的迭代器'''
    def __init__(self, lst):
        self.data_lst = lst
        self.cur_index = 0  #迭代器访问起始位置

    def __next__(self):
        '''此方法用来实现迭代器协议'''
        print("__next__方法被调用")
        if self.cur_index >= len(self.data_lst):
            raise StopIteration

        r = self.data_lst[self.cur_index]
        self.cur_index += 1
        return r


myl = MyList([2, 3, 5, 7])
it = iter(myl)   #等同于调用 it = myl.__iter__()
print(next(it))
print(next(it))
print(next(it))
print(next(it))

for x in myl:
    print(x)

L = [x**2 for x in myl]
print(L)

课后练习:
 1.实现原学生信息管理系统Student类的封装,让除Student实例方法
   外的函数或其它方法都不能访问姓名,年龄,成绩等属性

 2.写一个实现迭代器协议的类,让此类可以生成从b开始n个素数
  class Prime:
     def __init__(self, b, n):
      ...
     def __iter__(self):
      ...
     def __next__(self):
      ...

  L = [x for x in Prime(10, 4)]
  print(L)   #L = [11, 13, 17, 19]

 3.写一个类Fibonacci实现迭代器协议,此类的对象可以作为可迭代对象生成斐波那契数名
   1 1 2 3 5 8 13 .....
  class Fibonacci:
      def __init__(self, n):
         ...
      ...
    for x in Fibonacci(10):
        print(x)  #打印1 1 2 3 5 8 13....


 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值