Python 面向对象详解!

嗨,你好啊,我是猿java

作为一名 Java程序员,对面向对象编程肯定不陌生,那么,在 Python 语言中,面向对象是什么?它有什么作用?这篇文章我们就来讲一讲。

什么是 Python OOP?

在 Python中,面向对象编程(Object-Oriented Programming,简称OOP)是一种使用对象和类进行编程的编程范式。它旨在实现现实世界中的实体,如继承、多态、封装等。在编程中,面向对象编程的主要概念是将数据和与之相关的函数绑定为一个单元,以便代码的其他部分无法访问这些数据。

Python中的OOP包含以下概念:

  • Python类
  • Python对象
  • Python多态
  • Python封装
  • Python继承
  • Python数据抽象

接下来,我们对上面的概念一一讲解。

Python类

类是对象的集合。类包含创建对象的蓝图或原型。它是一个包含一些属性和方法的逻辑实体。

为了理解创建类的需求,让我们考虑一个例子,假设你想跟踪具有不同属性的狗,如品种和年龄。如果使用列表,第一个元素可能是狗的品种,而第二个元素可能代表其年龄。假设有 100只不同的狗,那么你怎么知道哪个元素代表哪个属性呢?如果你想为这些狗添加其他属性呢?这就缺乏组织性,这正是需要类的原因。

关于 Python类的一些要点:

  • 类是由关键字class创建的。
  • 属性是属于类的变量。
  • 属性总是公开的,可以使用点(.)操作符访问。例子:Myclass.Myattribute

类定义语法:

1
2
3
4
class ClassName:
# 语句-1

# 语句-N

创建一个空类

在下面的例子中,我们使用 class关键字创建了一个名为 Dog的空类。

1
2
class Dog:
pass

输出:无输出

Python对象

在面向对象编程中,对象是具有状态和行为的实体。它可以是任何现实世界的对象,如鼠标、键盘、椅子、桌子、笔等。整数、字符串、浮点数,甚至数组和字典,都是对象。更具体地说,任何单个整数或字符串都是对象。数字 12是一个对象,字符串“Hello, world”是一个对象,列表是一个可以包含其他对象的对象,等等。你一直在使用对象,可能甚至没有意识到。

一个对象包括:

  • 状态:由对象的属性表示。它也反映了对象的属性。
  • 行为:由对象的方法表示。它也反映了对象对其他对象的响应。
  • 身份:赋予对象一个唯一的名称,并使一个对象能够与其他对象交互。

为了理解状态、行为和身份,让我们以狗类为例(上面解释过)。

  • 身份可以被认为是狗的名字。
  • 状态或属性可以被认为是狗的品种、年龄或颜色。
  • 行为可以被认为是狗是否在吃东西或睡觉。

创建一个对象

下面的示例创建了一个名为 obj的 Dog类的对象。在深入研究对象和类之前,让我们了解一些在处理对象和类时会用到的基本关键字。

1
obj = Dog()

Python中的self

类方法在方法定义中必须有一个额外的第一个参数self。当我们调用方法时,不需要为这个参数提供值,Python会自动提供。

如果我们有一个不带参数的方法,那么我们仍然需要有一个参数。 这类似于 C++中的 this指针和 Java中的 this引用。

当我们调用一个对象的方法,如myobject.method(arg1, arg2)时,Python会自动将其转换为MyClass.method(myobject, arg1, arg2),这就是特殊的 self的作用。

Python中的__init__方法

__init__方法类似于 C++和 Java中的构造函数,它在类的对象实例化时自动运行。这个方法对于初始化对象非常有用。下面我们定义一个类,并使用 self 和 __init__方法创建一些对象。

创建带有类和实例属性的类和对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Dog:

# 类属性
attr1 = "mammal"

# 实例属性
def __init__(self, name):
self.name = name

# 主代码
# 对象实例化
Rodger = Dog("Rodger")
Tommy = Dog("Tommy")

# 访问类属性
print("Rodger is a {}".format(Rodger.__class__.attr1))
print("Tommy is also a {}".format(Tommy.__class__.attr1))

# 访问实例属性
print("My name is {}".format(Rodger.name))
print("My name is {}".format(Tommy.name))

输出:

1
2
3
4
Rodger is a mammal
Tommy is also a mammal
My name is Rodger
My name is Tommy

创建带有方法的类和对象:

这里,Dog类定义了两个属性:

  • attr1是一个类属性,值为“mammal”。类属性由类的所有实例共享。
  • __init__是一个特殊方法(构造函数),用于初始化Dog类的实例。它接收两个参数:self(指代被创建的实例)和name(代表狗的名字)。name参数用于为每个Dog实例分配一个name属性。
  • speak方法在Dog类中定义。该方法打印一个包含狗实例名字的字符串。
    主代码首先创建了两个Dog类的实例:Rodger和Tommy。__init__方法被调用以初始化它们的name属性。speak方法在两个实例中调用(Rodger.speak()和Tommy.speak()),使每只狗打印出带有其名字的声明。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    class Dog:

    # 类属性
    attr1 = "mammal"

    # 实例属性
    def __init__(self, name):
    self.name = name

    def speak(self):
    print("My name is {}".format(self.name))

    # 主代码
    # 对象实例化
    Rodger = Dog("Rodger")
    Tommy = Dog("Tommy")

    # 访问类方法
    Rodger.speak()
    Tommy.speak()
    输出:
    1
    2
    My name is Rodger
    My name is Tommy

Python继承

在Python面向对象编程中,继承是一个类从另一个类派生或继承属性的能力。派生属性的类称为派生类或子类,从中派生属性的类称为基类或父类。继承的好处包括:

  • 它很好地表示现实世界的关系。
  • 它提供代码的重用性。我们不必一遍又一遍地编写相同的代码。此外,它允许我们在不修改类的情况下为其添加更多功能。
  • 它具有传递性,这意味着如果类B继承自类A,那么类B的所有子类将自动继承自类A。

继承的类型

  • 单继承:单级继承使派生类能够从单个父类继承特性。
  • 多级继承:多级继承使派生类能够从直接父类继承属性,而父类又继承自其父类。
  • 层次继承:层次级继承使多个派生类能够从一个父类继承属性。
  • 多重继承:多重继承使一个派生类能够从多个基类继承属性。

在上面的文章中,我们创建了两个类:Person(父类)和Employee(子类)。Employee类继承自Person类。我们可以通过Employee类使用Person类的方法,如上面的display函数所示。子类还可以修改父类的行为,如details()方法所示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# Python代码演示如何调用父类构造函数。

# 父类
class Person(object):

# __init__被称为构造函数
def __init__(self, name, idnumber):
self.name = name
self.idnumber = idnumber

def display(self):
print(self.name)
print(self.idnumber)

def details(self):
print("My name is {}".format(self.name))
print("IdNumber: {}".format(self.idnumber))

# 子类
class Employee(Person):
def __init__(self, name, idnumber, salary, post):
self.salary = salary
self.post = post

# 调用父类的__init__方法
Person.__init__(self, name, idnumber)

def details(self):
print("My name is {}".format(self.name))
print("IdNumber: {}".format(self.idnumber))
print("Post: {}".format(self.post))

# 创建对象变量或实例
a = Employee('Rahul', 886012, 200000, "Intern")

# 使用实例调用Person类的方法
a.display()
a.details()

输出:

1
2
3
4
5
Rahul
886012
My name is Rahul
IdNumber: 886012
Post: Intern

Python多态

在Python面向对象编程中,多态简单来说就是具有多种形式。例如,我们需要确定给定的鸟类是否会飞,使用多态,我们可以用一个函数来完成这个任务。

此代码演示了Python类中的继承和方法重写概念。它展示了子类如何重写父类中定义的方法以提供特定行为,同时仍然继承父类的其他方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Bird:

def intro(self):
print("There are many types of birds.")

def flight(self):
print("Most of the birds can fly but some cannot.")

class Sparrow(Bird):

def flight(self):
print("Sparrows can fly.")

class Ostrich(Bird):

def flight(self):
print("Ostriches cannot fly.")

obj_bird = Bird()
obj_spr = Sparrow()
obj_ost = Ostrich()

obj_bird.intro()
obj_bird.flight()

obj_spr.intro()
obj_spr.flight()

obj_ost.intro()
obj_ost.flight()

输出:

1
2
3
4
5
6
There are many types of birds.
Most of the birds can fly but some cannot.
There are many types of birds.
Sparrows can fly.
There are many types of birds.
Ostriches cannot fly.

Python封装

在Python面向对象编程中,封装是OOP的基本概念之一。它描述了将数据和操作数据的方法封装在一个单元中的想法。这对直接访问变量和方法进行了限制,防止数据的意外修改。为了防止意外更改,对象的变量只能通过对象的方法更改。这类变量称为私有变量。

类是封装的一个例子,因为它封装了所有的数据,包括成员函数、变量等。

在上面的例子中,我们创建了 c变量作为私有属性,我们不能直接访问这个属性,也不能更改其值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# Python程序演示私有成员
# "__"双下划线表示私有属性。
# 私有属性以"__"开头。

# 创建基类
class Base:
def __init__(self):
self.a = "猿java"
self.__c = "猿java"

# 创建派生类
class Derived(Base):
def __init__(self):

# 调用基类的构造函数
Base.__init__(self)
print("调用基类的私有成员:")
print(self.__c)

# 主代码
obj1 = Base()
print(obj1.a)

# 取消注释print(obj1.c)会引发AttributeError

# 取消注释obj2 = Derived()也会引发AttributeError,因为
# 基类的私有成员在派生类中被调用

输出:

1
猿java

Python数据抽象

数据抽象隐藏了用户不需要的代码细节。同时,当我们不想暴露代码实现的敏感部分时,数据抽象就派上用场了。

在Python中,数据抽象可以通过创建抽象类来实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Rectangle:
def __init__(self, length, width):
self.__length = length # 私有属性
self.__width = width # 私有属性

def area(self):
return self.__length * self.__width

def perimeter(self):
return 2 * (self.__length + self.__width)

rect = Rectangle(5, 3)
print(f"Area: {rect.area()}") # 输出: Area: 15
print(f"Perimeter: {rect.perimeter()}") # 输出: Perimeter: 16

# print(rect.__length) # 这将引发AttributeError,因为length和width是私有属性

输出:

1
2
Area: 15
Perimeter: 16

常见问题

Python面向对象编程的四大支柱是什么?

面向对象编程(OOP)的四大支柱是:

  • 封装:将数据(属性)和操作数据的方法(函数)捆绑在一个单元(类)中。
  • 抽象:隐藏复杂的实现细节,并提供简化的接口。
  • 继承:允许一个类从另一个类继承属性和方法,促进代码重用。
  • 多态:使用单一接口表示不同的数据类型或对象。

Python使用OOP吗?

是的,Python完全支持面向对象编程(OOP)概念。类、对象、继承、封装和多态是 Python的基本特性。

Python是100%面向对象吗?

Python是一种多范式编程语言,这意味着它支持包括过程式、函数式和面向对象编程在内的多种编程范式。虽然 Python主要是面向对象的,但它也允许过程式和函数式编程风格。

Python的__init__是什么?

__init__是Python类中的一个特殊方法(构造函数)。当类的新实例(对象)被创建时,它会自动调用。它的主要目的是初始化对象的属性或执行对象所需的任何设置。

1
2
3
4
class MyClass:
def __init__(self, arg1, arg2):
self.arg1 = arg1
self.arg2 = arg2

Python中的super()是什么?

super()用于从子类(派生类)调用超类(父类)的方法。它返回一个代理对象,将方法调用委托给超类。这对于访问在子类中被重写的继承方法非常有用。

1
2
3
4
class ChildClass(ParentClass):
def __init__(self, arg1, arg2):
super().__init__(arg1) # 调用ParentClass的__init__()方法
self.arg2 = arg2

为什么 Python有self?

self是Python中的一种约定,用于引用类的实例(对象)本身。它是实例方法的第一个参数,指代调用方法的对象。它允许方法访问和操作属于实例的属性(变量)。

1
2
3
4
5
6
7
8
9
class MyClass:
def __init__(self, name):
self.name = name

def greet(self):
return f"Hello, {self.name}!"

obj = MyClass("Python")
print(obj.greet()) # 输出: Hello, Python!

总结

如果你是Java程序员,对面向对象编程肯定不陌生,面向对象编程也是 Python中的一种编程范式,通过使用类和对象来实现代码的模块化、可维护性和可扩展性。OOP的核心概念包括类、对象、继承、封装、多态和抽象。

  • 类是对象的蓝图,定义了对象的属性和方法;
  • 对象是类的实例,具有状态和行为。
  • 继承允许子类从父类继承属性和方法,促进代码重用;
  • 封装将数据和方法封装在一个单元中,限制直接访问;
  • 多态允许不同对象通过相同接口进行操作;
  • 抽象隐藏实现细节,提供简化接口。

学习交流

如果你觉得文章有帮助,请帮忙转发给更多的好友,或关注公众号:猿java,持续输出硬核文章。

drawing