面向对象
2018-01-24 18:54:29 53 举报
AI智能生成
Python之面向对象
作者其他创作
大纲/内容
面向对象进阶
反射
反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。
面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
四个可以实现自省的函数
getattr(object, name[,default])
获取对象object的属性或者方法,如果存在打印出来,如果不存在,打印出默认值,默认值可选。
需要注意的是,如果是返回的对象的方法,返回的是方法的内存地址,如果需要运行这个方法,
可以在后面添加一对括号。
需要注意的是,如果是返回的对象的方法,返回的是方法的内存地址,如果需要运行这个方法,
可以在后面添加一对括号。
hasattr(object, name)
判断一个对象里面是否有name属性或者name方法,返回BOOL值,有name特性返回True, 否则返回False。
需要注意的是name要用括号括起来
需要注意的是name要用括号括起来
setattr(object, name, values)
给对象的属性赋值,若属性不存在,先创建再赋值。
delattr
(object, name) 删除一个变量,删除指定对象的指定名称的属性,和setattr函数作用相反,当属性不存在的时候,会报错,不能删除对象的方法。
在删除时,注意作用域。对象的属性里没有可以去找类的属性,但不能去object这个父类找
双下方法
内置的类方法 和 内置的函数之间有着千丝万缕的联系
__str__
内建函数str()和repr() (representation,表达,表示)或反引号操作符(``)可以方便地以字符串的方式获取对象的内容、类型、数值属性等信息。str()函数得到的字符串可读性好(故被print调用)
__repr__
repr()函数得到的字符串通常可以用来重新获得该对象,通常情况下 obj==eval(repr(obj)) 这个等式是成立的。
__str__和__repr__小结
子主题
__del__
析构方法,当对象在内存中被释放时,自动触发执行。
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,
所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
__call__
Python中的__call__允许程序员创建可调用的对象(实例),默认情况下, __call__()方法是没有实现的,这意味着大多数实例是不可调用的。然而,如果在类定义中覆盖了这个方法,那么这个类的实例就成为可调用的。
a = A('alex')() #后面的括号可以直接让__call__(self)函数执行
初识面向对象
面向过程VS面向对象
面向过程
面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西。
优点
极大的降低了写程序的复杂度,只需要顺着要执行的步骤,堆叠代码即可。
缺点
一套流水线或者流程就是用来解决一个问题,代码牵一发而动全身。
应用场景
一旦完成基本很少改变的场景,著名的例子有Linux內核,git,以及Apache HTTP Server等。
面向对象
面向对象的程序设计的核心是对象(上帝式思维),要理解对象为何物,必须把自己当成上帝,上帝眼里世间存在的万物皆为对象,不存在的也可以创造出来。
优点
解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易。
缺点
可控性差,无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法预测最终结果。于是我们经常看到一个游戏人某一参数的修改极有可能导致阴霸的技能出现,一刀砍死3个人,这个游戏就失去平衡。
应用场景
需求经常变化的软件,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都是面向对象的程序设计大显身手的好地方。
初识类和对象
类
类型的本质就是类。
两种作用
属性引用
类名.属性
实例化
类名加括号就是实例化,会自动触发__init__函数的运行,可以用它来为每个实例定制自己的特征
实例化的过程就是类——>对象的过程
关于self:
在实例化时自动将对象/实例本身传给__init__的第一个参数,可以是其他名字,但默认都是这个,要不然其他人会不认识的。
类属性的补充
在python中,用变量表示特征,用函数表示技能,因而具有相同特征和技能的一类事物就是‘类’,对象是则是这一类事物中具体的一个。
对象
python中一切皆为对象,对象是关于类而实际存在的一个例子,即实例。
对象/实例只有一种作用:属性引用
小结
类命名空间与对象、实例的命名空间
创建一个类就会创建一个类的名称空间,用来存储类中定义的所有名字,这些名字称为类的属性
静态属性
静态属性就是直接在类中定义的变量
其中类的数据属性是共享给所有对象的
动态属性
动态属性就是定义在类中的方法
而类的动态属性是绑定到所有对象的
创建一个对象/实例就会创建一个对象/实例的名称空间,存放对象/实例的名字,称为对象/实例的属性
只能在对象或实例中的名称空间里找动态属性,找不到就到类中的名称空间里找,找不到就报错,不会在类外面找。
面向对象的用法
组合
组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合
当类之间有显著不同,并且较小的类是较大的类所需要的组件时,用组合比较好
人狗大战
计算圆环的周长和面积
教授的生日和课程
面向对象的三大特性
继承
继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类
继承:是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构。
python中类的继承分为:单继承和多继承
一个类 可以被多个类继承,一个类 可以继承多个父类
python3中,都是新式类,没有继承父类默认继承 object
先抽象再继承
抽象即抽取类似或者说比较像的部分。
抽象最主要的作用是划分类别
抽象只是分析和设计的过程中,一个动作或者说一种技巧,通过抽象可以得到类
用已经有的类建立一个新的类,这样就重用了已经有的软件中的一部分设置大部分,大大省了编程工作量,这就是常说的软件重用,不仅可以重用自己的类,也可以继承别人的,比如标准库,
来定制新的数据类型,这样就是大大缩短了软件开发周期,对大型软件开发来说,意义重大.
派生
子类也可以添加自己新的属性或者在自己这里重新定义这些属性(不会影响到父类),需要注意的是,一旦重新定义了自己的属性且与父类重名,那么调用新增的属性时,就以自己为准了。
通过继承建立了派生类与基类之间的关系,它是一种'是'的关系,比如白马是马,人是动物。
当类之间有很多相同的功能,提取这些共同的功能做成基类,用继承比较好,比如教授是老师
抽象类与接口类
接口类
继承有两种用途
一:继承基类的方法,并且做出自己的改变或者扩展(代码重用)
二:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,并且实现接口中的功能
例子
抽象类
抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化
抽象类的本质还是类,指的是一组类的相似性,包括数据属性(如all_type)和函数属性(如read、write),而接口只强调函数属性的相似性。
抽象类是一个介于类和接口直接的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计
在抽象类中,我们可以对一些抽象方法做出基础实现;
而在接口类中,任何方法都只是一种规范,具体的功能需要子类实现
而在接口类中,任何方法都只是一种规范,具体的功能需要子类实现
接口隔离原则:
使用多个专门的接口,而不使用单一的总接口。即客户端不应该依赖那些不需要的接口。
使用多个专门的接口,而不使用单一的总接口。即客户端不应该依赖那些不需要的接口。
方法的实现
在抽象类中,我们可以对一些抽象方法做出基础实现;
而在接口类中,任何方法都只是一种规范,具体的功能需要子类实现
而在接口类中,任何方法都只是一种规范,具体的功能需要子类实现
钻石继承
继承顺序
当类是经典类时,多继承情况下,会按照深度优先方式查找
当类是新式类时,多继承情况下,会按照广度优先方式查找
名词解析
抽象:抽象即抽取类似或者说比较像的部分。是一个从具题到抽象的过程。
继承:子类继承了父类的方法和属性
派生:子类在父类方法和属性的基础上产生了新的方法和属性
小结
多态
多态指的是一类事物有多种形态。Python3天生支持多态。
鸭子类型
封装
隐藏对象的属性和实现细节,仅对外提供公共访问方式。
好处
1. 将变化隔离
2. 便于使用
3. 提高复用性
4. 提高安全性
封装原则
将不需要对外提供的内容都隐藏起来
把属性都隐藏,提供公共方法对其访问
私有变量和私有方法
在python中用双下划线开头的方式将属性隐藏起来(设置成私有的)
这种自动变形的特点:
1.类中定义的__x只能在内部使用,如self.__x,引用的就是变形的结果。
2.这种变形其实正是针对外部的变形,在外部是无法通过__x这个名字访问到的。
3.在子类定义的__x不会覆盖在父类定义的__x,因为子类中变形成了:_子类名__x,而父类中变形成了:_父类名__x,即双下滑线开头的属性在继承给子类时,子类是无法覆盖的。
这种变形需要注意的问题
这种机制也并没有真正意义上限制我们从外部直接访问属性,知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了,如a._A__N
变形的过程只在类的内部生效,在定义后的赋值操作,不会变形
私有方法
在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的
封装与扩展性
封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码;而外部使用用者只知道一个接口(函数),只要接口(函数)名、参数不变,使用者的代码永远无需改变。这就提供一个良好的合作基础——或者说,只要接口这个基础约定不变,则代码改变不足为虑。
总结
接口类 抽象类
python中没有接口类,有抽象类,abc模块中的metaclass = ABCMeta,@abstructmethod
本质是做代码规范用的,希望在子类中实现和父类方法名字完全一样的方法
两者有什么区别
区别
多态和鸭子类型
多态 —— python天生支持多态
鸭子类型 —— 不依赖父类的情况下实现两个相似的类中的同名方法
封装 —— 私有的
小结
0 条评论
下一页