python学习笔记6:OOP
2018-12-28 18:29
204 查看
1. 面向对象概述(ObjectOriented,OO)
- OOP思想 接触到任意一个任务,首先想到的是任务这个世界的构成,是由模型构成的
-
OO:面向对象
-
类:抽象名词,代表一个集合,共性的事物
-
表明事物的特征,叫做属性(变量)
2.类和对象的所有成员
-
可以通过默认内置变量 _dict_ 检查类和对象的所有成员
对象所有成员:在未对类成员进行赋值时,无相应成员
dana = Stu()
dana.dict#此时无数据
dana.name = "dana"
dana.dict #此时数据为:{'name': 'yueyue'} - 类所有的成员:classname._dict\
3. 类和对象的成员分析
- 类和对象都可以存储成员,类存储成员时使用的是与类关联的一个对象, 独享存储成员是是存储在当前对象中
- 对象访问一个成员时,如果对象中没有该成员,尝试访问类中的同名成员,
如果对象中有此成员,一定使用对象中的成员 - 创建对象的时候,类中的成员不会放入对象当中,而是得到一个空对象,没有成员
- 通过对象对类中成员重新赋值或者通过对象添加成员时,对应成员会保存在对象中,而不会修改类成员
4. 关于self
- 不管类中方法有没有参数--study(),第一个参数的名字是什么--study(course),调用时都第一个参数都传入self
- self在对象的方法中表示当前对象本身,如果通过对象调用一个方法,那么该对象会自动传入到当前方法
的第一个参数中 (不论第一个参数是什么名字) - self并不是关键字,只是一个用于接受对象的普通参数,理论上可以用任何一个普通变量名代替
- 方法中有self的方法成为非绑定类的方法,可以通过对象访问, 没有self的是绑定类的方法,
只能通过类访问 - 使用类访问绑定类的方法时, 如果类方法中需要访问当前类的成员,可以通过 _class_成员名来访问
class Teacher(): name = "dana" age = 19 def say(self): self.name = "yaona" self.age = 17 print("My name is {0}".format(self.name)) # 调用类的成员变量需要用 __class__ print("My age is {0}".format(__class__.age)) def sayAgain(): print(__class__.name) print(__class__.age ) print("Hello, nice to see you again") t = Teacher() t.say() # 调用绑定类函数使用类名 Teacher.sayAgain()
5. 面向对象的三大特性
- 封装:对对象的成员进行访问控制
- 继承
- 多态
5.1 封装
-
封装的三个级别:
公开,public - 受保护的,protected
- 私有的,private
- python中public,private,protected不是关键字
-
对象内部:私有
-
公共的封装实际对成员没有任何操作,任何地方都可以访问
受保护的封装(用的较少)
受保护的封装是将对象成员进行一定级别的封装,然后在类中或者子类中都可以进行访问,但是在外部不可以
class Person(): # name是共有的成员 name = "liuying" # _nick_name就是保护成员 _nick_name = 18 # __age就是私有成员 __age = 18
私有
-
私有成员是最高级别的封装,只能在当前类或对象中访问
在成员前面添加两个两个下划线即可
class Person(): # name是共有的成员 name = "liuying" # __age就是私有成员 __age = 18
可以使用对象._classname_attributename访问
5.2 继承
-
被继承的类叫父类,也叫基类,也叫超类
-
所有的类都继承自object类,即所有的类都是object类的子类
# 父类 def work(self): print("make some money") def work(self): # 扩充父类的功能只需要调用父类相应的函数 #Person.work(self) # 扩充父类的另一种方法 # super代表得到父类 super().work() self.make_test() t = Teacher() t.work()
super
-
super不是关键字, 而是一个可以获取父类的类
继承和变量函数的查找顺序问题
-
优先查找自己的变量,没有则查找父类, 如果本类有定义,则不在继续向上查找
-
是一类特殊的函数,在类进行实例化之前进行调用
class PaxingAni(Animel): def __init__(self, name): print(" Paxing Dongwu {0}".format(name)) class Cat(PaxingAni): pass # 此时,由于Cat没有构造函数,则向上查找 # 因为PaxingAni的构造函数需要两个参数,实例化的时候给了一个,报错 c = Cat() c = Cat("cat")
-
单继承和多继承的优缺点
单继承: 传承有序,逻辑清晰,语法简单,隐患少 - 功能不能无限扩展,只能在当前唯一的继承链中扩展
-
优点:类的功能扩展方便
-
多个子类继承自同一个父类,这些子类由被同一个类继承,于是继承关系图形成一个菱形图谱
5.3 多态
- 多态就是同一个对象在不同情况下有不同的状态出现
- python中多态不是语法,是一种设计思想
- 多态性: 一种调用方式,不同的执行效果
- 多态: 同一事物的多种形态,动物分为人类,狗类,猪类
-
Mixin设计模式
主要采用多继承方式对类的功能进行扩展 - Mixin概念
- MRO and Mixin
- Mixin模式
- Mixin MRO
- MRO
-
首先他必须表示某一单一功能,而不是某个物品
-
使用Mixin可以在不对类进行任何修改的情况下,扩充功能
class TeacherMixin(): def work(self): print("Work") class StudentMixin(): def study(self): print("Study") # 助教既有教学,也有学习 class TutorM(Person, TeacherMixin, StudentMixin): pass tt = TutorM() print(TutorM.__mro__) print(tt.__dict__) print(TutorM.__dict__)
6.类相关函数
- issubclass:检测一个类是否是另一个类的子类
- isinstance:检测一个对象是否是一个类的实例
- hasattr:检测一个对象是否由成员xxx
- getattr: get attribute--Student.getattr(name)
- setattr: set attribute
- delattr: delete attribute
- dir: 获取对象的成员列表 dir(Stu)
7.类的成员描述符
- 类的成员描述符是为了在类中对类的成员属性进行相关操作而创建的一种方式 实际上是定义几个函数专门进行处理,相当对传入的参数做特定的处理,可参考help(property) get: 获取属性的操作
- set:修改或者添加属性操作
- delete: 删除属性的操作
-
使用类实现描述器(待补充
-
类的方式: 适合多个类中的多个属性共用用一个描述符
# peroperty案例 # 定义一个Person类,具有name,age属性 # 对于任意输入的姓名,我们希望都用大写方式保存 # 年龄,我们希望内部统一用整数保存 # x = property(fget, fset, fdel, doc) class Person(): # 函数的名称可以任意 def fget(self): return self._name * 2 def fset(self, name): # 所有输入的姓名以大写形式保存 self._name = name.upper() def fdel(self): self._name = "NoName" name = property(fget, fset, fdel, "对name进行下操作")
8. 类的内置属性
__dict__:以字典的方式显示类的成员组成 __doc__: 获取类的文档信息 __name__:获取类的名称,如果在模块中使用,获取模块的名称 __bases__: 获取某个类的所有直接父类,以元组的方式显示 **__mro__显示家族谱**
9. 类的常用魔术方法:(魔法函数)
- 魔术方法就是不需要人为调用的方法,基本是在特定的时刻自动触发
- 魔术方法的统一的特征,方法名被前后各两个下滑线包裹
- 操作类
__init__
: 构造函数 __new__
: 对象实例化方法,在构造函数之前执行,此函数较特殊,一般不需要使用__call__
: 对象 当函数使用 的时候触发a = A() a()
__str__
: 当对象被当做字符串使用的时候调用 :print(a)__repr__
: 返回字符串,函数str() 用于将值转化为适于人阅读的形式,而repr() 转化为供解释器读取的形式,某对象没有适于人阅读的解释形式的话,str() 会返回与repr(),所以print展示的都是str的格式
__set__
__get__
__delete__
__getattr__: 访问一个不存在的属性时触发
__setattr__: 对成员属性进行设置的时候触发 参数: self用来获取当前对象
__gt__: 进行大于判断的时候触发的函数 参数:gt(self,obj) self
10. 类和对象的三种方法
- 实例方法 需要实例化对象才能使用的方法,使用过程中可能需要借助对象的其他对象的方法完成
-
不需要实例化,类方法的第一个参数,一般命名为cls,区别于self
-
不需要实例化:不需要用第一个参数表示自身或者类
#三种方法的案例 class Person: # 实例方法 def eat(self): print(self) print("Eating.....") #类方法 # 类方法的第一个参数,一般命名为cls,区别于self @classmethod def play(cls): print(cls) print("Playing.....") # 静态方法 # 不需要用第一个参数表示自身或者类 @staticmethod def say(): print("Saying....") yueyue = Person() # 实例方法 yueyue.eat() Person.eat(Person)#必须传入self # 类方法 Person.play() yueyue.play() #静态方法 Person.say() yueyue.say()
11. 抽象类
- 抽象方法:没有具体实现内容的方法成为抽象方法,要求之类必须实现: @abc.abstractmethod def fun(self):pass
- 抽象方法的主要意义是规范了子类的行为和接口
-
抽象类的使用需要借助abc模块
import abc
- 抽象类:包含抽象方法的类叫抽象类,通常成为ABC类
-
抽象类的使用:class Human(metaclass=abc.ABCMeta):
抽象类可以包含抽象方法,也可以包含具体方法 - 抽象类中可以有方法也可以有属性
- 抽象类不允许直接实例化
- 必须继承才可以使用,且继承的子类必须实现所有继承来的抽象方法
- 假定子类没有是现实所有继承的抽象方法,则子类也不能实例化
- 抽象类的主要作用是设定类的标准,以便于开发的时候具有统一的规范
# 抽象类的实现 import abc #声明一个类并且指定当前类的元类 class Human(metaclass=abc.ABCMeta): # 定义一个抽象的方法 @abc.abstractmethod def smoking(self): pass # 定义类抽象方法 @abc.abstractclassmethod def drink(): pass # 定义静态抽象方法 @abc.abstractstaticmethod def play(): pass def sleep(self): print("Sleeping.......") class Stu(Human): def smoking(self): pass def drink(): pass def play(): pass pass aa =Stu() aa.sleep()
12. 自定义类
- 类其实是一个类定义和各种方法的自由组合
- 可以定义类和函数,然后自己通过类直接赋值
- 可以借助于MethodType实现
- 借助于type实现
- 利用元类实现- MetaClass 元类是类
- 备用来创造别的类
相关文章推荐
- python学习笔记-2(OOP)
- Python学习笔记(6)——OOP_1
- Python学习笔记(7)——OOP_2
- Python学习笔记——函数
- python学习笔记(2)——list&tuple
- opencv_python学习笔记十七
- python 学习笔记
- 《Python 黑帽子》学习笔记 - 网络基础2- Day 3
- python学习笔记二
- python学习笔记7.5-内建模块struct
- python学习笔记——第三章 字符串
- [简明python教程]学习笔记2014-05-04
- Think Python 学习笔记6:有返回函数 迭代
- python 基础学习笔记1
- python学习笔记——多进程中共享内存Value & Array
- Python学习笔记 协程
- Python学习笔记——判断语句和循环语句
- python自学习笔记
- Python学习笔记四
- python爬虫学习笔记4:信息提取