OOP 面向对象
-
面向对象的特性
- 封装
- 封装就是对对象的成员进行访问限制
- 封装的三个级别
- 公开:public
- 受保护的: protected
- 私有的:private
- public protected private 不是关键字
- 判断对象的位置
- 对象内部
- 对象外部
- 子类中
- 私有:
- 私有成员是最高级别的封装,只能在当前类或对象中访问
- 在成员变量前面加上两个下划线即可
- Python的私有不是真私有,是一种成为name mangling的改名策略,可以使用_clasname__attributeName进行访问
- 受保护的封装 protected
- 受保护的封装是将对象成员进行一定级别的封装,然后在类中或者子类中都可以进行访问,但是外部不可以
- 封装方法:在成员名称前添加一个下划线即可
- 公开的 共有的 public
- 公共的封装实际对成员没有操作,没有任何的访问限制
class Person(): #name是公有变量 name = "liuyun" #age是私有变量 __age = 18 p = Person() print(p.name) print(p._Person__age)
- 继承
- 继承就是一个类可以获得另一个类中成员属性和成员方法
- 作用:减少代码,增加代码的服用功能。同时可以设置类与类之间的关系
- 继承与被继承的概念:
- 被继承的类叫父类,也叫基类,也叫超类
- 用于继承的类叫子类,也叫派生类
- 继承与被继承一定存在一个is-A的关系
- 继承的特征
- 所有的类都继承自object类,即所有的类的父类都是object
- 子类一旦继承父类,则可以使用父类中除私有成员外的所有内容
- 子类继承父类后并没有将父类成员赋值到子类中,而是通过引用关系进行调用
- 子类中可以定义多有的成员属性和方法
- 子类中定义的成员和父类成员如果相同,则优先使用子类成员
- 子类如果想扩充父类的方法,可以在定义新方法的同时访问父类成员来进行代码重用,可以使用 父类名.父类成员 的格式来调用父类成员,也可以使用super(),父类成员的格式来调用
- 继承变量函数的查找顺序问题
- 优先查找自己的变量
- 没有则查找父类
- 构造函数如果本类中没有定义,则自动查找父类的构造函数,如果本类中有,则不想上查找
- 构造函数
- 是一类特殊的函数,在类进行实列化之前进行调用
- 如果定义了构造函数,则实列化时使用构造函数,不向上查找父类的构造函数
- 如果没有定义,则向上查找父类的构造函数
- 如果子类没有定义,父类的构造函数带有参数,则构造对象是参数应该按父类的构造函数的参数进行传值
- super
- super不是一个关键字,而是一个类
- super 的作用是获取MRO(MethodResolustionOrder)列表中的第一个类
- super于父类直接没任何实质的关系,但通过super可以调用到父类
#继承语法 # 在python中,任何一个类都有一个共同的父类叫object class Person(): name = "NoName" age = 0 _petname = "sec" # 小名 是保护的,子类可以用,但不能公开 __score = 0 #成绩 私有的,只能自己使用 def sleep(self): print("Slesping......") def work(self): print("make some money....") #父类写在括号中 class Teacher(Person): teacherId = "9527" name = "dana" #子类扩充父类的功能,只需要调用父类的功能 def work(self): # 方法一 Person.work(self) # 方法二 super().work() print("attention") pass t = Teacher() print(t.work()) print(t.name) print(t.age) print(t.sleep())
# 构造函数 class Animal(): pass class Mammal(Animal): #多个参数的构造函数 def __init__(self,type): print("i am mammal{0}".format(type)) class Dog(Mammal): #__init__ 就是构造函数 # 在实列化的时候,第一个被自动调用 # 主要的工作是进行初始化 def __init__(self): print("i am init in dog") class Cat(Mammal): pass zongzi = Dog() tiger = Cat("cat")
- 封装
-
面向对象编程
- 基础
- 公有私有
- 继承
- 组合、Minxi
-
魔法函数
- 魔法函数概述
- 构造类魔法函数
- 运算类魔法函数
1. 面向对象概述(ObjectOriented OO)
- OOP思想
- 首先接触任意一个任务,首先想到的是任务这个世界的构成,是由一个一个的模型构成的
- 名词解释
- OO:面向对象
- OOA: 面向对象的分析
- OOD: 面向对象的设计
- OOI: xxx的实现
- OOP: xxx的编程
- OOA-->OOD-->OOI:面向对象的实现过程
- 任何一个事物的名词都具有属性
2. 类和对象的概念
- 类: 抽象名词,代表一个集合,共性的事物
- 对象:具象的事物,单个个体
- 类与对象的关系
- 一个具象,代表一类事物的某一个个体
- 一个抽象,代表的是一大类事物
- 类中的内容,应该具有两个内容
- 表明事物的特征,叫做属性(变量)
- 表明事物功能或动作,成为成员方法(函数)
3.类的基本实现
命名规则(遵循命名规则)
-
声明
- 必须使用class关键字
- 类由属性和方法构成,其他不允许出现(保存其纯洁性)
- 成员属性定义可以直接使用变量赋值,如果没有值,可以使用None
- 案列 01.py
-
实例化类
变量 = 类名()
-
访问成员属性/方法
- obj.成员属性名称
- boj.成员方法
-
可以通过默认内置变量检查类和对象的所有成员
- 对象所有成员检查
# dict 前后各有两个下划线 boj.__dict__
- 类所有成员
# dict 前后各有两个下划线 class_name.__dict__
# 定义一个学生类
class Student():
# 定义一个类,pass标识直接跳过
pass
#定义一个对象
mingyue = Student()
class PythonStudent():
name = None
age = 19
course = "Python"
def doHomeWork(self):
print("我在做作业!")
# 建议所有的方法都提供返回值,哪怕没有返回的值
# 直接用return None
return None
# 实列一个学生
yueyue = PythonStudent()
print(yueyue.name)
print(yueyue.age)
yueyue.doHomeWork()
为不影响环境的纯洁性,使用anaconda进行虚拟环境的管理
- conda env list :虚拟环境列表
- conda create -n xxx pythone=3.6 (创建一个python版本为3.6 名称为xxx的虚拟环境)
- source activate oop: (激活虚拟环境)
- source deactivate:反激活(关闭)虚拟环境()在当前虚拟环境下
4.类和对象的成员分析
- 类和对象都可以存储成员,成员可以归类所有,也可以归对象所有
- 类存储成员时使用的是与类关联的一个对象
- 对象存储成员是存储在当前对象中
- 创建对象的时候,类中的成员不对放入实列中去,而是得到一个空对象,没有成员
- 类实列属性和对象的实列的属性在不对其进行赋值的时候,其指向的是同一块内存。如果实列的值进行变化,那么他的值归于该实列的独立空间中
- 就是在类(对象)中如果属性有默认值,那么在初次实列对象的时候。实列的属性也具有默认值,这个时候对象属性和实列属性所指向的是同一片内存空间
- 如果实列中属性的值产生变换,那么属性就将指向该实列自己的内存空间中
5.关于self
- self:在对象的方法中标识当前对象本身,如果通过对象调用一个方法,那么该对象会自动传入到当前方法的第一个参数中 相当于java类中的this
- self不是一个关键字,只是一个用于接收对象的普通参数,理论上可以用任何一个普通变量名代替
- 方法中的self形参的方法成为非绑定类的方法,可以通过对象方位,没有self的是绑定类的方法,只能通过类访问
- 使用类访问绑定类的方法时,如果类方法中需要访问当前类的成员,可以通过class成员名来访问
class A():
name = "aaa"
age = 0
def __init__(self):
name = "bbb"
age = 19
def say(self):
print(self.name)
print(self.age)
class B():
name = "ccc"
age = 11
a = A()
# 此时,系统会默认的把a最为一个参数传入到self中
a.say()
# 鸭子模型
# 此时,self被a替换,如果是类名来调用类中的函数,那么就必须传入一个和该对象有相同属性的对象
A.say(a)
A.say(A)
A.say(B)