面向对象(一)
面向对象
-
与面向过程相比:二狗子准备结婚,需要盖房子
- **面向过程:**数学逻辑的映射,学会做个好员工
- **面向对象:**生活逻辑的映射,学会做个好领导
-
生活实例
- 类: 人 手机 电脑
- 对象: 习大大、小杰 小杰的T2手机、小明的iPhone X 小杰的Mac、小李的华硕
-
官方定义:
- **类:**具有相同特征(属性和行为)事物的抽象
- **对象:**某个类的具象
-
编程语言:
- **类:**是一种自定义的数据类型
- **对象:**某个类型的变量
类的语法
-
定义类:
1
2class 类名:
内容 -
示例:定义一个人的类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24# 定义类
class Person:
# 行为的体现,通过方法
# 吃饭
def eat(self):
print('红烧鸡腿我喜欢吃')
# 打篮球
def play(self):
print('俺喜欢打篮球')
# 声明对象
bryant = Person()
# 调用方法
bryant.eat()
bryant.play()
# 设置属性:是动态添加的
bryant.name = '科比·布莱恩特'
# 获取属性
print(bryant.name) -
语法:
- 定义类需要使用关键字:class
- **类名:**原则上只要符合表示标识符的命名规范即可,但我们通常使用大驼峰(每个单词首字母大写)的风格
- 不要忘记类名后边的冒号
- 类的内容要进行缩进
- **行为:**通过函数体现,与外面定义函数的方式类似,第一个参数默认是self
- **属性:**通过变量体现,属性是动态添加的,因此在定义时可以不体现
- 成员访问:
- 成员属性:
对象.属性名
- 成员方法:
对象.方法名()
- 成员属性:
-
self
-
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25class Person:
def run(self):
# self表示当前对象:谁调用该方法就代表谁
print('{}每天以2m/s的速度锻炼5km'.format(self.name))
def introduce(self):
# self这个名字可以是任意的,但是通常都是要用这个
# 既可以访问成员属性
print('我叫{}'.format(self.name))
# 也可以访问成员方法
self.run()
mugai = Person()
mugai.name = '木盖'
# print(mugai)
mugai.run()
curry = Person()
curry.name = '史蒂芬·库里'
curry.run()
# 调用方法时第一个参数self不需要传递
curry.introduce() -
说明:
- 每个成员方法都有这么一个参数,调用的时候不需要传递
- 名字可以不是self,只不过通常我们都要self而已
- self表示当前对象,谁调用该方法就表示谁,哪个对象调用就表示哪个对象
- 通过self可以访问成员属性,也可以调用成员方法
-
-
__str__方法
-
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13class Person:
# 使用print函数打印时,默认打印对象所属的类型及对象的地址
# 该函数要求返回一个字符串,当对象作为print参数打印时会打印该字符串
def __str__(self):
# 要求返回一个字符串
return '我叫{},今年{}'.format(self.name, self.age)
xiaoming = Person()
xiaoming.name = 'xiaoming'
xiaoming.age = 18
print(xiaoming) -
练习:
- 自定义一个狗类,完成属性的动态添加,方法的调用
- 属性:名字、年龄、颜色
- 方法:跑、吃、游泳、叫
- 自定义一个狗类,完成属性的动态添加,方法的调用
-
-
构造方法
- **作用:**用于对象创建后初始化相关的属性
- 示例:
1
2
3
4
5
6
7
8
9
10
11
12
13class Cat:
def __init__(self, name, age):
# 创建对象后进行初始化操作,系统会自动调用
# 也叫构造方法
print('init')
self.name = name
self.age = age
self.color = '白色'
# 创建对象时的参数要与构造方法一致
tom = Cat('Tom', 1)
print(tom)
-
析构方法
-
**作用:**当对象即将销毁时,系统会自动调用
-
示例1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17import time
class Pig:
def __del__(self):
# 当对象释放时系统会自动调用,如果你使用del删除对象,则立即释放调用该方法
# 一般在此处做:断开连接、关闭文件、释放资源等
print('大师兄,我不行了')
bajie = Pig()
# 若删除对象,则会立即调用析构方法
del bajie
time.sleep(5)
bajie.name = 'wuneng' -
**示例2:**小明手里有两张牌,左手♥K,右手♠A,问:小明交换两手的牌后,手里分别是什么?
-
思路:
- 先找到对象:小明、左手、♥K、♠A、右手
- 根据对象抽象出来的类:人、牌、手
- 写出对应的逻辑,反过来完善抽象出来的类
- 按照题目要求创建对应的对象,调用相关的方法
- 代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56# 扑克牌
class Poker:
def __init__(self, color, number):
self.color = color
self.number = number
def __str__(self):
return '{}{}'.format(self.color, self.number)
# 创建两张牌
p1 = Poker('♥', 'K')
p2 = Poker('♠', 'A')
# 手的类
class Hand:
def __init__(self, poker=None):
self.poker = poker
def hold_poker(self, poker):
self.poker = poker
# 创建左右两只手的对象
left_hand = Hand(p1)
right_hand = Hand(p2)
# 人的类
class Person:
def __init__(self, name, left_hand, right_hand):
self.name = name
self.left_hand = left_hand
self.right_hand = right_hand
# 展示手里的牌
def show(self):
print('{}张开手'.format(self.name))
print('左手:{}'.format(self.left_hand.poker))
print('右手:{}'.format(self.right_hand.poker))
# 交换手里的牌
def swap(self):
self.left_hand.poker, self.right_hand.poker = self.right_hand.poker, self.left_hand.poker
print('{}交换两手的牌'.format(self.name))
# 创建小明对象
xiaoming = Person('小明', left_hand, right_hand)
# 展示手里的牌
xiaoming.show()
# 小明交换牌
xiaoming.swap()
# 再次展示手里的牌
xiaoming.show()
-
常见的内置函数
-
**内置函数:**在类的内部,特定时机自动触发的函数
-
**示例:**setattr、getattrr、delattr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39class Person:
# def __init__(self, name):
# self.name = name
def __setattr__(self, key, value):
# 当设置对象成员属性时,系统会自动调用
print(key, value)
self.__dict__[key] = value
def __getattr__(self, item):
# 当访问不存在的属性时,系统会自动调用
if item == 'age':
return 123
else:
return 'default'
def __delattr__(self, item):
# 当销毁对象的成员属性时,系统会自动调用
print('del', item)
xiaoming = Person()
# 每个对象都有一个成员属性:__dict__
# 用于存放对象的属性,包括动态添加的
# print(xiaoming.__dict__)
# xiaoming.name = '小明'
# print(xiaoming.name)
# print(xiaoming.__dict__)
xiaoming.age = 18
print(xiaoming.age)
print(xiaoming.hello)
del xiaoming.age
# del xiaoming.hello -
练习:
1
2自己研究:setitem、getitem、delitem
友情提醒:当将一个对象作为字典操作时,会触发上面对应的方法