面对对象编程
一、面对对象的概念
1.1 面对对象
- 是一种思维,使用这种思维设计的程序能够将数据和对数据进行的操作封装在一起组成一个类,可以通过类创建对象,通过对象之间的交互来解决问题。
- 面对对象三大要素:封装、继承和多态性。
1.2 面对对象编程(Object Oriented Programming)
- 是一种编程方式,此编程方式的落地需要使用’类’和’对象’来实现。所以,面对对象编程其实就是对’类’和’对象’的使用。
1.3 面对对象和面对过程的区别
- 面对对象编程:一遇到问题马上想有没有一个已经存在的对象拥有解决这个问题的能力,如果有,直接拿过来使用;反之,再自己创造这样一个对象。
- 面对过程编程:一遇到问题马上想通过代码来解决问题的逻辑。
1.4 面向过程、函数、面向对象这三者的实际应用!
-
面向过程: 主要是对解决一个问题的过程重复操作。
-
函数:先封装,将解决问题的方法打包成一个模块,相当于生活中一个固定执行步骤的机器,然后再向其中传入参数,循环调用。
-
面向对象:先创造出能够解决问题的对象,然后给这个对象提供一些属性和方法。最后再调用这些属性和方法。
二、认识类和对象
2.1 类的认识
- 类是具有相同的属性和行为事物的统称。
- 类是抽象的,在使用的时候通常使用这个类的一个具体的存在。
- 一个类可以有多个对象。
2.2 对象的认识
- 对象是真实存在的能够看到和摸到的具体的事物。
- 对象都有属性和行为,每个对象都是独一无二的,而且对象一定属于某个类(型)。
- 方法是和实例绑定的函数。
2.3 类和对象之间的关系
一个类可以由多个对象组成,其关系可以参照下图。
2.4 类和对象如何使用
a) 使用关键字 " class " 定义一个类。
# 定义一个学生类:使用关键字class,后面接类名。
class Student:
# 在学生类中给学生构造方法(对象方法)
def study(self,English):
return '学生在学习{English}'
def play(self, game):
return f'学生在玩{game}'
b) 通过类实例化对象。
# 使用构造器语法创建对象
s1 = Student()
print(s1)
# <__main__.Student object at 0x0000027D0FA25EE0>
# 构建一个对象
# s1是一个实例化个体
c) 对象调用对象方法。
# a、对象.对象方法(参数)
print(s1.study(English))
# 学生在学习English
# b、类.对象方法(对象,参数)
print(Student.play(s1, '王者荣耀'))
# 学生在玩王者荣耀
2.5 对象属性和类属性。
-
id: 查看某个数据类型在内存中的地址
-
self: 行业内约定俗成的一个名字,谁调用方法,就指向谁。
也可指代被实例化出来的对象,相当于一个类中各部分传参的介质
class Student:
# 定义类属性
schoolUniform = '校服'
# 初始化方法(设置对象属性):def _init_
def _init_(self, name, sex, age):
self.name = name
self.sex = sex
self.age = age
# 在学生类中给学生构造方法(对象方法)
def study(self):
return f'{self.age}岁穿着{Student.schoolUniform}'的{self.name}在学习
def play(self, game):
return f'{self.name}在玩{game}'
# 给某个对象赋予属性(对象属性)
s1 = Student('张三','男',18)
print(s1)
# <__main__.Student object at 0x000001CDDD80A400>
print(s1.play('王者荣耀'))
print(s1.study())
# 张三在玩王者荣耀
# 18岁穿着校服的张三在学习
# a、调用类属性
# 1、类名.类属性
print(Student.schoolUniform)
# 校服
# 2、对象.类属性
print(s1.schoolUniform)
# 校服
# b、调用对象属性
# 用法:1、对象.对象属性
print(s1.name)
# 张三
2.6 类和对象属性的练习
- 定义一个圆类,实现两个圆之间圆心距离的计算,该类中包括属性radius(半径),还包括__init__()、get_perimeter周长()和get_area面积()共三个方法。设计完成后,创建Circle类的对象求圆的周长和面积。
# 定义一个圆类
class Circle:
# 定义一个类的属性
pi = 3.14
# 初始化方法,设置对象属性
def _init_(self, radius):
self.radius = radius
# 在圆类中,给圆类构造方法(方法与方法之间互相调用)
def perimeter(self):
return pi*2*self.radius
def area(self):
return 3.14*self.radius**2
# 实例化圆对象
circle = Circle(6)
print(f'周长是{circle.perimeter()},面积是{circle.area}')
三、对象方法、类方法、静态方法
3.1 三种方法的区别:
-
对象方法:在类中定义的对象能够做的事情的方法,叫做对象方法。方法中第一个参数为self,指向对象。
-
类方法:在类中给类定义的方法,需要写语法糖@classmethod,类方法中第一个参数是cls,指向类。
-
静态方法:在类中定义的普通方法,需要写语法糖@staticmethod,既不指向类,也不指向对象,仅仅是依附于类。
3.2 这三种方法如何去调用?
- 对象方法只能是对象调用。
- 类方法既可以直接使用类进行调用,也可以使用对象调用。
- 静态方法既可以直接使用类进行调用,也可以使用对象调用。
3.3 对象方法、类方法以及静态方法调用的示例
- 定义一个三角形类,判断能不能构成一个三角形。
class triangle:
# 初始化对象的属性
def _init_(self, a, b, c):
self.a = a
self.b = b
self.c = c
# 调用类方法,classmethod装饰器。
@classmethod
def isTriangle(cls, a, b, c):
if a + b > c and a + c > b and b + c > a:
return True
else:
return False
# 调用静态方法
@staticmethod
def isTriangle_1(a, b, c):
is a + b > c and a + c > b and b + c > a:
return True
else:
return False
# 调用对象方法
def permeter(self):
return (self.a + self.b + self.c)/2
def area(self):
'''海伦公式(秦九韶公式)'''
p = self.a + self.b + self.c
return (p / 2 * (p / 2 - self.a) * (p / 2 - self.b) * (p / 2 - self.c)) ** 0.5
a, b, c = 3, 4, 10
if triangle.isTriangle(a, b, c):
t1 = triangle(a, b, c)
print(t1.permeter())
print(t1.area())
else:
print('这三条边不能构成三角形')
# 12
6.0
- 定义一只狗的类,定义类的属性为狗的皮肤颜色,分别去调用对象方法、类方法和静态方法。
# 定义一只狗的类
class Dog:
# 定义类的属性
dogNum = {'黄色': 30, '黑色': 20, '白色': 0}
def __init__(self, name, color, weight):
self.name = name
self.color = color
self.weight = weight
# 对象方法(实例方法)可以访问对象属性,只能通过对象名访问
def bark(self):
return f'{self.name}正在叫'
# 类方法可以访问类属性,可以通过对象名或类名访问
@classmethod
def dog_num(cls):
num = 0
for i in cls.dogNum.values():
num += i
return num
# 静态方法不能访问类属性,也不能访问对象属性;可以通过对象名或类名访问
@staticmethod
def total_weight(dogs):
total = 0
for j in dogs:
total += j.weight
return total
d1 = Dog('大黄', '黄色', 10)
print(d1.bark())
# 对象调用类方法
print(f'共有{d1.dog_num()}条狗')
# 类调用类方法
print(f'共有{Dog.dog_num()}条狗')
d2 = Dog('旺财', '黑色', 8)
d2.bark()
# 静态方法可以通过对象名或者类名访问
print(f'狗共重{Dog.total_weight([d1, d2])}公斤')
# 大黄正在叫
# 共有50条狗
# 共有50条狗
# 狗共重18公斤
四、魔法方法
4.1 魔法方法的定义
- 魔法方法是python定义的一系列由双下划线 + 方法名组成的特殊方法。
- 魔法方法是Python内置的方法,不需要主动调用,它们总能够在适当的时候被自动调用。
- 魔法方法的第一个参数是 cls 或者 self。
- cls: 代表当前类的名称。
- self: 代表当前类的名称。
4.2 常见的魔法方法有哪些?
init | 初始化对象属性 |
_del | python内存回收机制(ARC),python可以自动的在一个对象被销毁后回收内存。 |
_str | 将其他数据类型转字符串:a.%s、str()等被调用时会自动触发本方法。 |
_repr | 是 _str 的备胎,没有 _str 的情况下就执行 repr。 |
_add | 定义了加法行为。 |
_sub | 定义了减法行为。 |
_mul | 定义了乘法行为。 |
_truediv | 定义了真除法( \ )行为。 |
_floordiv | 定义了整除行为。 |
_mod | 定义了取模算法(取余)行为。 |
4.3 简单魔法方法的使用示例:
- 定义一个学生类,附加属性姓名和年龄,用魔法方法来实现。
# 定义一个学生类
class Student:
# 初始化对象属性
def _init_(self, name, age):
self.name = name
self.age = age
#调用魔法方法,构造一个我们想要打印的效果。
def _repr_(self):
return f'{self.name}:{self.age}'
# 给某个对象赋予属性
s1 = Student('张三',18)
print(s1)
# 这是18岁的张三
- 定义一个类描述平面上的点,要求提供计算到另一个点距离的方法。
from math import sqrt
# 定义一个点的类
class Point(object):
# 初始化点的属性,点的坐标
def _init_(self, x, y):
self.x = x
self.y = y
def move_to(self, x, y):
'''移动到指定位置'''
self.x = x
self.y = y
def move_by(self, dx, dy):
'''移动指定的增量'''
self.x += dx
self.y += dy
# 调用对象方法(解决问题)
def distance(self, other):
'''计算与另一个点的距离'''
dx = self.x - other.x
dy = self.y - other.y
return sqrt(dx ** 2 + dy ** 2)
# 魔法方法
def _str_(self):
return f'str{self.x}, str{self.y}'
def main():
p1 = Point(3, 5)
p2 = Point()
print(p1)
print(p2)
p2.move_by(-1, 2)
print(p2)
print(p1.distance_to(p2))
if __name__ == '__main__':
main()
- 定义一个类描述数字时钟
from time import sleep
class Clock(object):
'''构建一个数字时钟'''
# 构建时钟的初始化方法
def __init__(self, hour=0, minute=0, second=0):
self._hour = hour
self._minute = minute
self._second = second
def run(self):
'''时钟转动'''
self._scond += 1
if self._second == 60:
self.second = 0
self._minute += 1
if self._minute == 60:
self._minute = 0
self._hour += 1
if self._hour == 24:
self._hour = 0
def show(self):
'''显示时钟的时间'''
return f'{self._hour}:{self._minute}:{self._second}'
def main():
clock = Clock(23, 59, 58)
while True:
print(clock.show())
sleep(1)
clock.run()
if __name__ == '__main__':
main()
# 打印结果为: 23:59:58