初学Python——面向对象(二)
一、抽象类、接口类和抽象接口
转自博客园魏恒https://www.cnblogs.com/weihengblog/p/8528967.html
(一)接口类
什么是接口类?在继承中,我们可以声明某个子类继承自某基类,这个基类是个接口类,在接口类中定义了接口名(函数名)且并未实现接口的功能,子类继承接口类,并实现接口中的功能。这又叫做“接口继承”。
接口继承实质上是规定了一个兼容接口,使得外部调用者无需关心具体细节,可一视同仁的处理实现了特定接口的所有对象”——这在程序设计上,叫做归一化。特点:1.做出良好的抽象类,2.规定兼容接口 3.调用者可以无需关心具体实现细节,可以一视同仁处理实现特定接口的所有对象。
#做出一个良好的抽象
class Payment(object):
#规定了一个兼容接口
def pay(self):
pass #微信支付
class WeChatPay(Payment):
def pay(self,money):
print('微信支付了%s'%money) #支付宝支付
class AliPay(Payment):
def pay(self,money):
print('支付宝支付了%s'%money) #苹果支付
class ApplePay(Payment):
def pay(self,money):
print('苹果支付了%s'%money) def pay(obj,money):
obj.pay(money) weixin = WeChatPay()
alipay = AliPay()
applepay = ApplePay() #调用者无需关心具体实现细节,可以一视同仁的处理实现了特定接口的所有对象
pay(weixin,100)
pay(alipay,200)
pay(applepay,300)
(二)抽象类
什么是抽象类?
与java一样,python也有抽象类的概念但是同样需要借助模块实现,抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化
为什么要有抽象类?
如果说类是从一堆对象中抽取相同的内容而来的,那么抽象类就是从一堆类中抽取相同的内容而来的,内容包括数据属性和函数属性。
比如我们有香蕉的类,有苹果的类,有桃子的类,从这些类抽取相同的内容就是水果这个抽象的类,你吃水果时,要么是吃一个具体的香蕉,要么是吃一个具体的桃子。。。。。。你永远无法吃到一个叫做水果的东西。
从设计角度去看,如果类是从现实对象抽象而来的,那么抽象类就是基于类抽象而来的。
从实现角度来看,抽象类与普通类的不同之处在于:抽象类中有抽象方法,该类不能被实例化,只能被继承,且子类必须实现抽象方法。这一点与接口有点类似,但其实是不同的
#一切皆文件
import abc #利用abc模块实现抽象类 class All_file(metaclass=abc.ABCMeta):
all_type='file'
@abc.abstractmethod #定义抽象方法,无需实现功能
def read(self):
'子类必须定义读功能'
pass @abc.abstractmethod #定义抽象方法,无需实现功能
def write(self):
'子类必须定义写功能'
pass # class Txt(All_file):
# pass
#
# t1=Txt() #报错,子类没有定义抽象方法 class Txt(All_file): #子类继承抽象类,但是必须定义read和write方法
def read(self):
print('文本数据的读取方法') def write(self):
print('文本数据的读取方法') class Sata(All_file): #子类继承抽象类,但是必须定义read和write方法
def read(self):
print('硬盘数据的读取方法') def write(self):
print('硬盘数据的读取方法') class Process(All_file): #子类继承抽象类,但是必须定义read和write方法
def read(self):
print('进程数据的读取方法') def write(self):
print('进程数据的读取方法') wenbenwenjian=Txt() yingpanwenjian=Sata() jinchengwenjian=Process() #这样大家都是被归一化了,也就是一切皆文件的思想
wenbenwenjian.read()
yingpanwenjian.write()
jinchengwenjian.read() print(wenbenwenjian.all_type)
print(yingpanwenjian.all_type)
print(jinchengwenjian.all_type)
(三)抽象类和接口类
抽象类的本质还是类,指的是一组类的相似性,包括数据属性和函数属性,而接口强调函数属性的相似性。
抽象类是一个介于类和接口直接的一个概念,同时具备类和接口的部分特征,可以用来实现归一化设计。
二、静态方法、属性方法、类方法
1.静态方法
@staticmethod
静态方法就是一个普通方法,不能访问实例变量与类变量,与类唯一的联系就是需要通过类名来调用这个方法,所以
只是名义上归类管。私有方法不能作为静态方法,但受保护类可以作为静态方法。
class Dog(object):
def __init__(self,name):
self.name = name @staticmethod # 将eat变成了静态方法,作用是将此方法断绝与类的联系,变普通函数
def eat(self):
print(" is eating") d = Dog("ChenRonghua")
d.eat()
# 这样运行会出错,要想不出错
1.调用时,d.eat(d)。已经断绝与类的联系,"self"需要手动传入
2.eat()方法去掉参数self
2.类方法
@classmethod
变成类方法后,方法内只能访问类变量,不能访问实例变量。
class Cat(object):
name = "华仔"
def __init__(self,name):
self.name = name
self.__person = None @classmethod # 类方法
def eat(self,food):
print('{0}吃{1}' .format(self.name,food)) c1 = Cat("小猫") c1.eat("鱼")
# 输出结果显示,类方法没有使用实例变量,使用的是类变量
3.属性方法
@property
可以把一个方法变成静态属性。也就是将原本的方法变成了静态属性,不能传参数,不能修改属性值,也不能删除
先来看一下
class Cat(object):
name = "华仔"
def __init__(self,name):
self.name = name
self.person = None @property
def talk(self):
print("{0} is talking with {1}".format(self.name,self.person)) c1 = Cat("小猫") c1.talk
#输出:小猫 is talking with None
这时,想要对self.person进行修改是不可以的,会报错。
若非要修改,也是可以通过特殊方法来修改的,
#在上述代码的基础上加上如下代码(在原eat方法的下面,类的里面)
@talk.setter # 修改属性方法的值需要这样做
def talk(self,person):
print("{0} is talking with {1}".format(self.name,person))
self.person = person c1.talk = "Jack"
c1.talk # 再次访问,发现真正修改了它
# 输出:
小猫 is talk with Jack
同样,若非要删除,也可以
@talk.deleter # 删除属性方法的值需要这样做
def talk(self):
del self.person
print("已删除talk") del c1.talk
c1.talk # 删除后再访问运行出错!
这时相信你会有个疑问,为什么还需要属性方法的存在呢?直接定义一个静态变量不就行了吗?属性方法和属性有什么不同呢?
属性方法的本质还是方法(函数),只是变得特殊了,我们知道属性方法具有以下两点特征:
1.属性方法内可以对内部属性进行访问
2.属性方法不能被随意修改删除,防止误改误删,保证了安全性。
在实际应用中,有这样的需求:已经写好了具有特定功能的方法,作用是返回一个数值。而要经过一系列的动作才能得到这个值,这显然不是变量可以完成的。用户调用它时只需要像对待静态变量一样就可以得到一个值,中间的过程用户不需要关心。
三、反射
在实际应用中,我们需要根据用户输入来做出相应的工作,比如输入1调用a方法,输入2调用b方法,输入2调用c方法.....,这些我们可以用if else分支语句来判断并执行,但显而易见,如果用户输入的种类非常多,if else语句的代码量就非常可观了,不美观,也不便于维护。怎么办呢?
1.需要用到反射函数hasattr()来判断对象是否有这个方法
2.如果有这个方法,则可以用getatter()函数来找到对象方法的内存地址
3.加上括号即可调用
class Dog(object):
def __init__(self,name):
self.name = name def eat(self,name):
print("{0} is eating {1}".format(self.name,name)) def bulk(self):
print("{0} is yelling".format(self.name)) d = Dog("Alex") chioce = input("请输入操作:").strip()
If hasattr(d,chioce) == True:
fun = getattr(d,chioce)
a = input("what does the dog want eating ?")
fun(a)
else:
setattr(d,chioce,bulk) # 将类外部的函数加入了类的内部
v = getattr(d,chioce)
v(d)
so,什么叫反射?通过字符串来运行或修改程序运行时的状态、属性、方法
一共有四个方法:
1.hasattr(obj,str) obj是对象,str是字符串,判断对象是否有此方法(属性),返回True或False
2.getattr(obj,str) obj是对象,str是字符串,返回对象中方法(属性)的内存地址
3.setattr(x,y,z) (x,y=z)x是对象,y是字符串,z是方法的内容,设置一个新的方法(属性),或修改方法(属性)
4.delattr(obj,str) obj是对象,str是字符串,删除属性(不能删除原有的方法?)
chioce = input("请输入操作:").strip()
setattr(d,chioce,18) # 创建属性并赋值
print(d.talk)
setattr(d,"name","Chen") # 修改已存在的name属性
print(d.name) delattr(d,"name") # 删除name属性
#print(d.name) # 报错 # 输入:talk
输出:
18
Chen
Chen is yelling
四、动态导入模块
如何使用字符串导入模块呢?
之前讲过一个方法,使用__import__()内置函数;第二个方法是动态导入模块
- __import__()内置函数
'''导入lib包,调用包下aa模块的text()函数'''
b = __import__("lib.aa")
b.aa.text()
"这是解释器内部用的,一般不建议用这个,建议用下面的"
#output:
from lib.aa.text()
'''导入lib包,调用包下aa模块的text()函数'''
b = __import__("lib.aa")
b.aa.text()
"这是解释器内部用的,一般不建议用这个,建议用下面的"
#output:
from lib.aa.text()
- 动态导入
vimport importlib
c = importlib.import_module("lib.aa")
"导入lib.aa。b 代表 lib.aa "
c.text()
#output:
from lib.aa.text()
初学Python——面向对象(二)的更多相关文章
- 初学Python(二)——数组
初学Python(二)——数组 初学Python,主要整理一些学习到的知识点,这次是数组. # -*- coding:utf-8 -*- list = [2.0,3.0,4.0] #计算list长度 ...
- python面向对象(二)——类成员
Python面向对象 类成员 1.字段 普通字段 属于对象 静态字段 属于类 2.方法 普通方法 触发者是对象 括号里至少一个参数 se ...
- python面向对象二
1.1类的静态属性,类方法,类的静态方法 1.1.1静态属性(@property) 在类中: python内置的@property装饰器就是负责把一个方法(函数)变成属性来调用. class Stud ...
- 初学Python——面向对象编程
一.面向对象 or 面向过程? 编程范式: 编程是 程序 员 用特定的语法+数据结构+算法组成的代码来告诉计算机如何执行任务的过程 , 一个程序是程序员为了得到一个任务结果而编写的一组指令的集合,正所 ...
- python 面向对象二 类和实例
一.类和实例 面向对象最重要的概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板,比如Student类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法, ...
- Python 面向对象(二) 特殊方法
一些Python特殊方法的汇总 __bases__ 类的基类,返回元祖__base__ 类的基类,也叫父类__call__ '类名()',类名加括号调用时执行的语句__class__ 对象或类 ...
- python面向对象(二)
属性查找 类有两种属性:数据属性和函数属性 1. 类的数据属性是所有对象共享的 2. 类的函数属性是绑定给对象用的 class BeijingStudent: school='Beijing' ...
- python 面向对象(二)--访问限制
在Class内部,可以有属性和方法,而外部代码可以通过直接调用实例变量的方法来操作数据,这样,就隐藏了内部的复杂逻辑. 但是,从前面Student类的定义来看,外部代码还是可以自由地修改一个实例的na ...
- python 面向对象(二)成员
##################################总结########################### 类的成员: 变量: 实例变量 对象.属性=xxx 类变量 ...
随机推荐
- angluarjs中页面初始化的时候会出现语法{{}}在页面中问题
angluarjs中页面初始化的时候会出现语法{{}}在页面中问题,也即是页面闪烁问题.出现这个的原因是:由于页面或者组件需要渲染加载数据,浏览器和angluarjs渲染页面需要消耗一定的时间,虽然这 ...
- 2018-11-27 中文代码示例之Programming in Scala笔记第七八章
续前文: 中文代码示例之Programming in Scala学习笔记第二三章 中文代码示例之Programming in Scala笔记第四五六章. 同样仅节选有意思的例程部分作演示之用. 源文档 ...
- 数据库连接池(基于MySQL数据库)
使用JDBC是怎么保证数据库客户端和数据库服务端进行连接的? 通过代码: conn=DriverManager.getConnection(url, username, password); JDBC ...
- 山东理工大学SDUT - ACM OJ 题: Python代码 及分析
Python基础语法学习完成,先刷基础题100道巩固 ,附 题目.代码.知识分析 题目:http://acm.sdut.edu.cn/onlinejudge2/index.php/Home/Index ...
- Android为TV端助力 最简单的自定义圆点view
首先创建一个选择器,用来判断圆点状态,可以根本自己的需求改 <selector xmlns:android="http://schemas.android.com/apk/res/an ...
- 添加/删除/修改Windows 7右键的“打开方式”
右键菜单添加/删除"打开方式" 此"打开方式"非系统的"打开方式",二者可以并存. 右键菜单添加"打开方式" 在HKEY ...
- C#:读取视频的宽度和高度等信息
读取方式:使用ffmpeg读取,所以需要先下载ffmpeg.网上资源有很多. 通过ffmpeg执行一条CMD命令可以读取出视频的帧高度和帧宽度信息. 如图: 蓝线框中可以看到获取到的帧高度和帧宽度. ...
- android 圆角背景
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http: ...
- (网页)习惯了CS回车操作人员,操作BS网页表单也是回车666
1.第一步把表单,里面需要回车的input,或者是其他的表单按钮给一个clsss,例如下面的$('.cls'); 2.第二步, 把下面的代码复制过去,填写完最后一个自动提交:$("#sav ...
- 关于ARM CM3的启动文件分析
下面以ARM Cortex_M3裸核的启动代码为例,做一下简单的分析.首先,在启动文件中完成了三项工作: 1. 堆栈以及堆的初始化 2. 定位中断向量表 3. 调用Reset Handler. ...