面向对象
与面向过程对比:二狗子准备结婚,需要盖房子
面向过程:数学逻辑的映射,学会做个好员工
面向对象:生活逻辑的映射,学会做个好领导
官方定义:
类:具有相同特征(属性和行为)事物的抽象
对象:某个类的具象
编程语言:
类:是一种自定义的数据类型
对象:某个类型的变量
类的语法
定义类:
class 类名: 内容
示例:定义一个人的类
# 定义类 class Person: # 行为的体现,通过方法 # 吃饭 def eat(self): print('红烧鸡腿我喜欢吃') # 打篮球 def play(self): print('俺喜欢打篮球') # 声明对象 bryant = Person() # 调用方法 bryant.eat() bryant.play() # 设置属性:是动态添加的 bryant.name = '科比.布莱恩特' # 获取属性 print(bryant.name)
语法
定义类需要使用关键字:class
类名:原则上只要符合标识符的命名规范即可,但是我们通常使用大驼峰风格(每个单词首字母大写)命名
不要忘记类名后面的冒号':'
类的内容要进行缩进
行为:通过函数体现,与外面定义函数的方式相似,第一个参数默认是self
属性:通过变量体现,属性是动态添加的,因此在定义时可以不体现
成员访问:
成员属性:对象.属性名
成员方法:对象.方法名()
self
示例:
class 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 __方法
示例:
class Person: # 使用print函数打印对象时,默认打印对象所属类型及对象地址 # 该函数要求返回一个字符串,当对象作为print参数打印时会打印该字符串 def __str__(self): # 要求返回一个字符串 return '我叫{},今年{}'.format(self.name, self.age) xiaoming = Person() xiaoming.name = '小明' xiaoming.age = 18 print(xiaoming)
练习:
自定义一个狗类,完成属性的动态添加,方法的调用
属性:名字、年龄、颜色
方法:跑、吃、游泳、叫
构造方法
作用:用于对象创建后初始化相关的属性
示例:
class Cat: def __init__(self, name, age): # 创建对象后进行初始化操作,系统会自动调用 # 也叫构造方法 print('init') self.name = name self.age = age self.color = '白色' # 创建对象时的参数要与构造方法一致 tom = Cat('Tom', 1) print(tom)
析构方法
作用:当对象即将销毁时,系统会自动调用
示例:
class Pig: def __del__(self): # 当对象释放时系统会自动调用,如果使用del删除对象,则立即释放调用该方法 # 一般在此处做:断开连接、关闭文件、释放资源等 print('大师兄,我不行了') bajie = Pig() # 若删除对象,则会立即调用 析构方法 del bajie print('一路走好')
示例:小明手里有两张牌,左手♥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)) 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、getattr、delattr
class 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