0. OOP-Python面向对象
- Python面向对象
面向对象编程
- 基础
- 公有私有
- 继承
- 组合,Mixin
魔法函数
- 魔法函数概述 - 构造类魔法函数 - 运算类魔法函数
1. 面向对象概述(ObjectOriented, OO)
OOP思想
- 接触到任意一个任务,首先想到的是任务这个世界的构成,是由模型构成的
几个名词
- OO:面向对象
- OOA:面向对象的分析
- OOD:面向对象的设计
- OOI:面向对象的实现
- OOP:面向对象的编程
- OOA->OOD->OOI:面向对象的实现过程
类和对象的概念
- 类:抽象名词,代表一个集合,共性的事物
- 对象:具象的东西,单个个体
类跟对象的关系
- 一个具象,代表一类事物的某一个个体 - 一个是抽象,代表的是一大类事物
类中的内容,应该具有两个内容
- 表明事物的特征。叫做属性(变量)
- 表明事物功能或动作,称为成员方法(函数)
2. 类的基本实现
类的名字
- 遵守变量命名的规范
- 大驼峰(有一个或者多个单词构成,每个单词首字母大写,单词跟单词直接相连)
- 尽量避开跟系统命名相似的命名
如何声明一个类
- 必须用class关键字
- 类由属性和方法构成,其他不允许使用
- 成员属性定义可以直接使用变量赋值,如果没有值,允许使用None
- 案例 01.py
实例化类
变量 = 类名() # 实例化了一个对象
访问对象成员
- 使用点操作符
obj.成员属性名称
obj.成员方法
- 使用点操作符
可以通过默认内置变量检查类和对象的所有成员
对象所有成员检查
dict前后各有两个下划线
obj.__dict__
类所有的成员
dict前后各有两个下划线
class_name.__dect__
3. anaconda基本使用
- anaconda主要是一个虚拟环境管理器
- 还是一个安装包管理器
- conda list: 显示anaconda安装的包
- conda env list:显示anaconda的虚拟环境列表
- conda create -n xxx python=3.6 :创建python版本为3.6的虚拟环境,名称为xxx
4. 类和对象的成员分析
- 类和对象都可以存储成员,成员可以归类所有,也可以归对象所有
- 类存储成员时使用的是与类关联的一个对象
- 对象存储成员是存储在当前对象中
- 对象访问一个成员时,如果对象中没有该成员,尝试访问类中的同名成员
如果对象中有此成员,一定使用对象中的成员 - 创建对象的时候,类中的成员不会放入对象当中,而是得到一个空对象,没有成员
- 通过对象对类中成员重新赋值或者通过对象添加成员时,对应成员会保存在对象中,
而不会修改类成员
5.关于self
- self在对象的方法中表示当前对象本身,如果通过对象调用一个方法,
那么该对象会自动传入到当前方法的第一个参数中
- self并不是关键字,只是一个用于接收对象的普通参数,理论上可以用任何一个
普通变量名代替
- 方法中有self形参的方法成为非绑定类的方法,可以通过对象访问,没有self的
是绑定类的方法,只能通过类访问
- 使用类访问绑定类的方法时,如果类方法中需要访问当前类的成员,可以通过
__class__成员名来访问
6. 面向对象的三大特性
- 封装
- 继承
- 多态
6.1 封装
- 封装就是对对象的成员进行访问限制
封装的三个级别
- 公开:public
- 受保护的:protected
- 私有的:private
- public,private,protected不是关键字
判别对象的位置
- 对象内部
- 对象外部
- 子类中
- python中下划线的使用
私有
- 私有成员是最高级别的封装,只能在当前类或对象中访问
在成员前面添加两个下划线即可
class Person():
# name是共有的成员 name = "ruochen" # __age就是私有成员 __age = 18
- Python的私有不是真私有,是一种成为name mangling的改名策略
可以使用对象._classname_attributename访问
受保护的封装 protected
- 受保护的封装是将对象成员进行一定级别的封装,然后,在类中或者子类
中都可以访问,但是在外部不可以
- 封装方法:在成员名称前添加一个下划线即可
公开的,公共的 public
- 公共的封装实际对成员没有任何操作,任何地方都可以访问
class Student():
name = "aaa"
age = 18
Student.__dict__
# 实例化
a = Student()
a.__dict__
print(a.name)
aaa
class A():
name = "dana"
age = 18
# 注意say的写法,参数有一个self
def say(self):
self.name = "aaa"
self.age = 200
# 此案例说明
# 类实例的属性和其对象的实例的属性在不对对象的实例属性赋值的前提下,
# 指向同一变量
# 此时,A称为类实例
print(A.name)
print(A.age)
print("*" * 20)
# id可以鉴别出一个变量是否和另一个变量是同一变量
print(id(A.name))
print(id(A.age))
print("*" * 20)
a = A()
print(a.name)
print(a.age)
print(id(a.name))
print(id(a.age))
dana
18
********************
2245155422024
140717429003616
********************
dana
18
2245155422024
140717429003616
# 此时,A称为类实例
print(A.name)
print(A.age)
print("*" * 20)
# id可以鉴别出一个变量是否和另一个变量是同一变量
print(id(A.name))
print(id(A.age))
print("*" * 20)
a = A()
# 查看A内所有属性
print(A.__dict__)
print(a.__dict__)
a.name = "yaona"
a.age = 16
print(a.__dict__)
print(a.name)
print(a.age)
print(id(a.name))
print(id(a.age))
dana
18
********************
2245155422024
140717429003616
********************
{'__module__': '__main__', 'name': 'dana', 'age': 18, 'say': <function A.say at 0x0000020ABDBC7E18>, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}
{}
{'name': 'yaona', 'age': 16}
yaona
16
2245155597256
140717429003552
class Student():
name = "dana"
age = 18
# 注意say的写法,参数有一个self
def say(self):
self.name = "aaa"
self.age = 200
print("My name is {0}".format(self.name))
print("My age is {0}".format(self.age))
def sayAgain(s):
print("My name is {0}".format(s.name))
print("My age is {0}".format(s.age))
yueyue = Student()
yueyue.say()
yueyue.sayAgain()
My name is aaa
My age is 200
My name is aaa
My age is 200
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()
My name is yaona
My age is 19
dana
19
Hello, nice to see you again
# 关于self的案例
class A():
name = "ruochen"
age = 18
def __init__(self):
self.name = "aaaa"
self.age = 200
def say(self):
print(self.name)
print(self.age)
class B():
name = "bbb"
age = 99
a = A()
# 此时,系统会默认把a作为第一个参数传入函数
a.say()
# 此时,self被a替换
A.say(a)
# 同样可以把A作为参数传入
A.say(A)
# 此时,传入的是类实例B,因为B具有name和age属性,所有不会报错
A.say(B)
# 以上代码,利用鸭子模型
aaaa
200
aaaa
200
ruochen
18
bbb
99
# 私有变量案例
class Person():
# name是共有的成员
name = "ruochen"
# __age就是私有成员
__age = 18
p = Person()
# name是公有变量
print(p.name)
# __age是私有变量
# 注意报错信息
print(p.__age)
ruochen
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-41-e118b6505697> in <module>
11 # __age是私有变量
12 # 注意报错信息
---> 13 print(p.__age)
AttributeError: 'Person' object has no attribute '__age'
# name.mangling 技术
print(Person.__dict__)
p._Person__age = 19
print(p._Person__age)
{'__module__': '__main__', 'name': 'ruochen', '_Person__age': 18, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}
19