面向对象编程
类和对象
面向对象编程 --Object Oriented Programming, 简称 OOP, 是一种程序设计思想.
OOP 把对象作为程序的基本单元, 一个对象包含了 数据和操作数据的方法(函数).
在 Python 中, 所有数据类型都可以视为对象, 当然也可以自定义对象.
自定义的对象数据类型就是面向对象中的类 (Class) 的概念.
类 --- 抽象
对象 --- 实例化
猫科:
颜色
长短
体重
公母
生命维持时间
方法: 出生
确定公母
规定体重
猫科编号......
方法: 生孩子
创建新的猫科动物实例
调用出生方法
母猫体重减去 5kg
方法: 吃饭
体重增加 100g
生命维持时间 + 1 天
七公寓后面的小橘猫 = 猫科("橘色" ,"0.5 米" , 10kg, 公, 存活时间 0.5 天)
19
19
1
猫科:
2
颜色
3
长短
4
体重
5
公母
6
生命维持时间
7
方法: 出生
8
确定公母
9
规定体重
10
猫科编号......
11
方法: 生孩子
12
创建新的猫科动物实例
13
调用出生方法
14
母猫体重减去 5kg
15
方法: 吃饭
16
体重增加 100g
17
生命维持时间 + 1 天
18
19
七公寓后面的小橘猫 = 猫科("橘色" ,"0.5 米" , 10kg, 公, 存活时间 0.5 天)
假设我们要处理学生的成绩表, 为了表示一个学生的成绩, 面向过程的程序可以用一个 dict 表示:
- std1 = {
- 'name': 'Michael', 'score': 98
- }
- std2 = {
- 'name': 'Bob', 'score': 81
- }
而处理学生成绩可以通过函数实现, 比如打印学生的成绩:
- def print_score(std):
- print('%s: %s' % (std['name'], std['score']))
如果采用面向对象的程序设计思想, 我们首选思考的不是程序的执行流程,
而是 Student 这种数据类型应该被视为一个对象, 这个对象拥有 name 和 score 这两个属性(Property).
如果要打印一个学生的成绩, 首先必须创建出这个学生对应的对象,
然后, 给对象发一个 print_score 消息, 让对象自己把自己的数据打印出来.
- class Student(object):
- def __init__(self, name, score):
- self.name = name
- self.score = score
- def print_score(self):
- print('%s: %s' % (self.name, self.score))
- bart = Student('Bart Simpson', 59)
- lisa = Student('Lisa Simpson', 87)
- bart.print_score()
- lisa.print_score()
所以, 面向对象的设计思想是抽象出 类 Class, 根据 类 创建 对象
面向对象的抽象程度又比函数要高, 因为一个 Class 既包含数据, 又包含数据的操作方法.
由于类可以起到模板的作用, 因此, 可以在创建实例的时候, 把一些我们认为必须绑定的属性强制填写进去.
通过定义一个特殊的 __init__ 方法, 在创建实例的时候, 就把 name , score 等属性绑上去:
- class Student(object):
- def __init__(self, name, score):
- self.name = name
- self.score = score
注意到 __init__ 方法的第一个参数永远是 self , 表示创建的实例本身,
因此, 在 __init__ 方法内部, 就可以把各种属性绑定到 self , 因为 self 就指向创建的实例本身.
私有变量
如果要让内部属性不被外部访问, 可以把属性的名称前加上两个下划线__
在 Python 中, 实例的变量名如果以 __ 开头, 就变成了一个私有变量(private)
只有内部可以访问, 外部不能访问
(没有绝对的私有, 全靠自觉)
继承
在 OOP 程序设计中, 当我们定义一个 class 的时候, 可以从某个现有的 class 继承
新的 class 称为子类(Subclass), 而被继承的 class 称为基类, 父类或超类(Base class,Super class)
继承可以把父类的所有功能都直接拿过来, 这样就不必重零做起,
子类只需要新增自己特有的方法, 也可以把父类不适合的方法覆盖重写.
猫科:
颜色
长短
体重
公母
生命维持时间
方法: 出生
确定公母
规定体重
猫科编号......
方法: 生孩子
创建新的猫科动物实例
调用出生方法
母猫体重减去 5kg
方法: 吃饭
体重增加 100g
生命维持时间 + 1 天
猫咪(继承自猫科):
数据继承自猫科
方法: 叫:
print(喵喵喵)
方法: 抓耗子:
......
豹子(继承自猫科):
数据继承自猫科
方法: 叫:
print(嗷嗷嗷)
方法: 抓落单的马:
......
橘猫(继承自猫咪):
颜色
方法: 叫:
print(我是橘猫)
七公寓后面的小橘猫 = 猫咪("橘色" ,"0.5 米" , 10kg, 公, 存活时间 0.5 天)
35
35
1
猫科:
2
颜色
3
长短
4
体重
5
公母
6
生命维持时间
7
方法: 出生
8
确定公母
9
规定体重
10
猫科编号......
11
方法: 生孩子
12
创建新的猫科动物实例
13
调用出生方法
14
母猫体重减去 5kg
15
方法: 吃饭
16
体重增加 100g
17
生命维持时间 + 1 天
18
猫咪(继承自猫科):
19
数据继承自猫科
20
方法: 叫:
- 21
- print(喵喵喵)
- 22
方法: 抓耗子:
23
......
24
豹子(继承自猫科):
25
数据继承自猫科
26
方法: 叫:
- 27
- print(嗷嗷嗷)
- 28
方法: 抓落单的马:
29
......
30
橘猫(继承自猫咪):
31
颜色
32
方法: 叫:
- 33
- print(我是橘猫)
- 34
七公寓后面的小橘猫 = 猫咪("橘色" ,"0.5 米" , 10kg, 公, 存活时间 0.5 天)
35
多态:
方法调用将作用在 x 的实际类型上.
s 是 cat 类型, 它实际上拥有自己的 run()方法以及从 animal 继承的 run 方法,
但调用 s.run()总是先查找它自身的定义,
如果没有定义, 则顺着继承链向上查找, 直到在某个父类中找到为止.
七公寓后面的小橘猫 1 = 猫咪("橘色" ,"0.5 米" , 10kg, 公, 存活时间 0.5 天)
七公寓后面的小橘猫 1. 叫()
---- 结果: 喵喵喵
七公寓后面的小橘猫 2 = 橘猫("0.5 米" , 10kg, 公, 存活时间 0.5 天)
七公寓后面的小橘猫 2. 叫()
---- 结果: 我是橘猫
7
7
1
七公寓后面的小橘猫 1 = 猫咪("橘色" ,"0.5 米" , 10kg, 公, 存活时间 0.5 天)
2
七公寓后面的小橘猫 1. 叫()
3
---- 结果: 喵喵喵
4
5
七公寓后面的小橘猫 2 = 橘猫("0.5 米" , 10kg, 公, 存活时间 0.5 天)
6
七公寓后面的小橘猫 2. 叫()
7
---- 结果: 我是橘猫
使用 dir()
如果要获得一个对象的所有属性和方法, 可以使用 dir() 函数, 它返回一个包含字符串的 list
比如, 获得一个 str 对象的所有属性和方法:
- dir('ABC')
- ['__add__', '__class__', '__contains__', '__delattr__', '__dir__',
- '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
- '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__',
- '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__',
- '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
- '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__',
- '__subclasshook__', 'capitalize', 'casefold', 'center', 'count',
- 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map',
- 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier',
- 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper',
- 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace',
- 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split',
- 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate',
- 'upper', 'zfill']
仅仅把属性和方法列出来是不够的, 配合 getattr() , setattr() 以及 hasattr() ,
我们可以直接操作一个对象的状态:
- hasattr(obj, 'y') # 有属性'y'吗?
- setattr(obj, 'y', 19) # 设置一个属性'y'
- getattr(obj, 'y') # 获取属性'y'
如果试图获取不存在的属性, 会抛出 AttributeError 的错误
多重继承
通过多重继承, 一个子类就可以同时获得多个父类的所有功能.
- class Student(object):
- # 数据区 方法内访问数据区数据需要用 self.name 来访问, 以与方法内参数区分
- name=""
- score=0
- # 方法区: 方法的第一个参数为 self(类自身, 写方法体需要带上, 调用的时候不用加上)
- #__init__方法: 创建这个类的对象的时候调用, 初始化这个对象
- def __init__(self, name, score):
- self.name = name
- self.score = score
- # 自定义方法
- def print_score(self):
- print('%s: %s' % (self.name, self.score))
- # 自定义方法
- def get_grade(self):
- if self.score>= 90:
- return 'A'
- elif self.score>= 60:
- return 'B'
- else:
- return 'C'
- bart = Student('Bart Simpson', 59)
- lisa = Student('Lisa Simpson', 87)
- print('bart.name =', bart.name)
- print('bart.score =', bart.score)
- bart.print_score()
- print('grade of Bart:', bart.get_grade())
- print('grade of Lisa:', lisa.get_grade())
- 33
- 33
- 1
- class Student(object):
- 2
- # 数据区 方法内访问数据区数据需要用 self.name 来访问, 以与方法内参数区分
- 3
- name=""
- 4
- score=0
- 5
- 6
- # 方法区: 方法的第一个参数为 self(类自身, 写方法体需要带上, 调用的时候不用加上)
- 7
- 8
- #__init__方法: 创建这个类的对象的时候调用, 初始化这个对象
- 9
- def __init__(self, name, score):
- 10
- self.name = name
- 11
- self.score = score
- 12
- 13
- # 自定义方法
- 14
- def print_score(self):
- 15
- print('%s: %s' % (self.name, self.score))
- 16
- 17
- # 自定义方法
- 18
- def get_grade(self):
- 19
- if self.score>= 90:
- 20
- return 'A'
- 21
- elif self.score>= 60:
- 22
- return 'B'
- 23
- else:
- 24
- return 'C'
- 25
- 26
- 27
- bart = Student('Bart Simpson', 59)
- 28
- lisa = Student('Lisa Simpson', 87)
- 29
- print('bart.name =', bart.name)
- 30
- print('bart.score =', bart.score)
- 31
- bart.print_score()
- 32
- print('grade of Bart:', bart.get_grade())
- 33
- print('grade of Lisa:', lisa.get_grade())
来自为知笔记(Wiz) http://www.wiz.cn/i/77ad7a1f
来源: http://www.bubuko.com/infodetail-3016180.html