面向对象
面向对象
- 与面向过程对比
- 面向过程:数学逻辑的映射,学会做个好员工。
- 面向对象:生活逻辑的映射,学会做个好领导。
- 生活实例
- 类: 人 手机 电脑
- 对象: 习大大、普京 二狗的iphoneX 生辉桌上的电脑
- 类: 人 手机 电脑
- 官方定义
- 类:具有相同特征(属性和行为)事物的抽象
- 对象:某个类的具象
- 编程语言
- 类:是一种自定义的数据类型
- 对象:某个类类型的变量
面向对象语法
类的定义
class 类名: pass
语法说明
- 定义类需要使用关键字
class
- 类名:原则上符合标识符命名规范即可,但是通常我们都采用大驼峰风格命名,如:UserName
- 类名后面的’:’不要忘记
- 类的内容要进行整体缩进
- 行为通过方法体现
- 属性通过变量体现,需要动态添加
- 成员访问:
- 属性:对象.属性名
- 方法:对象.方法名()
- 示例:
# 定义类 class Person: # 行为时通过方法体现的 # 吃饭 def eat(self): print('红烧鸡腿我喜欢吃') # 睡觉 def sleep(self): print('睡觉是一种生活态度') # 创建对象 hui = Person() # 属性时动态添加的 hui.age = 30 hui.height = 170 print(hui.age) # 调用对象方法 hui.eat()
- 定义类需要使用关键字
self使用
class Person: def run(self): # self表示当前对象,就是调用该方法的对象 print('{}每天以2m/s的速度慢跑5km'.format(self.name)) def introduce(self): # 不但可以访问成员属性 print('我叫{}今年18岁'.format(self.name)) # 还可以调用成员方法 # self参数可以使用其他名字,调用方法时不需要传递 self.run() hui = Person() hui.name = '生辉' # hui.run() fei = Person() fei.name = '赵飞' # fei.run() fei.introduce()
__str__方法
class Person: # 默认打印对象,显示类名+地址 # 重写该方法,打印该方法的返回值 def __str__(self): return '我叫{},今年{}岁'.format(self.name, self.age) james = Person() james.name = '勒布朗.詹姆斯' james.age = 33 print(james)
__init__方法
class Cat: def __str__(self): return 'name:{},age:{},color:{}'.format(self.name, self.age, self.color) # 构造方法:创建对象后,会自动调用该方法完成初始化设置 def __init__(self, name, age, color): # print('__init__', name, age, color) self.name = name self.age = age self.color = color # 这种方案比较繁琐 # jiafei = Cat() # jiafei.name = '加菲' # jiafei.age = 2 # jiafei.color = '橘黄色' # print(jiafei) jiafei = Cat('加菲', 2, '橘黄色') print(jiafei)
__del__方法
class Pig: # 析构方法:当对象释放时,系统会自动调用 # 若手动使用del删除:则会立即调用该方法 # 该方法一般做资源释放操作,如:数据库断开连接,文件关闭 def __del__(self): print('大师兄,我不行了') bajie = Pig() del bajie print('八戒,一路走好')
思考:小明手里有2张牌,左手♥K,右手♠A,小明交换两手的牌后,手里分别有什么?
先找到对象:小明、左手、右手、♥K、♠A
- 根据对象抽象类:人、手、牌
- 根据需求完善设计对应的类
- 示例
# 扑克牌 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), end=' ') print('左手:{}'.format(self.left_hand.poker), end=',') 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()
- 练习:设计一个数学类,属性有两个数,方法:加、减、乘、除,展示成员
常用内置函数
内置函数:在类中,特定时机自动回触发的函数。
- 设置、获取、销毁属性时自动触发的方法:
class Person: def __str__(self): return '姓名:{}'.format(self.name) def __init__(self, name): self.name = name def __del__(self): print('对象即将销毁') # 当访问不存在的属性时会自动触发该方法 def __getattr__(self, item): if item == 'age': return 18 else: return '你猜' # 设置属性时会自动触发该方法 def __setattr__(self, key, value): # print(key, value) self.__dict__[key] = value # 销毁对象的指定属性时会自动触发 def __delattr__(self, item): print(item, '属性即将销毁') xiaoming = Person('小明') # print(xiaoming.age) # print(xiaoming.weight) xiaoming.age = 20 # 存放了所有的对象属性 # print(xiaoming.__dict__) # print(xiaoming.age) del xiaoming.age
将对象当做字典操作,特定时机自动触发的函数
class Person: # 将对象当做字典操作,添加或设置属性时自动触发 def __setitem__(self, key, value): print(key, value) self.__dict__[key] = value # 将对象当做字典操作,获取属性时自动触发 def __getitem__(self, item): # print(item) return self.__dict__.get(item) # 将对象当作字典操作,销毁属性时自动触发 def __delitem__(self, key): print(key, '即将销毁') del self.__dict__[key] xiaoming = Person() xiaoming['name'] = '小明' # print(xiaoming.name) print(xiaoming['name']) del xiaoming['name']
- 将对象当做函数调用
class Person: # 将对象当做函数调用时,会自动触发该方法 def __call__(self, *args, **kwargs): # print('__call__', args) return sum(args) xiaoming = Person() # 如果想这样调用,必须重写__call__方法 ret = xiaoming(1, 2, 3) print(ret)
- 判断一个对象是否可以调用,是否拥有某属性,是否是函数
def test(): pass # 判断一个对象能否被调用 print(callable(xiaoming)) print(callable(test)) # 判断一个对象是否拥有__call__属性 print(hasattr(test, '__call__')) print(hasattr(xiaoming, '__call__')) # 判断一个对象是否能够调用 from inspect import isfunction print(isfunction(test)) print(isfunction(xiaoming))
练习
- 第一题
- 设计一个学生类
- 属性:姓名、学号、年龄、成绩
- 设计一个班级类
- 属性:班级代号,所有学生
- 要求:实现向班级中添加学生、删除学生、查看学生、按照指定条件排序
- 第二题
- 将歌词解析封装成类,要求:提供一个方法(根据时间返回歌词)
- 提示:封装两个类:歌词类、歌词管理类