zoukankan      html  css  js  c++  java
  • python面向对象编程的基本概念

    作者|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和基本概念了。

    原文链接:https://www.analyticsvidhya.com/blog/2020/09/object-oriented-programming/

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

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

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

  • 相关阅读:
    Android录制音频的三种方式
    LeetCode Maximum Gap
    Android中BroadcastReceiver组件具体解释
    shell命令技巧——文本去重并保持原有顺序
    HDU 1284 钱币兑换问题(全然背包:入门题)
    【物联网云端对接-1】 通过HTTP协议与微软Azure IoT hub进行云端通信
    LoRa无线通信设计(一)原理
    leetCode 77.Combinations (组合)
    USACO4.2.1 网络流最大流算法
    [error:没有解析库]Couldn't find a tree builder with the features you requested: xml. Do you need to install a parser library?
  • 原文地址:https://www.cnblogs.com/panchuangai/p/13789576.html
Copyright © 2011-2022 走看看