• 0

  • 490

python面向对象编程的基本概念

perpetual

python交流

2星期前

作者|HIMANSHI SINGH 编译|VK 来源|Analytics Vidhya

介绍

在学习面向对象编程时,我决定深入研究它的历史,结果发现它很迷人。术语“面向对象编程”(OOP)是Alan Kay 在1966年研究生院时提出的。

Simula语言是第一种具有面向对象编程特点的编程语言。它是在1967年开发的,用于制作模拟程序,其中最重要的信息称为对象。

尽管OOPS自20世纪60年代初就在市场上,但在20世纪90年代,OOPS开始因为C++而增长。

除此之外,这种编程技术已经被包括Python在内的各种编程语言所采用,它的应用几乎遍及所有领域,如实时系统、人工智能、专家系统、CS系统、面向对象数据库等等。

因此,在本文中,我将解释Python中面向对象编程的基本概念。

目录

  1. 什么是面向对象编程?

  2. 面向对象编程(OOP)与面向过程编程(POP)

  3. OOPs的主要概念

    1. 什么是类?
    2. 对象和对象实例化
    3. 类方法
    4. Python类中的继承
    5. 封装
    6. 多态性
    7. 数据抽象

什么是面向对象编程?

面向对象编程(OOP)就是创建“对象”。对象是一组相互关联的变量和函数。这些变量通常称为对象的属性,函数称为对象的行为。这些对象为程序提供了一个更好、更清晰的结构。

例如,汽车可以是一个对象。如果我们把汽车当作一个对象,那么它的属性就是——颜色、型号、价格、品牌等等,它的行为/函数是加速、减速、换挡。

另一个例子——如果我们把狗当作一个物体,那么它的属性就是——它的颜色、品种、名字、体重等,而它的行为/函数是行走、吠叫、玩耍等。

面向对象编程因其在编程中实现了对象、隐藏、继承等现实实体而闻名。它使可视化更容易,因为它接近真实世界的场景。

面向对象编程(OOP)与面向过程编程(POP)

OOP和过程式编程的基本区别是

  • 一种思考POP的方法就是你做柠檬水的方式。制作柠檬水的过程包括——首先根据需要取水,然后在水中加入糖,然后在混合物中加入柠檬汁,最后将整个溶液混合。这样你的柠檬水就准备好了。同样,POP也需要一定的步骤。程序程序由函数组成。这意味着在POP方法中,程序被划分为特定于不同任务的函数。这些功能按特定的顺序排列,程序的控制按顺序进行。

  • 而OOP程序是由对象组成的。面向对象方法将程序划分为对象。这些对象是将现实世界对象的属性和行为捆绑在一起的实体。

  • POP只适用于小任务。因为随着程序长度的增加,代码的复杂性也随之增加。最后变成了一个函数网。而且,它变得很难调试。OOP通过更清晰、以更不复杂的结构来解决这个问题。它允许以继承的形式重新使用代码。

  • 另一个重要的是,在面向过程的编程中,所有函数都可以访问所有数据,这意味着缺乏安全性。假设你想保护来自世界各地的凭据或任何其他关键信息。那么程序化方法就不能为你提供这种安全性。因为这个OOP帮助你实现了一个称为封装的惊人功能,它允许我们隐藏数据。不用担心,在本文的后半部分,我将详细介绍这一点以及面向对象编程的其他概念。现在,只需理解OOP支持安全性,POP不支持。

  • 编程语言如C、Pascal和Basic使用过程方法,而java、Python、JavaScript、PHP、Scala和C++是提供面向对象方法的主要语言。

OOPs的主要概念

在本节中,我们将深入探讨OOP的基本概念。我们将讨论以下主题

  1. 对象

  2. 方法

  3. 继承

  4. 封装

  5. 多态性

  6. 数据抽象

1.什么是类?

这个问题的直接答案是:类是对象的集合。与原始数据结构不同,类是用户定义的数据结构。它们使代码更易于管理。

让我们看看如何定义下面的类

class class_name:
    class body
复制代码

我们用关键字“class”在类名和分号后面定义一个类。在使用缩进之后,我们会考虑有缩进的所有东西。为了让这更容易理解,让我们看一个例子。

以汽车展厅为例。你要存储每辆车的详细信息。让我们首先定义一个类

class Car:
    pass
复制代码

就这样!

注意:我用pass语句代替了它的主体,因为主要目的是展示如何定义一个类,而不是它应该包含什么。

在详细介绍之前,首先要了解对象和实例化。

2.对象和对象实例化

当我们定义一个类时,只会创建对象的描述或蓝图,在这个过程中没有内存分配。而对象实例具有内存分配,它包含真实的数据或信息。

实例化是创建一个类的实例。让我们创建上面定义的类的对象-

obj1 = Car()
复制代码

这样就创建了一个对象实例。请注意,你可以根据你的选择更改对象名称。

尝试打印此对象

print(obj1)
复制代码

因为我们的类是空的,所以它返回存储对象的地址,即0x7fc5e677b6d8

在继续学习之前,你还需要了解类的构造函数。

类构造函数

到目前为止,我们有一辆空的车,是时候把车的特征填满我们的类了。类构造函数的工作是在创建类的对象时将值分配给类的数据成员。

一辆车可以有不同的属性,如名称、颜色、型号、品牌、发动机功率、重量、价格等。我们将仅选择其中几项以便于理解。

class Car:
    def __init__(self, name, color):
        self.name = name
        self.color = color
复制代码

因此,car或任何其他对象的属性必须位于一个我们称为 __init__( )的方法中。此方法也称为构造函数方法。每当类的对象被构造时,就调用构造函数方法。

现在,让我们来讨论一下 __init__( )方法的参数。所以,这个方法的第一个参数必须是self。然后才是剩下的参数

构造函数方法中的两个语句是

  1. self.name = name
  2. self.color = color:

这将创建新的属性,即name和color,然后将参数的值分配给它们。“self”关键字表示类的实例。通过使用“self”关键字,我们可以访问类的属性和方法。它在方法定义和变量初始化中很有用。“self”在每次定义方法时都显式使用。

注意:你也可以在此方法之外创建属性。但是这些属性对整个类都是通用的,必须给它们赋值。

假设你的展厅中的所有汽车都是Sedan,而不是一次又一次地指定它,你可以通过创建一个属性来将car_type的值固定为Sedan。

class Car:
    car_type = "Sedan"                 #类属性
    def __init__(self, name, color):
        self.name = name               #实例属性
        self.color = color             #实例属性
复制代码

这里,实例属性是指构造函数方法中的属性,在这个例子中是self.name 和 self.color。类属性是指构造函数方法之外的属性,在这个例子中是car_type。

3.类方法

到目前为止,我们已经添加了汽车的属性。现在是时候添加一些行为了。方法是我们用来描述对象行为的函数。它们也在类中定义。请看下面的代码

class Car:   
    car_type = "Sedan" 

    def __init__(self, name, mileage):
        self.name = name 
        self.mileage = mileage 

    def description(self):                 
        return f"The {self.name} car gives the mileage of {self.mileage}km/l"

    def max_speed(self, speed):
        return f"The {self.name} runs at the maximum speed of {speed}km/hr"
复制代码

在类中定义的方法(而不是构造函数方法)称为实例方法。此外,这里有两个实例方法,description()和max_speed()。

  • description()—此方法返回一个字符串,其中包含汽车的描述,如名称和里程数。此方法没有其他参数。此方法正在使用实例属性。
  • max_speed()—此方法有一个附加参数,并返回一个显示车辆名称及其速度的字符串。

请注意,附加参数speed没有使用“self”关键字。因为speed不是一个实例变量,所以我们不使用self关键字作为前缀。让我们为上面描述的类创建一个对象。

obj2 = Car("Honda City",24.1)
print(obj2.description())
print(obj2.max_speed(150))
复制代码

我们所做的是创建一个类car的对象并传递所需的参数。为了使用object_name.method_name().

description()方法没有任何附加参数,因此在调用它时没有传递任何参数。

max_speed()方法有一个附加参数,因此我们在调用它时传递了一个参数。

注意:三件重要的事要记住

  1. 可以创建一个类的任意数量的对象。

  2. 如果方法需要n个参数,而你没有传递相同数量的参数,则会发生错误。

  3. 参数的顺序很重要。

让我们一个个来看看

  1. 创建一个类的多个对象
class Car:
    def __init__(self, name, mileage):
        self.name = name 
        self.mileage = mileage 

    def max_speed(self, speed):
        return f"The {self.name} runs at the maximum speed of {speed}km/hr"
复制代码
Honda = Car("Honda City",21.4)
print(Honda.max_speed(150))

Skoda = Car("Skoda Octavia",13)
print(Skoda.max_speed(210))
复制代码
  1. 参数数目错误
class Car:

    def __init__(self, name, mileage):
        self.name = name 
        self.mileage = mileage
复制代码
Honda = Car("Honda City")
print(Honda)
复制代码

因为我们没有提供第二个参数,所以我们得到了这个错误。

  1. 参数顺序
class Car:

    def __init__(self, name, mileage):
        self.name = name 
        self.mileage = mileage 

    def description(self):                
        return f"The {self.name} car gives the mileage of {self.mileage}km/l"
复制代码
Honda = Car(24.1,"Honda City")
print(Honda.description())
复制代码

搞混了!因为我们改变了论点的顺序。

现在,面向对象编程有四个基本概念:继承、封装、多态和数据抽象。为了理解OOPs,了解所有这些非常重要。到目前为止,我们已经介绍了面向对象编程的基本知识,让我们进一步深入。

4. Python类中的继承

继承是一个类继承另一个类的属性和方法的过程。被继承的类称为父类。从父类继承属性的类是子类。

有趣的是,除了继承的属性和方法外,子类可以有自己的属性和方法。

如何继承父类?使用以下语法:

class parent_class:
body of parent class

class child_class( parent_class):
body of child class
复制代码

让我们看看实现

class Car:          #父类

    def __init__(self, name, mileage):
        self.name = name 
        self.mileage = mileage 

    def description(self):                
        return f"The {self.name} car gives the mileage of {self.mileage}km/l"

class BMW(Car):     #子类
    pass

class Audi(Car):     #子类
    def audi_desc(self):
        return "This is the description method of class Audi."
复制代码
obj1 = BMW("BMW 7-series",39.53)
print(obj1.description())

obj2 = Audi("Audi A8 L",14)
print(obj2.description())
print(obj2.audi_desc())
复制代码

我们创建了两个子类,即“BMW”和“Audi”,它们继承了父类“Car”的方法和属性。在BMW类我们没有提供额外的特征和函数。而Audi内部的一个附加方法。

注意在obj1.description()和obj2.description()的帮助下,父类的实例方法description()是如何被子类的对象访问的。此外,还可以使用obj2.Audi_desc()访问Audi类的单独方法。

5.封装

正如我在文章开头部分提到的,封装是确保安全性的一种方法。基本上,它将数据隐藏起来,不让外人访问。例如,如果我们想让某些值不被客户或任何未经授权的人访问,那么封装就是确保这一点的方法。

你可以在方法或属性的名称前使用一个下划线( _ ) 来声明受保护的方法或属性。例如 self._name或def _method();这两行都说明属性和方法是受保护的,不应在类和子类的访问之外使用,而是可以由类方法和对象访问。

Python只是将‘_‘ 用作编码约定,告诉你应该在类的范围内使用这些属性/方法。你仍然可以像往常一样访问定义为受保护的变量和方法。

现在,为了实际防止从类范围之外访问属性/方法,可以使用“私有成员”。若要将属性/方法声明为私有成员,请在前缀中使用双下划线( __ ) 。例如– self.__name或def __method();这两行都说明属性和方法是私有的,不能从类外部进行访问。

class car:

    def __init__(self, name, mileage):
        self._name = name                #受保护属性
        self.mileage = mileage 

    def description(self):                
        return f"The {self._name} car gives the mileage of {self.mileage}km/l"
复制代码
obj = car("BMW 7-series",39.53)

#通过类方法访问受保护变量
print(obj.description())

#直接从外部访问受保护变量
print(obj._name)
print(obj.mileage)
复制代码

请注意我们如何访问受保护的变量而没有任何错误。很明显,对变量的访问仍然是公开的。让我们看看封装是如何工作的

class Car:

    def __init__(self, name, mileage):
        self.__name = name              #私有变量
        self.mileage = mileage 

    def description(self):                
        return f"The {self.__name} car gives the mileage of {self.mileage}km/l"
复制代码
obj = Car("BMW 7-series",39.53)

#通过类方法访问私有变量
print(obj.description())

#直接从外部访问私有变量
print(obj.mileage)
print(obj.__name)
复制代码

当我们尝试使用description()方法访问私有变量时,没有遇到任何错误。但是当我们尝试直接在类外部访问私有变量时,Python给出了一个错误,声明:car对象没有属性''__name'。

你仍然可以使用该属性的修饰名称直接访问它。Name mangling(命名修饰)是一种从外部访问类成员的机制。Python解释器将任何带有“__var”的标识符重写为“_ClassName__var”。使用这个你可以从外部访问类成员。

class Car:

    def __init__(self, name, mileage):
        self.__name = name              #私有变量     
        self.mileage = mileage 

    def description(self):                
        return f"The {self.__name} car gives the mileage of {self.mileage}km/l"
复制代码
obj = Car("BMW 7-series",39.53)

#通过类方法访问私有变量
print(obj.description())

#直接从外部访问私有变量
print(obj.mileage)
print(obj._car__name)      #名称修饰
复制代码

请注意,这个规则的设计是想处理某些情况,例如在调试器中。但是正常编程中不推荐使用

6.多态

多态(Polymorphism)一个希腊单词。如果我们分解Polymorphism这一术语,我们会得到“poly”(多)和“morph”(变形)形式。所以多态性意味着有多种形式。在OOP中,它指的是具有相同名称但具有不同功能的函数。

class Audi:
  def description(self):
    print("This the description function of class AUDI.")

class BMW:
  def description(self):
    print("This the description function of class BMW.")
复制代码
audi = Audi()
bmw = BMW()
for car in (audi,bmw):
 car.description()
复制代码

使用对象audi调用函数时,将调用audi类的函数;使用对象bmw调用函数时,将调用bmw类的函数。

7.数据抽象

我们使用抽象来隐藏函数的内部细节或实现,只显示其功能。这与你在不知道汽车原理的情况下知道如何驾驶汽车,或者你知道如何用开关打开或关闭灯,但你不知道插座后面发生了什么的情况类似。

任何具有至少一个抽象函数的类都是抽象类。为了首先创建一个抽象类,你需要从ABC模块导入ABC类。这使你可以在其中创建抽象方法。ABC代表抽象基类。

from abc import ABC

class abs_class(ABC):
    Body of the class
复制代码

重要的是,不能为抽象类创建实例对象。例如-

from abc import ABC, abstractmethod

class Car(ABC):
    def __init__(self,name):
        self.name = name 

 @abstractmethod
    def price(self,x):
        pass
复制代码
obj = Car("Honda City")
复制代码

现在的问题是我们如何准确地使用这个抽象。答案是使用继承。

from abc import ABC, abstractmethod

class Car(ABC):
    def __init__(self,name):
        self.name = name

    def description(self):
        print("This the description function of class car.")

    @abstractmethod
    def price(self,x):
        pass
class new(Car):
    def price(self,x):
        print(f"The {self.name}'s price is {x} lakhs.")
复制代码
obj = new("Honda City")

obj.description()
obj.price(25)
复制代码

Car是从ABC模块的ABC类继承的抽象类。注意我在抽象类中有一个抽象方法(price())和一个具体方法(description())。这是因为抽象类可以同时包含这两种类型的函数,而普通类则不能。从这个抽象类继承的另一个类是new。new的price()方法是我们重写了抽象类Car的price方法。

在用户从new()类创建对象并调用price()方法之后,new()类中price方法的定义就开始发挥作用了。这些定义对用户是隐藏的。抽象方法只是提供一个声明。需要提供子类的定义。

但是,当为new()类(即obj)的对象调用description()方法时,将调用Car的description()方法,因为它不是抽象方法。

结尾

总之,在本文中,我介绍了Python中面向对象编程的基本概念。现在你们知道OOPs和基本概念了。

原文链接:www.analyticsvidhya.com/blog/2020/0…

欢迎关注磐创AI博客站: panchuang.net/

sklearn机器学习中文官方文档: sklearn123.com/

欢迎关注磐创博客资源汇总站: docs.panchuang.net/

免责声明:文章版权归原作者所有,其内容与观点不代表Unitimes立场,亦不构成任何投资意见或建议。

Python

490

相关文章推荐

未登录头像

暂无评论