[python全栈]03.面向对象(3)

目录

  1. 封装
  2. 多态
  3. 多继承
  4. 继承的MRO问题
  5. 函数重写
面相对象的编程语言的特征 :
	C++ / Java / Python / Swift / c#
特征 :
	1.继承
	2.封装
	3.多态

1. 封装

封装 enclosure :
	封装是指隐藏类的实现细节,让使用者不用关心这些细节
	封装的目的是让使用者尽可能少的使用实例变量(属性)进行操作
私有属性 :
	python类中,以双下划线'__'开头,不以双下划线结尾的标识符为私有成员
	在类的外部无法直接访问
eg:
class A :
	def __init__(self):
		self.__p1 = 100	#__p1为私有属性,在类的外部不可调用
	def test(self):
		print(self.__p1)
		self.__m1()
	def __m1(self):
		print('我是类内的__m1方法')	
a = A()
print(a.__p1)	#>>>AttributeError: 'A' object has no attribute '__p1'
a.test()	#p1=100 ;  我是类内的__m1方法
a.m1()	#>>>AttributeError: 'A' object has no attribute '__m1'

2. 多态

多态 polymorphic :
	多态是指在继承/派生关系的类中
	调用基类对象的方法,实际能调用子类的覆盖版本方法的现象叫做 多态
说明 :
	多态调用的方法与对象相关,不与类型相关
	python的全部对象都只有'运行时状态(动态)'
	没有'C++/Java'里的'编译时状态(静态)'
eg:
class Shape :
	def draw(self):
		print('Shape.draw被调用')
class Point(Shape):
	def draw(self):
		print('正在画一个点')
class Circle(Point):
	def draw(self):
		print('正在画一个圆')
def my_draw(s):
	s.draw()	#调用方法由 s 的类决定(动态决定)
s1 = Circle()
s2 = Point()
my_draw(s1)	#调用Circele里的draw
my_draw(s2)	#调用Point里的draw

3. 多继承

!!!尽量少使用多继承(仅 C++ Python 支持)!!!
--------------------------------------------------
多继承 multiple inheritance :
	多继承是指一个子类继承自两个或两个以上的基类
语法 :
	class 类名(基类名1,基类名2,......):
		语句块
说明 :
	1.一个子类同时继承自多个父类
		父类中的方法可以同时被继承下来	
	2.如果两个父类中有同名方法
		而在子类中又没有覆盖此方法时,调用结果难以确定
多继承的问题(缺陷) :
	标识符(名字空间冲突的问题),要谨慎使用多继承
eg:
class Car :
	def run(self,speed):
		print('以',speed,'km/h速度行驶')
class Plane :
	def run(self,speed):
		print('飞机以',speed,'km/h速度滑动')
	def fly(self,height):
		print('飞到了海拔',height,'米')
class PlaneCar(Car,Plane):
	''' 同时继承 Car 和 Plane'''
p1 = PlaneCar()
p1.fly(10000)	#>>>飞到了海拔 10000 米
p1.run(300)	
#此时 p1.run()不能确定调用哪个,以继承列表内顺序为准(Car,Plane)

4. 继承的MRO问题

继承的MRO (Merhod Resolution Order) 问题 :
	类内的 __mro__ 属性用来记录继承方法的查找顺序
eg:
class A :
	def m(self):
		print('A.m')
class B(A):
	def m(self):
		print('B.m')
		super().m()
class C(A):
	def m(self):
		print('C.m')
class D(B,C):
        def m(self):
                print('C.m')
                super().m()
d = D()
print(D.__mro__)
#>>>(<class '__main__.D'>, <class '__main__.B'>, 
	<class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
d.m() #>>>C.m;B.m;C.m 多继承中 suoper()是按照 __mro_顺序查找

练习 :

''' 已知list列表内没有insert_head方法,写一个自定义的类Mylist
	继承自list类,在Mylist类内添加'''

class Mylist(list):
        def insert_head(self,value):
         '''将value插入到列表的开始处'''
                self[:0] = [value]
                #self.insert(0,value)
L = Mylist(range(1,5))
print(L)
L.insert_head(0)
print(L)		

5. 函数重写

函数重写 override :
	重写是在自定义的类内添加相应的方法,让自定义的类生成的对象(实例)
	像内建对象一样进行内建的函数操作
对象转字符串的函数重写 :
	repr(object) 返回一个能代表此对象的 '表达式字符串',
	通常: eval(repr(obj)) == obj
	str(obj)	通过给定的对象返回一个字符串
对象转字符串函数重写方法 :
	repr() 函数的重写方法 :
		def __repr__(self):
			return 能表达self内容的字符串,eval()可执行字符串
		str()函数的重写方法 :
		def __str__(self):
			return 人能看懂的字符串
说明 :
	1.str(obj)函数优先调用obj.__str__()方法返回字符串
	2.如果obj没有__str__()方法,则调用obj.__repr__()方法返回字符串
	3.如果obj没有__repr__()方法,则调用object类的__repr__()实例方法
		显示<xxxx>格式的字符串			
eg:#自定义的类使用内建函数进行操作
class MyNumber:
    def __len__(self):
        return 100
n1 = MyNumber()
x = len(n1)	#相当于调用了 return n1.__len__()
print(x)	#>>> 100

eg:示例 repr()和str()
class MyNumber:
	def __init__(self,value):
		self.data = value
	def __str__(self):
		return "数字:%d" % self.data
	def __repr__(self):
		return "Mynumber(%d)" % self.data	    
n1 = MyNumber(100)
print(str(n1))	#>>>数字:100
print(repr(n1))	#>>>Mynumber(100)
数值转换函数的重写 :
	def __complex__(self)	complex(obj)函数调用
	def __int__(self)		int(obj)函数调用
	def __float__(self)		float(obj)函数调用
	def __bool__(self)		bool(obj)函数调用
eg:#示例数值转换
class MyNumber:
	def __init__(self,v):
		self.data = v
	def __repr__(self):
		return "MyNumber(%d)" % self.data
	def __int__(self):
		return int(v)
n1 = MyNumber(100)
print(type(n1))	#>>><class '__main__.MyNumber'>
n1 = int(n1)	#>>>TypeError

内建函数的重写
	__abs__()		abs(obj)
	__len__()		len(obj)
	__reversed__()	reversed(obj)
	__round__()		round(obj)
eg:#自定义类MyList 与系统内建类一样,用来保存任意类型数据
class MyList :
    def __init__(self, iterator=[]):
        self.data = [x for x in iterator]
    def __repr__(self):
        return "MyList(%r)" % self.data
    def __abs__(self):
        return MyList((abs(x) for x in self.data))
    def __len__(self):
        return len(self.data  )     
myl = MyList([1,-2,3,-4])
print(myl)
print(abs(myl))	#>>>MyList([1, 2, 3, 4])
myl2 = MyList(range(10))
print(myl2)
print('myl2的长度是:',len(L2))
布尔测试函数的重写 :
	格式  def __bool__(self):
作用 :
	用于bool(obj)函数取值
	用于if语句真值表达式中
	用于while语句真值表达式中					...
说明:
	1.优先调用__bool__方法取值
	2.如果不存在__bool__方法,则用__len__() 方法取值后判断是否为零值
		如果不为零返回True,否则返回False
	3.	如果再没有__len__方法,则直接返回True
迭代器(高级)
  什么是迭代器
    可以通过next(it) 函数取值的对象就是迭代器
  迭代器协议:
    迭代器协议是指对象能够使用next函数获取下一项数据,在没有下一项数据时触发一个StopIterator来终止迭代的约定
    
  实现方法:
    类内需要有 __next__(self) 方法来实现迭代器协议
  语法形式:
    class MyIterator
        def __next__(self) :
            迭代器协议的实现
            return 数据
  
  什么是可迭代对象
     是指能用iter(obj) 函数返回迭代器的对象(实例)
     可迭代对象内部一定要定义__iter__(self)方法来返回迭代器

  可迭代对象的语法形式:
    class MyIterable:
        def __iter__(self):
            语句块
            return 迭代器 	  
eg:
class MyList:
	def __init__(self,iterator):
		self.data = list(iterator)
	def __repr__(self):
		return 'MyList(%r)' % self.data
	def __iter__(self):
		print('__iter__方法被调用')
		return MyListIterator(self.data)
class MyListIterator:
	''' 此类用来创建一个迭代器对象,
	用此迭代器对象可以访问MyList类型的数据'''
	def __init__(self,iter_data):
		self.cur = 0	#设置迭代器的初始值为0代表列表下标
		#it_data 绑定要迭代的列表
		self.it_data = iter_data
	def __next__(self):
		''' 有next方法的对象才叫迭代器
			此方法一定要实现迭代器协议'''
			#如果self.cur已经超出列表索引范围就报迭代结束
		if self.cur >= len(self.it_data):
			raise StopIteration
		r = self.it_data[self.cur]
		self.cur += 1
		return r
myl = MyList([2,3,5,7])
print(myl)
for x in myl:
	print(x)

练习 :

写一个类,Fibonacci 实现迭代器协议,此类的对象可以作为可迭代对象生成相应的斐波那契数
     1 1 2 3 5 8 ....
    class Fibonacci:
        def __init__(self, n):
           ...
    实现如下操作:
    for x in Fibonacci(10):
        print(x)
    L = [ x for x in Fibonacci(30)]
    print(sum(Fibonacci(25)))
      (需要实现迭代器协议)
提示: 可以用一个类来实现,也可以用两个类实现
    class Fibonacci:
        def __init__(self, n):
           ...
        def __iter__(self):
            ....
        def __next__(self):
            ....
class Fibonacci:
    def __init__(self, n):
        self.__count = n
    def __iter__(self):
        return FiboIterator(self.__count)
class FiboIterator:
    def __init__(self, n):
        self.__count = n
        self.cur_count = 0
        self.a = 0  # 用来保存前第二个数
        self.b = 1  # 用来保存前一个数
    def __next__(self):
        if self.cur_count >= self.__count:
            raise StopIteration
        self.cur_count += 1  # 生成数加1
        self.a, self.b = self.b, self.a + self.b
        return self.a

for x in Fibonacci(10):
    print(x)

L = [x for x in Fibonacci(30)]
print(L)
print(sum(Fibonacci(25)))

#方法二
class Fibonacci:
    def __init__(self, n):
        self.__count = n
    def __iter__(self):
        self.cur_count = 0
        self.a = 0  # 用来保存前第二个数
        self.b = 1  # 用来保存前一个数
        return self
    def __next__(self):
        if self.cur_count >= self.__count:
            raise StopIteration
        self.cur_count += 1  # 生成数加1
        self.a, self.b = self.b, self.a + self.b
        return self.a

for x in Fibonacci(10):
    print(x)

L = [x for x in Fibonacci(30)]
print(L)
print(sum(Fibonacci(25)))             

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值