python 多态、多继承、函数重写、迭代器
用于类的函数 issubclass(cls,class_or_tuple)
判断一个类是否继承自其他的类,如果此类cls是class或tuole中的一个派生(子类)则返回True,否则返回False
封装 enclosure
封装的目的是让使用者尽可能少的引用实例变量(属性)进行操作
私有属性:python类中,以双下划线‘__’开头,不以双下划线结尾的标识符为私有成员,在类的外部无法直接访问。
class A:
def __init__(self):
self.__p1 = 100 #__p1为私有属性,在类的外部不可访问 def test(self):
print(self.__p1) # 可以访问
self.__m1() # A类的方法可以调用A类的私有方法 def __m1(self):
'''我是私有方法,只有我自己的类中的方法才能调用我哦'''
print("我是A类的__m1方法!") a = A() # 创建对象
# print(a.__p1) # 在类外看不到__p1属性,访问失败!
a.test()
# a.__m1() # 出错.无法调用私有方法
__私有属性
多态 polymorphic
多态是指在继承\派生关系的类中,调用基类对象的方法,实际能调用子类的覆盖版本方法的现象叫多态
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() # 此处显示出多态中的动态 s1 = Circle()
s2 = Point()
my_draw(s1) # 调用Circle里的draw 正在画一个圆
my_draw(s2) # 调用Point里的draw 正在画一个点
多态
多继承 multiple inheritance
多继承是指一个子类继承自两个或两个以上的基类
说明:一个子类可以同时继承自多个父类,父类中的方法可以同时被继承下来。如果两个父类中有同名的方法,而在子类中又没有覆盖此方法时,调用结果难以确定
class Car:
def run(self, speed):
print("汽车以", speed, '公里/小时的速度行驶') class Plane:
def fly(self, height):
print("飞机以海拔", height, '的高度飞行') class PlaneCar(Car, Plane):
'''PlaneCar同时继承自汽车类和飞机类''' p1 = PlaneCar()
p1.fly(10000)
p1.run(300)
多继承
多继承的问题(缺陷):名字冲突问题,要谨慎使用多继承(会先使用第一个继承的基类)
class A:
def m(self):
print("A.m()被调用") class B:
def m(self):
print('B.m()被调用') class AB(A, B):
pass ab = AB()
ab.m() # A.m()被调用
命名冲突
继承的MRO(Method Resolution Order)问题
类的__mro__属性用来记录继承方法的查找顺序
class A:
def m(self):
print("A.m")
class B(A):
def m(self):
print("B.m")
class C(A):
def m(self):
print("C.m")
class D(B, C):
'''d类继承自B,C'''
def m(self):
print("D.m")
d = D()
print(D.__mro__)
#(<class '__main__.D'>,
# <class '__main__.B'>,
# <class '__main__.C'>,
# <class '__main__.A'>,
# <class 'object'>)
d.m() # 调用方法的顺序如上所示
多继承顺序
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")
super().m()
class D(B, C):
'''d类继承自B,C'''
def m(self):
print("D.m")
super().m()
d = D()
d.m() # 调用方法的顺序是什么? for x in D.__mro__:
print(x) # D.m
# B.m
# C.m
# A.m
# <class '__main__.D'>
# <class '__main__.B'>
# <class '__main__.C'>
# <class '__main__.A'>
# <class 'object'>
多继承顺序
函数重写
在自定义类内添加相应的方法,让自定义类创建的实例能像内建对象一样进行内建函数操作
对象转字符串函数:
repr(obj) 返回一个能代表此对象的表达式字符串,通常eval(repr(obj))==obj (这个字符串通常是给python解释执行器运行用的)
对象转字符串函数的重写方法
reper(obj)函数的重写方法: def__repr__(self):
return 能够表达self内容的字符串
str(obj)函数的重写方法: def__str__(self):
return 人能看懂的字符串
class MyNumber:
def __init__(self, value):
self.data = value
def __str__(self):
print("__str__被调用")
return "数字: %d" % self.data
def __repr__(self):
print("__repr__被调用")
return 'MyNumber(%d)' % self.data
n1 = MyNumber(100)
# print(str(n1)) # 调用 n1.__str__(self);__str__被调用;数字: 100
# print(repr(n1)) #__repr__被调用 MyNumber(100)
print(n1) # ;__str__被调用;数字: 100
# n2 = eval("MyNumber(100)")
# print(n2) #__str__被调用;数字: 100
重写方法
说明:
1、str(obj)函数先调用obj.__str__()方法,调用此方法并返回字符串
2、如果obj没有__str__()方法,则调用obj.__repr__()方法返回的字符串
3、如果obj没有__repr__()方法,则调用object类的__repe__()实例方法显示<xxxx>格式的字符串
数值转换函数的重写
def __complex__(self) complex(obj) 函数调用
def __int__(self) int(obj) 函数调用
def __float__(self) float(obj) 函数调用
def __bool__(self) bool(obj) 函数调用
'''此示例示意自定义的类MyNumber能够转成为数值类型'''
class MyNumber:
def __init__(self, v):
self.data = v
def __repr__(self):
return "MyNumber(%d)" % self.data
def __int__(self):
'''此方法用于int(obj) 函数重载,必须返回整数
此方法通常用于制订自义定对象如何转为整数的规则
'''
return 10000 n1 = MyNumber(100)
print(type(n1))
# if n1 == 100:
# print("n1 == 100")
n = int(n1)
print(type(n))
print(n)
自定义类可以转成数值类型
<class '__main__.MyNumber'>
<class 'int'>
10000
结果
内建函数的重写
__abs__ abs(obj)
__len__ len(obj)
__reversed__ reversed(obj)
__round__ round(obj)
# 自定义一个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])
# 上一句语句可以用如下生成表达式代替已防止过多占内存
return MyList((abs(x) for x in self.data)) def __len__(self):
# return self.data.__len__()
return len(self.data) myl = MyList([1, -2, 3, -4])
print(myl)
print(abs(myl)) # MyList([1, +2, 3, +4])
print("原来的列表是:", myl) myl2 = MyList(range(10))
print(myl2)
print('myl2的长度是:', len(myl2))
print('myl的长度是: ', len(myl))
MyList([1, -2, 3, -4])
MyList([1, 2, 3, 4])
原来的列表是: MyList([1, -2, 3, -4])
MyList([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
myl2的长度是: 10
myl的长度是: 4
结果
布尔测试函数的重写
格式 def __bool__(self):
...
作用:
用于bool(obj) 函数取值
用于if语句真值表达式中
用于while语句真值表达式中
说明:
1. 优先调用__bool__方法取值
2. 如果不存在__bool__方激动 ,则用__len__()方法取值后判断是否为零值,如果不为零返回True,否则返回False
3. 如果再没有__len__方法,则直接返回True
class MyList:
'''自定义列表类'''
def __init__(self, iterator=[]):
self.data = [x for x in iterator] def __repr__(self):
return "MyList(%r)" % self.data def __bool__(self):
print("__bool__方法被调用!")
return False # def __len__(self):
# print("__len__被调用")
# return len(self.data) myl = MyList([1, -2, 3, -4])
print(bool(myl)) # False
if myl:
print("myl 是真值")
else:
print("myl 是假值")
__bool__方法被调用!
False
__bool__方法被调用!
myl 是假值
结果
迭代器(高级)
可以通过next(it) 函数取值的对象就是迭代器
迭代器协议:迭代器协议是指对象能够使用next函数获取下一项数据,在没有下一项数据时触发一个StopIterator来终止迭代的约定
实现方法:类内需要有 __next__(self) 方法来实现迭代器协议
语法形式:
class MyIterator
def __next__(self):
迭代器协议的实现
return 数据
可迭代对象是指能用iter(obj) 函数返回迭代器的对象(实例),可迭代对象内部一定要定义__iter__(self)方法来返回迭代器
可迭代对象的语法形式:
class MyIterable:
def __iter__(self):
语句块
return 迭代器
# 此示例示意可迭代对象和迭代器的定义及使用方式:
class MyList:
def __init__(self, iterator):
'''自定义列表类的初始化方法,此方法创建一个data实例
变量来绑定一个用来存储数据的列表'''
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):
'''有此方法的对象才叫迭代器,
此方法一定要实现迭代器协议'''
print("__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) # 此处可以这样做吗? # it = iter(myl)
# x = next(it)
# print(x)
# x = next(it)
# print(x)
# x = next(it)
# print(x)
MyList([2, 3, 5, 7])
__iter__方法被调用!
__next__方法被调用!
2
__next__方法被调用!
3
__next__方法被调用!
5
__next__方法被调用!
7
__next__方法被调用!
结果
python 多态、多继承、函数重写、迭代器的更多相关文章
- python -- 面向对象编程(继承、重写)
一.继承 子类可以继承父类的所有公有成员,但不能直接访问父类的私有成员,只能通过父类的公有方法间接访问私有属性或私有方法. 如: class DerviedClassName(BaseClassNam ...
- python: 多态与虚函数;
通过python的abc模块能够实现虚函数: 首先在开头from abc import ABCMeta, abstractmethod 例子 : #!/usr/bin/python #coding ...
- c++中的函数重载、函数重写、函数重定义
目录 一.函数重载 二.函数重写 三.函数重定义 为了更加深刻的理解 函数重载.重写.重定义,我们可以带着如下这两个问题去思考: 1.子类中是否可以定义父类中的同名成员?为什么? 可以,因为子类与父类 ...
- Python全栈工程师(多继承、函数重写)
ParisGabriel 每天坚持手写 一天一篇 决定坚持几年 为了梦想为了信仰 开局一张图 Python人工智能从入门到精通 补充: 对象 --------- ...
- Python面向对象:继承和多态
继承与多态简介: 继承可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写. 动态语言的鸭子类型特点决定了继承不像静态语言那样是必须的. ...
- Python入门之面向对象的多态和继承
本章内容 Python面向对象的多态和继承对比 ========================================= 在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的 ...
- python入门18 继承和多态
继承:子类继承父类的属性和方法 class 子类名(父类1,父类2) 多态:子类重写父类的方法 判断对象是否是某个类的实例: isinstance(object,class) 父类-汽车类 #co ...
- 【转载】 C++多继承中重写不同基类中相同原型的虚函数
本篇随笔为转载,原文地址:C++多继承中重写不同基类中相同原型的虚函数. 在C++多继承体系当中,在派生类中可以重写不同基类中的虚函数.下面就是一个例子: class CBaseA { public: ...
- [转]Java中继承、多态、重载和重写介绍
什么是多态?它的实现机制是什么呢?重载和重写的区别在那里?这就是这一次我们要回顾的四个十分重要的概念:继承.多态.重载和重写. 继承(inheritance) 简单的说,继承就是在一个现有类型的基础上 ...
随机推荐
- Redis之hash数据结构实现
参考 https://www.cnblogs.com/ourroad/p/4891648.html https://blog.csdn.net/hjkl950217/article/details/7 ...
- hihocode 股票价格 优先队列+map
股票价格 时间限制:20000ms 单点时限:2000ms 内存限制:256MB 描述 小Hi最近在分析一支股票的价格走势,他需要一个程序来辅助分析.这个程序会接收3种消息(指令): 价格信息,格式是 ...
- 朴素贝叶斯 Naive Bayes
2017-12-15 19:08:50 朴素贝叶斯分类器是一种典型的监督学习的算法,其英文是Naive Bayes.所谓Naive,就是天真的意思,当然这里翻译为朴素显得更学术化. 其核心思想就是利用 ...
- Java Spring-Bean
2017-11-06 18:59:30 Bean初始化和销毁方法 配置初始化和销毁的方法:* init-method=”setup”* destroy-method=”teardown”执行销毁的时候 ...
- netty做集群 channel共享 方案
netty做集群 channel如何共享? 方案一: netty 集群,通过rocketmq等MQ 推送到所有netty服务端, channel 共享无非是要那个通道都可以发送消息向客户端, MQ广播 ...
- eclipse SVN 上传.so库文件
eclipse SVN提交代码的时候,是自动忽略.so库文件的.用下面所说的操作后,.so库文件右下角的图标会变成一个蓝色的+号的图标,这样就可以提交.so文件了 选择要上传的.so文件,右键 ——& ...
- python中多线程
多线程 什么是多线程 开启线程的两种方式 进程和线程的区别 Thread对象的其他属性和方法 守护线程 死锁现象与递归锁 信号量.Event定时器 线程Queue 进程池和线程池 什么是多线程 在传统 ...
- CF1076E:Vasya and a Tree(DFS&差分)
Vasya has a tree consisting of n n vertices with root in vertex 1 1 . At first all vertices has 0 0 ...
- POJ1651 Multiplication Puzzle【区间DP】
LINK 每次删除一个数,代价是左右两边相邻的数的当前数的积 第一个和最后一个数不能删除 问最后只剩下第一个数的最后一个数的最小代价 思路 很简单的DP 正着考虑没有办法确定两边的数 那么就把每个区间 ...
- POJ3177 Redundant Paths【tarjan边双联通分量】
LINK 题目大意 给你一个有重边的无向图图,问你最少连接多少条边可以使得整个图双联通 思路 就是个边双的模板 注意判重边的时候只对父亲节点需要考虑 你就dfs的时候记录一下出现了多少条连向父亲的边就 ...