面向对象
面向对象
- 与面向过程对比:
- 面向过程:数学逻辑的映射,学会做个好员工
- 面向对象:生活逻辑的映射,学会做个好领导
- 生活实例:
- 类: 人 手机 电脑
- 对象: 我的手机、女朋友的手机 你的那部T400、老板桌上的电脑
- 类: 人 手机 电脑
- 官方定义:
- 类:具有相同特征(属性和行为)的事物的抽象
- 对象:某个类的具象
- 编程语言:
- 类:是一种自定义的数据类型
- 对象:某个类类型的变量
面向对象语法
-
类的定义:
class 类名: 内容
-
语法说明:
- 定义类需要使用关键字
class
- 类名:原则上只要符合标识符命名规范即可,但是通过我们都使用大驼峰(每个单词首字母大写)风格命名
- 如:UserName
- 类名后面的':'不要忘记
- 类的内容要进行整体缩进
- 行为:通过方法体现,在类中定义相关的函数即可(第一个参数通常是self)
- 属性:通过变量体现,在需要时动态添加,很多时候定义类时没有体现
- 成员访问:
- 属性:对象.属性名
- 方法:对象.方法名()
- 定义类需要使用关键字
-
示例:
# 定义类 class Person: # 行为通过方法体现 # 吃饭 def eat(self): print('红烧排骨我喜欢吃') # 睡觉 def sleep(self): print('睡觉也是一种生活态度') # 定义对象 liang = Person() # 调用方法 liang.eat() liang.sleep() # 属性时动态添加的 liang.name = '上官' # 获取属性 print(liang.name)
-
self使用
class Person: def run(self): # self表示当前对象:谁调用该方法就表示谁 print('{}每天以2m/s的速度慢跑5km'.format(self.name)) def introduce(self): # 不但可以访问成员属性 print('我叫{}'.format(self.name)) # 还可以调用成员方法 self.run() fei = Person() fei.name = '欧阳' fei.run() fei.introduce() long = Person() long.name = '诸葛' long.introduce()
- 说明:
1.类中的每个成员方法都有一个self参数,调用的时候不需要传递该参数 2.该参数的名字可以不是self,只不过通常我们都使用这个 3.self表示当前对象,对调用该方法self就代表谁,哪个对象调用就表示哪个对象 4.通过self可以访问成员属性,也可以调用成员方法
-
__str__方法
class Person: # 使用print方法打印对象,默认打印 类名 + 地址 # 若想打印特定内容,重写该方法即可,要求返回一个字符串 def __str__(self): return '我叫{},今年{}'.format(self.name, self.age) james = Person() james.name = '勒布朗.詹姆斯' james.age = 33 print(james)
-
练习:
- 自定义一个狗类,添加如下属性和方法:
- 属性:名字、年龄、颜色
- 方法:跑、吃、游泳、吠、描述
- 自定义一个狗类,添加如下属性和方法:
-
构造方法:创建对象后,初始化属性时,系统会自动调用该方法
class Cat: def __str__(self): return 'name:{},age:{},color:{}'.format(self.name, self.age, self.color) # 构造方法:创建对象后,初始化系统就会自动调用该方法 def __init__(self, name, age, color): print('__init__') self.name = name self.age = age self.color = color # 这种形式比较繁琐 # tom = Cat() # tom.name = 'Tom' # tom.age = 3 # tom.color = '蓝色' # 这种比较简洁 tom = Cat('Tom', 3, '蓝色') print(tom)
-
析构方法:当对象释放时系统会自动调用,通常用于释放资源
class Pig: # 析构方法:当对象释放时,系统会自动调用 # 若手动使用del删除,则会立即调用该方法 # 该方法一般做资源释放处理:数据库连接断开,文件关闭 def __del__(self): print('大师兄,我不行了') bajie = Pig() del bajie print('八戒,一路走好!')
-
经典示例:小明手里有两张牌,左手♥K,右手♠A,小明交换两手的牌后,手里分别是什么?
- 思路:
- 先找到对象:左手、右手、♥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): 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()
- 思路:
-
练习:设计一个数学类,有两个成员属性,成员方法有加、减、乘、除,展示成员。
常用内置函数
-
内置函数:在类的内部,特定时机自动触发的函数。
-
示例:setattr、getattr、delattr
class Person: def __init__(self, name): self.name = name def __str__(self): return '姓名:{}'.format(self.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('小明') xiaoming.age = 20 print(xiaoming.age) # 存放对象的所有属性 # print(xiaoming.__dict__) # print(xiaoming) 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): del self.__dict__[key] xiaoming = Person() xiaoming['name'] = '小明' print(xiaoming.__dict__) print(xiaoming['name']) del xiaoming['name']
-
将对象当做函数调用时,会自动触发下面方法
class Person: # 将对象当做函数调用时,会自动触发该方法 def __call__(self, *args, **kwargs): # print('__call__') return sum(args) xiaoming = Person() # 这样操作,需要提供call方法 ret = xiaoming(1, 2, 3, name='小明') print(ret)
-
函数判断
class A: def __call__(self, *args, **kwargs): pass def test(): pass a = A() # 判断是否可调用 print(callable(test)) print(callable(a)) # 判断是否拥有'__call__'属性 print(hasattr(test, '__call__')) print(hasattr(a, '__call__')) # 判断是否是函数 from inspect import isfunction print(isfunction(test)) print(isfunction(a))