声明:本文经过他人博客进行整合,仅为学习笔记,不作它用。
面向对象概念剖析
一言以蔽之:万物皆对象,每个对象都有自己的属性和行为。
面向对象和面向过程的对比
面向过程——步骤化:
面向过程就是分析出实现需求所需要的步骤,通过函数一步一步实现这些步骤,接着依次调用即可。
面向对象——行为化:
面向对象是把整个需求按照特点、功能划分,将这些存在共性的部分封装成类(类实例化后才是对象)。
创建了对象不是为了完成某一个步骤,而是描述某个事物在解决问题的步骤中的行为。
举例:设计一个桌球游戏
面向过程思想:
① player1 击球 —— ② 实现画面击球效果 —— ③ 判断是否进球及有效 —— ④ player2击球 —— ⑤ 实现画面击球效果 —— ⑥ 判断是否进球及有效 —— ⑦ 返回步骤 1—— ⑧ 输出游戏结果
面向对象思想:
经过观察我们可以看到,其实在上面的流程中存在很多共性的地方,所以我们将这些共性部分全集中起来,做成一个通用的结构。
玩家系统:包括 player1 和 player2
击球效果系统:负责展示给用户游戏时的画面
规则系统:判断是否犯规,输赢等
类
用户定义的对象原型(prototype),可将其理解为一个模板。该原型定义了一组可描述该类任何对象的属性和方法,可以利用其来生成各种不同的具体的对象。
对象
某一个类的具体实例。
属性
描述该类具有的特征。
方法
该类对象的行为。常通过方法改编一些类中的属性值。
举例
定义了一个Person类;而具体的人如小张即为Person类的对象;而Person类具备的属性如同人类具备的属性,例如姓名、身高、体重等等;这个对象会跳舞,那个对象会唱歌,诸如此类属于方法。
Python使用面向对象编程
类的定义
Python中使用关键字class来定义类
示例如下:
class Student:
pass
定义一个类时,由于规范性问题,常常大写第一个字母。
给类添加基本属性
在类中属性包含类属性和对象属性两种属性。
class Person:
person = "学生"
def __init__(self,name,age):
self.name = name
self.age = age
Xiaoming = Person("小明",18)
Xiaohong = Person("小红",19)
print(f"{Xiaoming.name}今年{Xiaoming.age}岁,是{Xiaoming.__class__.person}")
print(f"{Xiaohong.name}今年{Xiaohong.age}岁,是{Xiaohong.__class__.person}")
输出结果:
- 类中定义了一个person属性,即为类属性,可以通过
对象.(两个下划线)class(两个下划线).person
访问。 - 如果对象属性在一个地方被改变了,那么其他的地方也会改变。
- 类中定义了一个名为init的方法,我们称之构造方法。在python中创建对象的时候,这个方法会自动调用。
- 在构造方法中定义了两个对象属性,按照
self.属性=赋值
的格式。所以在下面创建对象的时候,就要传入这两个对象的属性,后面就可以通过
对象.属性
的方式得到我们设置的对象属性。 - 输出的时候,在引号前面加上f以格式化输出,插入调用内容时用{ }框住。
给类添加方法
使用def关键字定义一个方法,然后再方法体编写方法具体的功能即可。
示例如下:
class Person:
def __init__(self,name,age):
self.name = name
self.age = age
def study(self):
print(f"{self.name}在努力学习算法")
Xiaoming = Person("小明",18)
Xiaohong = Person("小红",19)
Xiaoming.study()
Xiaohong.study()
输出结果:
类中方法的定义中,第一个参数必须是self,它指的是当前对象。例如Xiaoming是当前对象,而self指的就是Xiaoming。
当我们需要调用对象方法的时候,只需要使用
对象.方法([参数])
即可。
面向对象的特性
封装
基本思想:决定属性和行为归属谁的问题,并隐藏对象中一些不希望被外部访问到的属性或方法,确保数据安全。
方法:在成员属性或者成员方法前面加上__,使外部不可见。
双下划线的作用:在 Python 中,双下换线是作为隐藏属性而存在的,但它其实还是可以通过方法访问的到的,在 Python 内部当中,双下划线实际上是把 属性换了一个更复杂的方式表示,比 hidden_属性 更复杂,它其实是把 “__xxx ” 替换成了 “_类名__属性名” 表示。
class Account:
def __init__(self,password):
self.__password = password
def getpsw(self):
return self.__password
def __print(self):
print("不能执行奥")
acc = Account("123456")
print(acc.getpsw())
# acc.__print() 这个执行不了
输出结果“:
继承
特点:子类继承父类后,就可以得到父类的属性和行为。
优点:提高代码的复用性,多个子类的相同代码可以放在父类中,相同的代码不用重复编写。
class Animals:
def __init__(self,name):
self.name = name
def eat(self):
print(self.name,"吃")
def drink(self):
print(self.name,"喝")
class Dog(Animals):
def bark(self):
print(self.name,"汪汪叫")
class Cat(Animals):
def bark(self):
print(self.name,"喵喵叫")
wangcai = Dog("旺财")
wangcai.eat()
wangcai.bark()
mimi = Cat("咪咪")
mimi.drink()
mimi.bark()
输出结果:
方法的覆盖
当子类和父类方法同名的时候,子类方法会覆盖父类的方法。
class Dog():
def __init__(self,name,age):
self.name = name
self.age = age
def bark(self):
print(f"{self.name} can bark")
def eat(self):
print(f"{self.name} 喜欢吃鸡肉")
class pipi(Dog):
def play(self):
print(f"{self.name} 会打滚")
def eat(self):
print(f"{self.name} 喜欢吃火腿")
dog1 = pipi("皮皮",2)
dog1.eat()
输出结果:
多态
定义:指对象可以有多种形态
优点:不同的对象调用相同的方法,产生不同的执行结果,增加代码的灵活度。
前提:以继承和重写父类方法为前提
class Animal():
def __init__(self,name):
self.name = name
def bark(self):
print(f"{self.name} can bark")
class Dog(Animal):
def bark(self):
print(f"{self.name}汪汪叫")
class Cat(Animal):
def bark(self):
print(f"{self.name}喵喵叫")
def animal_bark(animal):
if isinstance(animal, Animal):
animal.bark()
animal.bark()
wangcai = Dog("旺财")
animal_bark(wangcai)
mimi = Cat("咪咪")
animal_bark(mimi)
输出结果:
在上面的代码中,我们定义了一个 animal_bark() 方法,它可以介绍父类的对象,也可以接受子类的对象
使用多态,我们并不需要给每一个 子类定义一个调用 bark() 的方法,wangcai_bark(), mimi_bark(),只需要定义一个 animal_bark(), 在调用的时候给它传递对应的子类对象即可。