前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Python 入门第十五讲】OOP(面向对象)思想

【Python 入门第十五讲】OOP(面向对象)思想

原创
作者头像
GoBoy
修改2024-02-20 17:31:37
16200
代码可运行
修改2024-02-20 17:31:37
举报
运行总次数:0
代码可运行

在 Python 中,面向对象编程 (OOP) 是一种在编程中使用对象和类的编程范式。它旨在在编程中实现现实世界的实体,如继承、多态性、封装等。OOP 的主要概念是将数据和处理该数据的函数绑定在一起,作为一个单元,以便代码的其他部分无法访问此数据。

Python 中的 OOP 思想

  • Class 类
  • Objects 对象
  • Polymorphism 多态性
  • Encapsulation 封装
  • Inheritance 继承
  • Data Abstraction 数据抽象

Python Class(类)

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

为了理解创建类的必要性,我们考虑一个示例,假设你想跟踪可能具有不同属性(如品种和年龄)的狗的数量。如果使用列表,第一个元素可能是狗的品种,而第二个元素可以表示它的年龄。假设有 100 只不同的狗,那么你怎么知道哪个元素应该是哪个?如果想为这些狗添加其他属性怎么办?这种缺乏组织性,正是对类的需求。

Python 关于类的几点:

  • 类由关键字 class 创建。
  • 属性是属于类的变量。
  • 属性始终是公共的,可以使用点 (.) 运算符进行访问。例如:Myclass.Myattribute

Python 类定义语法:

代码语言:python
代码运行次数:0
复制
class ClassName:
   # Statement-1
   .
   .
   .
   # Statement-N

Python 中创建空类:

我们使用 class 关键字创建了一个名为 Dog 的类。

代码语言:python
代码运行次数:0
复制
# a class
class Dog:
	pass

Python Objects(对象)

对象是具有与其关联的状态和行为的实体。它可以是任何现实世界的物体,如鼠标、键盘、椅子、桌子、笔等。整数、字符串、浮点数、甚至数组和字典都是对象。更具体地说,任何单个整数或任何单个字符串都是一个对象。数字 12 是一个对象,字符串“Hello, world”是一个对象,列表是一个可以容纳其他对象的对象,依此类推。我们一直在使用对象,甚至可能没有意识到这一点。

对象由以下部分组成:

  • 状态:它由对象的属性表示。它还反映了对象的属性。
  • 行为:它由对象的方法表示。它还反映了一个对象对其他对象的响应。
  • 标识:它为对象提供唯一名称,并使一个对象能够与其他对象进行交互。

为了理解状态、行为和身份,让我们以类狗为例(如上所述)。

  • 身份可以看作是狗的名字。
  • 状态或属性可以被视为狗的品种、年龄或颜色。
  • 可以考虑该行为是狗在吃东西还是在睡觉。

创建对象

创建一个名为 obj 的对象,该对象属于上面定义的 Dog 类。在深入研究对象和类之前,让我们了解一些在处理对象和类时将使用的基本关键字。

代码语言:python
代码运行次数:0
复制
obj = Dog()

Python self

Self 表示类的实例。通过使用“self”,我们可以在 Python 中访问类的属性和方法。它将属性与给定的参数绑定。你需要使用self的原因。是因为 Python 不使用 @ 语法来引用实例属性。Python 决定以一种使方法所属的实例自动传递而不是自动接收的方式执行方法:methods 的第一个参数是调用该方法的实例。

self 作用

在 Python 中使用类时,术语“self”是指当前正在使用的类的实例。习惯上使用“self”作为类的实例方法中的第一个参数。每当调用从类创建的对象的方法时,该对象都会使用“self”参数自动作为第一个参数传递。这使您能够修改对象的属性并执行该特定实例特有的任务。

代码语言:python
代码运行次数:0
复制
class mynumber:
	def __init__(self, value):
		self.value = value
	
	def print_value(self):
		print(self.value)

obj1 = mynumber(17)
obj1.print_value()
  1. 类方法在方法定义中必须有一个额外的第一个参数。当我们调用该方法时,我们不会为此参数提供值,Python 提供了它
  2. 如果我们有一个不带参数的方法,那么我们仍然必须有一个参数。
  3. 这类似于 C++ 中的此指针和 Java 中的此引用。

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

Python __init__方法

__init__ 方法类似于 C++ 和 Java 中的构造函数。一旦实例化了类的对象,它就会运行。该方法可用于对对象执行任何初始化操作。我们定义一个类并使用 self 和 __init__ 方法创建一些对象。

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

代码语言:python
代码运行次数:0
复制
class Dog:

	# 类属性
	attr1 = "哺乳动物"

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

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

# 访问类属性
print("Rodger 是 {}".format(Rodger.__class__.attr1))
print("Tommy 也是 {}".format(Tommy.__class__.attr1))

# 访问实例属性
print("我的名字是 {}".format(Rodger.name))
print("我的名字是 {}".format(Tommy.name))

输出

代码语言:python
代码运行次数:0
复制
Rodger 是 哺乳动物
Tommy 也是 哺乳动物
我的名字是 Rodger
我的名字是 Tommy

使用方法创建类和对象

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

  • attr1 是设置为值“哺乳动物”的类属性。类属性由类的所有实例共享。
  • __init__ 是一个特殊方法(构造函数),用于初始化 Dog 类的实例。它有两个参数:self(指正在创建的实例)和 name(表示狗的名字)。name 参数用于为每个 Dog 实例分配一个 name 属性。speak 方法在 Dog 类中定义。此方法打印一个字符串,其中包含 dog 实例的名称。

首先创建 Dog 类的两个实例:Rodger 和 Tommy。为每个实例调用 __init__ 方法,以使用提供的名称初始化其名称属性。speak 方法在两个实例(Rodger.speak() 和 Tommy.speak()))中被调用,导致每只狗打印带有其名称的语句。

代码语言:python
代码运行次数:0
复制
class Dog:

	# 类属性
	attr1 = "哺乳动物"

	# 实例属性
	def __init__(self, name):
		self.name = name
		
	def speak(self):
		print("我的名字是 {}".format(self.name))

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

# 访问类方法
Rodger.speak()
Tommy.speak()

输出:

代码语言:python
代码运行次数:0
复制
我的名字是 Rodger
我的名字是 Tommy

Python Inheritance(继承)

继承是一个类从另一个类派生或继承属性的能力。派生属性的类称为派生类或子类,派生属性的类称为基类或父类。继承的好处是:

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

继承类型

  • Single Inheritance:单级继承使派生类能够从单父类继承特征。
  • Multilevel Inheritance: 多级继承使派生类能够从直接父类继承属性,而父类又从其父类继承属性。
  • Hierarchical Inheritance: 分层级继承使多个派生类能够从父类继承属性。
  • Multiple Inheritance: 多级继承使一个派生类能够从多个基类继承属性。

Python 中的继承

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

代码语言:python
代码运行次数:0
复制
# 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("我的名字是 {}".format(self.name))
		print("Id号码: {}".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("我的名字是 {}".format(self.name))
		print("Id号码: {}".format(self.idnumber))
		print("职位: {}".format(self.post))


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

# 使用实例调用 Person 类的函数
a.display()
a.details()

Output

代码语言:python
代码运行次数:0
复制
Rahul
886012
我的名字是 Rahul
Id号码: 886012
职位: 实习生

Python Polymorphism(多态)

多态性只是意味着具有多种形式。例如,我们需要确定给定种类的鸟类是否飞行,使用多态性,我们可以使用单个函数来做到这一点。

Python 中的多态性

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

代码语言:python
代码运行次数:0
复制
class Bird:

	def intro(self):
		print("有许多种类的鸟类。")

	def flight(self):
		print("大多数鸟类可以飞行,但有些不能。")

class sparrow(Bird):

	def flight(self):
		print("麻雀可以飞行。")

class ostrich(Bird):

	def flight(self):
		print("鸵鸟不能飞行。")

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

Output输出

代码语言:python
代码运行次数:0
复制
有许多种类的鸟类。
大多数鸟类可以飞行,但有些不能。
有许多种类的鸟类。
麻雀可以飞行。
有许多种类的鸟类。
鸵鸟不能飞行。

Python Encapsulation (封装)

封装是面向对象编程 (OOP) 的基本概念之一。它描述了将数据包装的想法以及在一个单元中处理数据的方法。这限制了直接访问变量和方法,并可以防止意外修改数据。为了防止意外更改,对象的变量只能通过对象的方法更改。这些类型的变量称为私有变量。

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

Python 中的封装

在下面的示例中,我们创建了 c 变量作为私有属性。我们甚至无法直接访问此属性,甚至无法更改其值。

代码语言:python
代码运行次数:0
复制
# Python 程序演示了私有成员
# "__" 双下划线表示私有属性。 
# 私有属性以 "__" 开头。

# 创建一个基类
class Base:
	def __init__(self):
		self.a = "Go"
		self.__c = "Go"

# 创建一个派生类
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 因为
# 在派生类中调用了基类的私有成员

Output输出

代码语言:python
代码运行次数:0
复制
Go

抽象(Abstraction数据

它向用户隐藏了不必要的代码详细信息。此外,当我们不想给出代码实现的敏感部分时,这就是数据抽象的来源。

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

在 Python 中,我们在属性名称之前使用双下划线(或 __),这些属性不会在外面直接可见。

代码语言:python
代码运行次数:0
复制
class MyClass: 

	# MyClass 的隐藏成员 
	__hiddenVariable = 0
	
	# 修改 __hiddenVariable 的成员方法 
	def add(self, increment): 
		self.__hiddenVariable += increment 
		print (self.__hiddenVariable) 

# 驱动代码 
myObject = MyClass()	 
myObject.add(2) 
myObject.add(5) 

# 此行导致错误 
print (myObject.__hiddenVariable) 

输出:

代码语言:python
代码运行次数:0
复制
2
7
Traceback (most recent call last):
  File "E:\StudyPython\demoPillow.py", line 18, in <module>
    print(myObject.__hiddenVariable)
AttributeError: 'MyClass' object has no attribute '__hiddenVariable'

在上面的程序中,我们使用一个对象访问类外部的隐藏变量,但它抛出了一个异常。

我们可以通过的语法来访问隐藏属性的值:

代码语言:python
代码运行次数:0
复制
# 一个 Python 程序,演示了隐藏成员可以在类外部被访问

class MyClass: 

	# MyClass 的隐藏成员 
	__hiddenVariable = 10

# 驱动代码 
myObject = MyClass()	 
print(myObject._MyClass__hiddenVariable) 

输出为:

代码语言:javascript
复制
10

私有方法可以在他们的类之外访问,只是不容易访问。Python 中没有任何东西是真正私有的;在内部,私有方法和属性的名称被动态地破坏和解开,使它们看起来无法通过它们的给定名称访问。

Printing Objects

打印对象为我们提供了有关我们正在处理的对象的信息。在C++中,我们可以通过为类添加一个朋友 ostream& 运算符 << (ostream&, const Foobar&) 方法来做到这一点。在 Java 中,我们使用 toString() 方法。

在 python 中,这可以通过使用 __repr__ 或 __str__ 方法来实现。

代码语言:python
代码运行次数:0
复制
class Test: 
	def __init__(self, a, b): 
		self.a = a 
		self.b = b 

	def __repr__(self): 
		return "Test a:%s b:%s" % (self.a, self.b) 

	def __str__(self): 
		return "From str method of Test: a is %s, b is %s" % (self.a, self.b)
	 
t = Test(1234, 5678) 
print(t) # This calls __str__() 
print([t]) # This calls __repr__() 

输出:

代码语言:python
代码运行次数:0
复制
From str method of Test: a is 1234, b is 5678
[Test a:1234 b:5678]

关于打印的要点:

  • 如果未定义__str__方法,则 print t(或 print str(t))使用 __repr__。
代码语言:python
代码运行次数:0
复制
class Test: 
	def __init__(self, a, b): 
		self.a = a 
		self.b = b 

	def __repr__(self): 
		return "Test a:%s b:%s" % (self.a, self.b) 
	 
t = Test(1234, 5678) 
print(t) 

输出:

代码语言:python
代码运行次数:0
复制
Test a:1234 b:5678

如果未定义__repr__方法,则使用默认值。

代码语言:python
代码运行次数:0
复制
class Test: 
	def __init__(self, a, b): 
		self.a = a 
		self.b = b 

# Driver Code		 
t = Test(1234, 5678) 
print(t) 

输出:

代码语言:python
代码运行次数:0
复制
<__main__.Test object at 0x7f54e4701390>

我正在参与2024腾讯技术创作特训营第五期有奖征文,快来和我瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Python 中的 OOP 思想
  • Python Class(类)
    • Python 关于类的几点:
      • Python 类定义语法:
        • Python 中创建空类:
        • Python Objects(对象)
          • 创建对象
          • Python self
            • self 作用
            • Python __init__方法
              • 创建具有类和实例属性的类和对象
                • 使用方法创建类和对象
                • Python Inheritance(继承)
                  • 继承类型
                    • Python 中的继承
                    • Python Polymorphism(多态)
                      • Python 中的多态性
                      • Python Encapsulation (封装)
                        • Python 中的封装
                        • 抽象(Abstraction)数据
                          • Printing Objects
                            • 关于打印的要点:
                            • 如果未定义__repr__方法,则使用默认值。
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档