Python(完结)| 图形的面积

类和面向对象、封装、继承、多态

类和面向对象中的三大特性:封装、继承、多态

面向对象中的三大特性:封装、继承、多态

封装

封装是面向对象的三大特性之一,封装的目的主要是为了保证数据的安全性,假设有一个"圆形"的类Circle,它有半径radius这个属性

python 复制代码
class Circle:
    def __init__(self, radius):
        self.radius = radius

然后创建一个圆对象Circle

python 复制代码
circle = Circle(5) #创建一个对象,半径为5

但是这样,外部代码可以直接访问和修改半径,甚至将其设置为负数,这样的设计显然是不合理的。

python 复制代码
circle.radius = -10

为了防止这样的问题发生,可以通过封装隐藏对象中一些不希望被外部所访问到的属性或方法,为以下两步:

  • 将对象的属性名,修改为一个外部不知道的名字
  • 提供gettersetter来获取和设置对象的属性

一般情况下,对于对象的隐藏属性,使用双下划线开头:__xxx

python 复制代码
class Circle:
    def __init__(self, radius):
        #1.将属性名,改为外部不知道的一个名字
        self.__radius = radius  #使用双下划线前缀将属性私有化
    #2.定义get方法,获取属性
    def get_radius(self):
        return self.__radius
    #定义set方法,设置属性
    def set_radius(self, radius):
        self.__radius = radius

circle = Circle(5)  #创建一个新对象,半径为5
#只有通过对应的方法,才能修改属性
circle.set_radius(10)

使用封装,我们隐藏了类的一些属性,具体的做法是使用getter方法获取属性,使用setter方法设置属性,如果希望属性是只读的,则可以直接去掉setter方法,如果希望属性不能被外部访问,则可以直接去掉getter方法。

继承

在对象中,总有一些操作是重复的,比如说Person类具有姓名、身高、年龄等特征,并具有一些行走、吃饭、睡觉的方法,而我们要实现一个Teacher类,Teacher首先也是一个人,他也基本人的特征和方法,那我们是不是也应该用代码去实现这些特征和方法呢,这就势必会产生一些重复的代码。

可以采用"继承"的方式使得一个类获取到其他类中的属性和方法。在定义类时,可以在类名后的括号指定当前类的父类(超类), 子类可以直接继承父类中的所有属性和方法,从而避免编写重复性的代码,此外我们还可以对子类进行扩展。

假设,有一个图形类shape,它具有两个属性和一个方法,属性为颜色和类型,方法为求图形的的面积。

python 复制代码
class Shape:
    # 包含颜色和类型两个属性
    def __init__(self, shape_type, color):
        self.type = shape_type
        self.color = color
    #计算图形面积的方法
    def calculate_area(self):
        #pass表示空语句,不需要执行任何操作
        pass
shape = shape('shape','white')

还需要一个圆的类,继承自shape类

python 复制代码
class Circle(shape);
    def __init__(self, shape_type, color, radius):
        super().__init__(shape_type, color)
        self.radius = radius
    #计算圆的面积
    def calculate_area(self):
        return 3.14 * self.radius * self.radius

circle = Circle('circle', 'white', 10)
#计算圆的面积
circle.calculate_area()

在上面的示例代码中,图形类拥有两个属性和一个方法,圆的类在图形类的基础上添加了半径这个属性。

父类和子类中含有一些共同属性,在重写子类时,为了省略重复的代码,可以通过super()动态的获取当前类的父类, 并调用父类的__init__()方法从而初始化父类中定义的属性。

在子类和父类中都有calculate_area这个方法,这被称为方法的重写,子类会优先调用自己的方法而不是父类的方法。如果子类的对象调用一个方法,发现并没有提供这个方法,就会从当前对象的父类中寻找,如果父类中有则直接调用父类中的方法,如果还没有,就从父类的父类中寻找,就好像,当父亲和儿子都拥有一样东西,会优先使用自己的,如果发现自己没有,才会使用继承的方法。

多态

多态常常和继承紧密联系,它允许不同的对象对方法调用做出不同的响应。你可以使用基类定义通用的代码,然后在派生类中提供提供特定的实现,从而在调用方法时调用不同的方法:

python 复制代码
class Shape:
    #基类的计算面积的方法:
    def calculate_area(self):        
        pass
    

class Ciecle(Shape):
    def __init__(self, radius):
        self.radius = radius
    #Circle类的计算面积的方法
    def calculate_area(self):
        return 3.14 * self.radius * self.radius


class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height
        #Rectangle类的计算面积的方法
    def calculate_area(self):
        return self.width * self.height
        

#创建不同类型的图形对象
circle = Circle(2)
rectangle = Rectangle(4, 3)

#存放图形对象的列表
shapes = [circle, rectangle]

#计算面积
for shape in shapes:
    #列表中的每个元素都调用计算面积的方法
    area = shape.calculate_area()
    #输出面积
    print(f"Area: {area:.2f}")

上面的代码中,基类Shape实现了calculate_area方法,两个派生类Circle和Rectangle则是重写了calculate_area方法,它们有着不同的计算逻辑。之后我们创建了一个包含不同类型的图形对象的列表shapes,然后循环遍历该列表并调用calculate_area方法,景观调用的方法时根据对象的类型动态确定的,这其实就是多态的概念。

代码如下:

python 复制代码
#shape类
class Shape:
    def __init__(self, shape_type):
        self.type = shape_type
        
    def caculate_area(self):
        pass
    
# Circle类,包含 radius, 计算面积的方法 
class Circle(Shape):
    def __init__(self, radius):
        super().__init__("Circle")
        self.radius = radius
        
    def caculate_area(self):
        return 3.14 * self.radius * self.radius

#  Rectangle类,包含 width 和 height, 计算面积的方法
class Rectangle(Shape):
    def __init__(self, width, height):
        super().__init__("Rectangle")
        self.width = width
        self.height = height
    
    def caculate_area(self):
        return self.width * self.height
        
shapes = []

while True:
    s = input().split()
    if s[0] == "end":
        break
    
    if s[0] == "rectangle":
        width, height = map(int, s[1: 3])
        # width, height = int(s[1]), int(s[2])
        shapes.append(Rectangle(width, height))
    elif s[0] == "circle":
        radius = int(s[1])
        shapes.append(Circle(radius))
    
for shape in shapes:
    print(f"{shape.type} area: {shape.caculate_area():.2f}")
相关推荐
初遇你时动了情13 分钟前
uniapp 城市选择插件
开发语言·javascript·uni-app
编程修仙28 分钟前
Collections工具类
linux·windows·python
芝麻团坚果44 分钟前
对subprocess启动的子进程使用VSCode python debugger
linux·ide·python·subprocess·vscode debugger
EterNity_TiMe_1 小时前
【论文复现】神经网络的公式推导与代码实现
人工智能·python·深度学习·神经网络·数据分析·特征分析
Stara05111 小时前
Git推送+拉去+uwsgi+Nginx服务器部署项目
git·python·mysql·nginx·gitee·github·uwsgi
zongzi_4941 小时前
二次封装的天气时间日历选择组件
开发语言·javascript·ecmascript
kikyo哎哟喂1 小时前
Java 代理模式详解
java·开发语言·代理模式
duration~1 小时前
SpringAOP模拟实现
java·开发语言
一条晒干的咸魚1 小时前
【Web前端】实现基于 Promise 的 API:alarm API
开发语言·前端·javascript·api·promise
hence..2 小时前
Vscode写markdown快速插入python代码
ide·vscode·python