面对对象编程理解

2021/7/3 17:21:33

本文主要是介绍面对对象编程理解,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

这里写目录标题

    • 序言
    • 类的定义与实例化
        • 类的定义
    • 类的封装
    • 继承
    • 多态

序言

参考的文章资源是http://www.coolpython.net/python_primary/oop/polymorphism.html
面向对象编程——Object Oriented Programming,简称OOP。与之相对应的另一种程序设计思想是面向过程编程。
OOP是从自然而来的,自然中,我们了解类和实例,比如爬行类、哺乳类、昆虫类等等。在哺乳类下面还有个灵长类。而我们人类属于灵长类。每一个人便是人类的一个实例。

面对对象的最核心的三个特征是:封装+继承+多态

类的定义与实例化

类的定义

因为python也是一种面对对象编程语言。所以也有类的概念。提供了面对对象的所有标准特性。比如允许一个类继承多个基类。 子类可以覆盖父类的方法等等。

使用class来定义一个类

class Stu:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def run(self):
        print("{name} is running".format(name=self.name))

理解:
(1)上面的Stu 是类的名字。你可以使用__name__ 来访问

print(Stu.__name__)
输出:
Stu

(2)在类里面,用def 关键词 来定义函数。但在类中 我们管这种函数为方法。称为实例方法。
(3)__init__是初始化函数。当实例被构造出来以后,使用__init__方法来初始化实例属性。self是实例, name 和 age都是实例的属性。 再看看为什么self是 实例。

s = Stu('小明', 18)
s.run()
输出:<class '__main__.Stu'>
小明 is running

这里我们看到s便是创建出来的实例。也就是之前所设置的self。
由于在初始化函数的时候,有name和age这两个属性。因为我们在创建实例的时候,必须输入这两个参数,在这里是’小明’, 18。
而s.run() 这行代码是在调用实例的run方法。
总结来说,我们上面创立了 实例的两个属性 name和age;也定义了实例的run方法。
所以说实例有相对应的方法和属性。

(4)对对象的属性进行修改

class Stu:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def info(self):
        print("{name}今年{age}岁".format(name=self.name, age=self.age))

    def run(self):
        print("{name} is running".format(name=self.name))

    def print(self):
        print("ok")

s = Stu("小刚", 18)
s.info()

print(s.name)
s.age = 20
s.info()

输出:
小刚今年18岁
小刚
小刚今年20岁

(5)使用类来组合数据和方法
使用一个例子说明:
一个名为 成绩单 的文件中保存了学生的考试成绩,内容如下

姓名  语文  数学  英语
小红  90   95    90
小刚  91   94    93

编写程序读取该文件,使用合适的数据类型保存这些数据,输出每一个人的各个科目和分数,并计算每个学生的总的分数。

如果是面对对象的编程,则这样子写:

stus = []
with open('成绩单', 'r', encoding='utf-8') as file:
    lines = file.readlines()
    for i in range(1, len(lines)):
        line = lines[i]
        arrs = line.split()
        stus.append(arrs)
for stu in stus:
    msg = "{name}的各科成绩如下: 语文:{yw_score}, " \
          "数学:{sx_score}, 英语:{en_score}".format(name=stu[0],
                                                yw_score=stu[1],
                                                sx_score=stu[2],
                                                en_score = stu[3]
                                                )
    print(msg)
    msg = "{name}的总成绩是{socre}".format(name=stu[0],
                                      socre=int(stu[1])+int(stu[2])+int(stu[3]))

    print(msg)

但如果用面对对象的编程,则写成:

class Stu:
    def __init__(self, name, yw, sx, en):
        self.name = name
        self.yw = yw
        self.sx = sx
        self.en = en

    def score_sum(self):
        return self.yw + self.sx + self.en

    def print_score(self):
        msg = "{name}的各科成绩如下: 语文:{yw_score}, " \
          "数学:{sx_score}, 英语:{en_score}".format(name=self.name,
                                                yw_score = self.yw,
                                                sx_score = self.sx,
                                                en_score = self.en
                                                )
        print(msg)
        msg = "{name}的总成绩是{score}".format(name=self.name, score=self.score_sum())
        print(msg)

stus = []
with open('成绩单', 'r', encoding='utf-8') as file:
    lines = file.readlines()
    for i in range(1, len(lines)):
        line = lines[i]
        arrs = line.split()
        s = Stu(arrs[0], int(arrs[1]), int(arrs[2]), int(arrs[3]))
        stus.append(s)
for stu in stus:
    stu.print_score()

从代码的可阅读性上看,使用类组织数据和方法显然更具有优势,而且,类这种概念,更加符合我们人类的思维。
使用类组织数据和方法,扩展性更好,可以随时添加新的属性和方法,比如,我想输出学生最高的科目分数,那么,我只需要修改类就可以了。
而面对过程的编程则需要大量的修改,可维护性很差。

类的封装

隐藏实现的细节,只对外公开我们想让他们使用的属性和方法,这就叫做封装。
封装的目的在于保护类内部数据结构的完整性, 因为使用类的用户无法直接看到类中的数据结构,只能使用类允许公开的数据,很好地避免了外部对内部数据的影响,提高了程序的可维护性。

(1)私有属性和方法

假设,你和你的同事一起做项目,现在,需要你写一个类让同事使用,这个类,你定义了5个属性,10个方法,但是呢,你的同事其实只会用到其中一个方法,剩下那9个,都是用到的那个方法在执行过程中调用的方法。

那么问题来了,你明确告诉他,你就调用那个A方法就好了,其他方法,你不要使用,不然,可能会影响结果。如果你的同事是个很安分守己的人,他听从了你的建议,老老实实的调用A方法,其他方法,他一概不动,这样就是安全的。

可是过了几天,来了新同事,他偏偏不听话,非得调用剩余的9个方法,它觉得,自己调用那9个方法,可以更好的实现功能,结果呢,出了大问题了,那9个方法,他用的不好,导致程序出错了。

我们写了一个类,有些属性,有些方法,我们不希望被其他人使用,因为那样很容易就产生错误,那么这时,我们就需隐藏实现的细节,只对外公开我们想让他们使用的属性和方法,这就叫做封装。就好比把一些东西用一个盒子封装起来,只留一个口,内部让你看不见

如何才能做到这一点呢?

在python里,如果属性和方法前面是双下划线,那么这个属性和方法就变成了私有的属性。下面是一个例子。

class Animal:
    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    def __run(self):
        print("run")

a = Animal('猫', 2)
a.__run()
print(a.__name, a.__age)

这样就会发生错误,你没法使用 run的这个方法和name、age这两个属性。
还有一个问题是 如果设置年龄是10000岁呢,这就显然不对。所以在类中也设置这样的方法,避免这种情况。

class Animal:
    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    def set_age(self, age):
        if age > 100 or age < 1:
            raise Exception("年龄范围错误")
        self.__age = age

    def get_age(self):
        return self.__age

    def __run(self):
        print("run")

a = Animal('猫', 2)
a.set_age(3)
print(a.get_age())

继承

继承是一种创建新类的方式,python中的继承,可以继承一个或者继承多个父类,新建的类被称之为派生类或者子类,被继承的类是父类。

(1)单继承

class Car(object):
	def __init__(self, speed,brand):
		self.speed = speed
		self.brand = brand
	def run(self):
		print("{brand}在行驶".format(brand = self.brand))
# 燃油车
class Gasolinecar(Car):
	def __init__(self,speed,brand,price):
		super().__init__(speed,brand)
		self.price = price

class Audi(Gasolinecar):
	pass

honda = Gasolinecar(130,'本田', 13000)
honda.run()

audi_car = Audi(100,'奥迪',10000)
audi_car.run()

输出:
本田在行驶
奥迪在行驶

继承是指 子类即将拥有父类的方法和属性。同时新增子类的属性和方法。
Gasolinecar类里,我没有写run方法,但是Gasolinecar的父类定义了run方法,因此,Gasolinecar也有这个方法,因此这个类的对象honda可以使用run方法。

Audi类没有定义任何方法,但是它继承了Gasolinecar,因此,Gasolinecar有的属性和方法,它都拥有,这里就包括了__init__方法。

super()可以用来调用父类的方法,Gasolinecar多传了一个price属性,其父类的__init__方法里有两个参数,因此,可以先调用父类的__init__方法初始化speed, brand,然后在初始化price。

多态

(1)重写
多态这个概念依赖于继承,因为继承,使得子类拥有了父类的方法,这里就产生了一个问题,如果子类有一个方法和父类的方法同名,那么子类在调用这个方法时,究竟是调用子类自己的方法,还是父类的方法?

class Base():
    def print(self):
        print("base")


class A(Base):
    def print(self):
        print("A")


a = A()
a.print()
输出:
A

父类和子类都有print方法,那么子类A的对象a调用print方法时,调用的是谁的print方法呢?

答案是子类的print方法,如果A类没有定义print方法,那么a.print()调用的是父类的print方法,但是A类定义了print方法,这种情况称之为重写,A类重写了父类的print方法

(2)多态的表现形式

class Animal:
    def run(self):
        raise NotImplementedError

class People(Animal):
    def run(self):
        print("人在行走")


class Pig(Animal):
    def run(self):
        print("猪在跑")


p1 = People()
p1.run()

p2 = Pig()
p2.run()

输出:
人在行走
猪在跑

People和 Pig 都继承了Animal,都是动物,是同一类事物,他们都有run方法,但是最终的运行结果却不一样,这就是多态,同一类事物有多种形态



这篇关于面对对象编程理解的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程