python中的OOP:实用指南
#初学者 #python #datascience #100daysofdatascience

100天的第3天数据科学训练营从NOOB到专家。

github链接:Complete-Data-Science-Bootcamp

主要帖子:Complete-Data-Science-Bootcamp

回顾第2天

昨天我们已经详细研究了有关python buit it数据结构的研究。

面向对象的编程(OOP)是基于“对象”概念的编程范式,该范例可以包含操纵数据的数据和代码。

在OOP中,“类”是用于创建对象的模板。它定义对象可以拥有的属性(数据)和方法(函数)。对象是从类模板创建的类的实例。

这是Python中简单类的示例:

主要的python oops概念 -

在本节中,我们将深入研究OOP的基本概念。我们将介绍以下主题 -

  1. class

  2. 对象

  3. 方法

  4. 继承

  5. 封装

  6. 多态性

  7. 数据抽象

班级

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

class Car:
    # class body
    pass

目的

当我们仅定义一个类别时,创建对象的描述或蓝图。在我们创建其对象之前,没有内存分配。反对者实例包含真实的数据或信息。

实例化无非是创建类的新对象/实例。让我们创建我们定义的上述类的对象 -

obj1 = Car()
print(obj1)

<main.Car对象在0x7f50d9fc6280>

由于我们的班级为空,因此返回对象存储的地址,即0x7fc5e6777b6d8

您还需要在前进之前就了解类构造函数。

类构造函数

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

汽车的名称,颜色,型号,品牌,发动机力量,重量,价格等都可以有各种特性。我们将仅选择少数用于理解目的。

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

因此,汽车或任何其他对象的属性必须在我们称为 init ()的方法内。此 init ()方法也称为构造方法。每当构建类的对象时,我们都会调用构造方法。

现在让我们谈论 init ()方法的参数。因此,该方法的第一个参数必须是自我。然后,其余参数才会出现。

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

  1. self.name = name

  2. self.color =颜色:

这将创建新属性,即名称和颜色,然后将相应参数的值分配给它们。自我关键字代表类的实例。通过使用自我关键字,我们可以访问类的属性和方法。它在方法定义和可变初始化中很有用。每次定义方法时,都会明确使用自我。

注意:您还可以在此 init ()方法之外创建属性。但是这些属性将与整个类都是通用的,您必须为其分配值。

假设您的陈列室中的所有汽车都是轿车,而不是一次又一次地指定它,而是可以通过在 intim ()之外创建属性来确定CAR_TYPE作为轿车的价值。

class Car:
    car_type = "Sedan"                 #class attribute
    def __init__(self, name, color):
        self.name = name               #instance attribute   
        self.color = color             #instance attribute

在这里,实例属性是指构造方法中的属性,即self.name和self.color。并且,类属性请参考构造函数方法之外的属性,即car_type。

方法

到目前为止,我们添加了汽车的性质。现在是时候添加一些行为了。方法是我们用来描述对象行为的功能。它们也在课堂内定义。查看以下代码 -

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"

obj2 = Car("Honda City",24.1)
print(obj2.description())
print(obj2.max_speed(150))

本田市汽车的里程为24.1km/l本田城的行驶速度为150公里/小时的最大速度

除构造方法方法以外的类中定义的方法称为实例方法。此外,我们在此处有两个实例方法 - description()和max_speed()。让我们单独谈论它们 -

  • description() - 此方法正在返回带有汽车描述的字符串,例如名称及其里程。该方法没有其他参数。此方法使用实例属性。

  • max_speed() - 此方法具有一个附加参数,并返回一个显示汽车名称及其速度的字符串。

请注意,附加的参数速度没有使用自我关键字。由于速度不是实例变量,因此我们不使用自关键字作为其前缀。让我们为上述类创建一个对象。

obj2 = Car("Honda City",24.1)
print(obj2.description())
print(obj2.max_speed(150))

本田市汽车的里程为24.1km/l本田城的行驶速度为150公里/小时的最大速度

我们所做的是创建了类汽车的对象,并通过了所需的参数。为了访问实例方法,我们使用object_name.method_name()。

方法描述()没有任何其他参数,因此我们在调用它时没有通过任何参数。

方法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))

本田城以最大速度为150 km/hr的速度,斯柯达明保持速度以210 km/hr

的最大速度运行

2.传递错误的参数。

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

Honda = Car("Honda City")
print(Honda)

----------------------------------------------------------------------------- ------------------------------------

TypeError Trackback(最近的最新通话)

单元格在[22]中,第6行3 self.name =名称4 self.mileage =里程-----> 6本田= CAR(“本田市”)7 PRINT(HONDA)

typeError: init ()缺少1所需的位置参数:'里程'

由于我们没有提供第二个参数,因此我们得到了此错误。

3.论点的顺序

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())

24.1汽车提供了本田Citykm/l

的里程

面向对象的编程 - 参数顺序

搞砸了!注意我们更改了论点的顺序。现在,有四个基本概念,是面向对象的编程 - 继承,封装,多态性和数据抽象。了解所有这些以了解所有这些非常重要。到目前为止,我们涵盖了OOP的基础知识,让我们进一步潜水。

Python班级的继承

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

有趣的是,与继承的属性和方法一起,子类可以具有自己的属性和方法。

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

class parent_class:
    # body of parent class
    pass

class child_class( parent_class):
    # body of child class
    pass

让我们看到实现 -

class Car:          #parent class

    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):     #child class
    pass

class Audi(Car):     #child class
    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())

宝马7系汽车的里程为39.53 km/l,奥迪A8 L车的里程为14公里/L,这是奥迪类的描述方法。

我们创建了两个子类,即BMW和奥迪,他们继承了父级的方法和属性。我们在BMW类中没有提供其他功能和方法。奥迪类中的另一种方法。

请注意,借助OBJ1.DESCRIPTION()和OBJ2.description(),子类的对象如何访问父类的实例方法描述()。也可以使用obj2.audi_desc()。

封装

正如我在文章的初始部分中提到的那样,

封装是确保安全性的一种方法。基本上,它隐藏了局外人访问的数据。例如,组织要保护对象/信息免受客户或任何未经授权的人的不需要访问权限,然后封装是确保此访问的方法。

您可以在其名称之前使用单个下划线( *)声明方法或属性。例如 - self。*名称或def _method();这两条行都表明属性和方法受到保护,不应在类和子类的访问之外使用,但可以通过类方法和对象访问。

尽管Python使用_'作为编码约定,但它告诉您应该在类范围内使用这些属性/方法。但是您仍然可以访问像往常一样被定义为保护的变量和方法。

现在,为了实际防止从类范围外的属性/方法访问,您可以使用私人成员。为了将属性/方法声明为私人成员,请在前缀中使用Double下划线()。例如自我。名称或def __method();这两种行都表明属性和方法是私有的,并且从类外部无法访问。

class car:

    def __init__(self, name, mileage):
        self._name = name                #protected variable
        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)

#accessing protected variable via class method 
print(obj.description())

#accessing protected variable directly from outside
print(obj._name)
print(obj.mileage)

宝马7系汽车的里程为39.53 km/L BMW 7系39.53

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

class Car:
    def __init__(self, name, mileage):
        self.__name = name              #private variable        
        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)

#accessing private variable via class method 
print(obj.description())

#accessing private variable directly from outside
print(obj.mileage)
print(obj.__name)

封装

当我们尝试使用Description()方法访问私有变量时,我们没有遇到任何错误。但是,当我们尝试直接在班级外访问私有变量时,python给了我们一个错误,说明:汽车对象没有属性。

您仍然可以使用其操纵名称直接访问此属性。名称Mangling是我们用于从外部访问类成员的机制。 Python解释器将任何标识符重写为__varâ_ _classname__varâ。并使用此功能也可以从外部访问类成员。

class Car:

    def __init__(self, name, mileage):
        self.__name = name              #private variable        
        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)

#accessing private variable via class method 
print(obj.description())

#accessing private variable directly from outside
print(obj.mileage)
print(obj._Car__name)      #mangled name

宝马7系汽车的里程为39.53 km/l 39.53 BMW 7系列

请注意,漫画规则的设计主要避免发生事故。但是仍然可以访问或修改被视为私有的变量。这甚至在特殊情况下可能很有用,例如在调试器中。

多态性

这是一个希腊语。如果我们打破多态性一词,我们将获得poly的和变形。因此,多态性意味着有多种形式。在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()

这是奥迪类的描述功能。这是BMW类的描述功能。

使用对象Audi调用该函数,然后调用类Audi的函数,当使用对象BMW调用该函数时,则调用BMW类的函数。

数据抽象

我们使用抽象来隐藏函数的内部详细信息或实现,并仅显示其功能。这类似于您知道如何在不知道背景机制的情况下驾驶汽车的方式。或者您知道如何使用开关打开或关闭灯,但您不知道插座后面发生了什么。

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

from abc import ABC

class abs_class(ABC):
    # Body of the class
    pass

重要的是,您无法使用抽象方法为抽象类创建对象。例如 -

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)

这是类汽车的描述功能。本田城的价格为250万。

CAR是从ABC模块继承的ABC类的抽象类。请注意,我如何在抽象类中具有抽象方法(Price(Price())和一个具体方法(Description(Description(Description(Description(Description(Description(Description),这是因为抽象类可以包括这两种功能,但是正常类不能。从该抽象类继承的另一个类是新()。此方法为抽象方法(价格())定义,这是我们使用抽象函数的方式。

用户从new()类创建对象并调用Price()方法后,新()类中的价格方法的定义开始起作用。这些定义对用户隐藏。抽象方法只是提供声明。儿童课需要提供定义。

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

从: https://www.analyticsvidhya.com

中获取了大部分内容

您将在Github的第2天的练习笔记本中找到练习问题。

如果您喜欢它,然后...

Buy Me A Coffee