文章目录
- 参考
- 描述
- 面向对象编程
- 概念
- 类与实例
- 继承
- super() 与代理对象
- 方法的自动继承
- 属性的继承
- isinstance 与 type 内置函数
- isinstance()
- 可迭代对象仅能为元组
- 可能产生的 TypeError
- 嵌套的元组
- type
- isinstance() 与 type() 的区别
参考
| 项目 | 描述 |
|---|---|
| Python 官方文档 | https://docs.python.org/zh-cn/3/ |
| 搜索引擎 | Google 、Bing |
| 菜鸟教程 | Python isinstance() 函数 |
注:
本篇博客中的图片均来源于网络。
描述
| 项目 | 描述 |
|---|---|
| PyCharm | 2023.1 (Professional Edition) |
| Python | 3.10.6 |
面向对象编程
概念
面向对象编程的含义是?如果从 字面含义 对其进行理解,那么你可能会认为

实际上,面向对象编程(Object Oriented Programming,OOP)是一种 编程范式,面向对象编程以对象作为程序的基本单元,将 数据 和 操作 封装在对象中,并通过对象之间的交互来实现程序的功能。
下面是面向对象编程的几个 核心概念:
-
类(Class)
类是对象的蓝图或模板,定义了对象的结构和行为。类就像是一种物品或者一个类别。例如,我们可以将汽车定义为一个类,它们具有共同的属性(如颜色、品牌、型号)和方法(如启动、加速、刹车)。 -
对象(Object)
对象是类的实例,是类的具体实现,对象具有类定义的属性和方法,并可以进行操作和交互。举个例子,一辆特定的汽车(比如一辆红色的宝马X5)就是汽车类的一个对象,这个对象具有特定的属性值(如红色、宝马、X5)和可以执行的方法(如启动、加速、刹车)。

-
封装(Encapsulation)
封装是将数据和对数据的操作封装在类中,使其成为对象的内部细节,对外部隐藏。通过封装,对象的实现细节被保护起来,只提供公共的接口供其他对象使用。类似于一辆汽车,我们只需知道如何使用车辆的控制器(方法)来操作汽车,而不需要了解引擎、传动系统等内部细节。 -
继承(Inheritance)
继承是一种机制,允许创建一个新类(子类)从现有的类(父类)继承属性和方法,子类可以重用父类的代码,并可以扩展或修改父类的行为。例如,从汽车类派生出轿车类和卡车类,轿车和卡车将继承汽车类的通用属性和方法。

-
多态(Polymorphism)
多态是指对象可以根据上下文的不同表现出多种形态,多态允许使用统一的接口来处理不同类型的对象,提高了代码的灵活性和可重用性。以动物为例,不同种类的动物(如狗、猫、鸟)可以共享一个发出声音的方法,但每种动物的具体实现方式不同,产生了不同的声音。

- 抽象(Abstraction)
抽象是指从具体的事物中抽取出共同的特征和行为,形成类的抽象描述。抽象的目的是忽略不必要的细节,关注对象的关键属性和行为,以便于更好地理解和处理问题。抽象可以让我们将问题领域的复杂性抽象化为简单的模型,从而更好地组织和管理代码。
这些概念共同构成了面向对象编程的基础,使得程序设计更加 模块化、可维护 和 可扩展。面向对象编程提供了一种 思考 和 组织代码 的方法,使得代码更具 可读性 和 可理解性,并支持面向对象分析、设计和开发的整个软件开发生命周期。
类与实例
在 Python 中,我们可以使用 class 关键字来定义一个类,class 关键字后面紧跟类的名称和一个冒号。类的定义包含在一个代码块中,其中可以定义属性、方法和其他相关内容。
一旦我们定义了一个类,我们就可以通过 实例化操作 来创建该类的对象。在 Python 中,通过类名后面跟随括号的方式调用类的 构造函数,可以将一个类实例化为一个对象。
举个栗子
class MyClass:
# 定义 MyClass 类的构造函数,该函数
# 将在该类被实例化为对象时自动执行。
def __init__(self):
# 定义一个属性
self.name = 'RedHeart'
# 定义一个方法
def get_name(self):
return self.name
# 将 MyClass() 类实例化为一个对象
myClass = MyClass()
# 将 myClass 对象的字符串表示输出至控制台中
print(myClass)
# 将 myClass 对象的 name 属性的值输出至控制台中
print(myClass.name)
# 通过调用 myClass 对象的 get_name() 方法
# 获取该对象的 name 属性的值
print(myClass.get_name())
执行效果
<__main__.MyClass object at 0x000001D721E46D10>
RedHeart
RedHeart
继承
在 Python 中,我们可以通过 继承(Inheritance) 来创建一个类从另一个类派生的子类。子类继承了父类的属性和方法,并且可以添加自己特定的属性和方法。
类继承的基本语法是,在定义一个类时,在类名后面使用括号指定要继承的父类。
super() 与代理对象
在 Python 中 super() 是一个 内置的类对象,在类的内部实例化该类将得到一个特殊的 代理对象,该对象 绑定了父类的方法。super() 提供了一种方便的方式来 访问 父类的方法,允许你调用父类的方法,而不需要 显式地 引用父类的名称。对此,请参考如下示例:
class Parent:
def __init__(self):
self.name = 'Parent'
def get_self_name(self):
return self.name
class Children(Parent):
def get_parent_name(self):
# 通过调用 super() 返回的代理对象的
# get_self_name() 方法获取父类对象的 name 属性值
return super().get_self_name()
children = Children()
print(children.get_parent_name())
执行效果
Parent
方法的自动继承
一旦类与类之间确立了 继承关系,子类将 自动继承 父类中的 所有方法,包括实例方法、类方法和静态方法。这样,子类便可以 重用 父类的功能,并可以在子类中 添加新方法 来 扩展 子类的行为。
class Parent:
def __init__(self):
self.name = 'Parent'
def get_self_name(self):
return self.name
class Children(Parent):
def get_parent_name(self):
# 通过调用从父类继承得到的 get_self_name
# 方法获取父类的 name 属性值
return self.get_self_name()
children = Children()
print(children.get_parent_name())
执行效果
Parent
注:
子类可以通过 重写 父类的方法来 改变方法的行为。当子类定义了与父类 同名 的方法时,子类的方法会 覆盖 父类的方法。这样,子类可以根据自己的需求来重新定义方法的功能。对此,请参考如下示例:
class Parent:
def __init__(self):
self.name = 'Parent'
def get_self_name(self):
return self.name
class Children(Parent):
# 定义与父类同名的方法,子类的方法将覆盖父类的
# 同名方法。
def get_self_name(self):
return 'Hello World'
children = Children()
print(children.get_self_name())
执行效果
Hello World
属性的继承
即使确定了类与类之间的继承关系,子类也 不会自动继承 父类的属性(除 静态属性 外),并且使用 super() 返回的代理对象也仅能够访问父类中的 方法。那么,子类该如何继承父类中的属性呢?
可以通过调用含有 实例属性定义 的方法来继承父类中的属性。对此,请参考如下示例:
class Parent:
def set_parent_attrs(self):
# 在 Children 的父类中的 set_parent_attrs
# 函数中定义属性 name
self.name = 'Parent'
class Children(Parent):
pass
children = Children()
# 尝试访问定义于父类中的实例属性 name。
try:
print(children.name)
except AttributeError:
# 由于自 set_parent_attrs() 函数还未被调用
# name 实例属性还未被定义。
print("'Children' object has no attribute 'name'")
# 调用由父类中继承的 set_parent_attrs() 以
# 继承父类的属性 name。
children.set_parent_attrs()
print(children.name)
执行效果
'Children' object has no attribute 'name'
Parent
在 Python 中,常用于定义实例属性的方法为类对象的构造函数 __init__()。由于子类中也常需要使用到 __init__() 来定义该类的实例属性,而这将导致从父类继承的来的 __init__() 方法被覆盖。因此,常在子类的 __init__() 方法中通过 super() 返回的代理对象调用父类的 __init__() 方法来继承定义于父类 __init__() 方法中的实例属性。对此,请参考如下示例:
class Parent:
def __init__(self):
self.name = 'Parent'
class Children(Parent):
def __init__(self):
super().__init__()
self.local_name = 'Children'
children = Children()
print(children.name)
print(children.local_name)
执行效果
Parent
Children
注:
如果子类不需要 特别定制 或 扩展 父类的 初始化过程,可以不定义属于子类的 __init__() 构造函数,让子类自动继承父类的 __init__() 方法。对此,请参考如下示例:
class Parent:
def __init__(self):
self.name = 'Parent'
class Children(Parent):
pass
children = Children()
print(children.name)
执行效果
Parent
isinstance 与 type 内置函数
isinstance()
isinstance() 函数是 Python 中的 内置函数,该函数用于检查一个对象是否是 指定类 或 其子类 的 实例。如果对象是给定类型的实例,则返回 True;如果不是,则始终返回 False。
isinstance(object, classinfo)
其中:
-
object
需要进行类型检查的对象,isinstance()函数将判断object是否是指定类型或指定类型的子类的实例。 -
classinfo
classinfo的值允许为一个类型对象、多个类型对象组成的元组或Union类型。
# 判断数值 1 是否是 int 类型或该类型的子类类型的实例
result = isinstance(1, int)
print(result)
# 判断数值 1 是否是 str 类型或该类型的子类类型的实例
result = isinstance(1, str)
print(result)
# 判断数值 1 是否是 str 或 int 类型或其子类类型的实例
result = isinstance(1, (str, int))
print(result)
# 判断数值 1 是否是 str、int、bool 类型或其子类类型的实例
result = isinstance(1, str | int | bool)
print(result)
# 判断数值 1 是否是 str、int、bool、list、tuple
# 类型或其子类型的实例
result = isinstance(1, (str | int, bool | list, tuple | tuple, tuple))
print(result)
执行效果
True
False
True
True
True
可迭代对象仅能为元组
isinstance() 函数的参数 classinfo 的值可以为包含一个或多个类型对象的元组,但这不意味着可以使用与元组同为 可迭代对象 的 列表 等数据类型。否则,Python 将抛出 TypeError 异常错误。
result = isinstance(1, [int, str])
print(result)
可能产生的 TypeError
在 isinstance 函数的 classinfo 参数不符合预期时,isinstance() 函数将抛出 TypeError 异常,但也存在例外。对此,请参考如下示例:
result = isinstance(1, (int, 1))
print(result)
执行效果
True
倘若将 isinstance() 函数的第二个参数 (int, 1) 中的内容的顺序修改为 (1, int),则 Python 将为此抛出 TypeError 异常错误。
这是因为在通过 isinstance() 函数在进行类型检查时,isinstance() 函数会按照元组中的顺序逐个检查类型,一旦找到与 object 相匹配的类型对象,就返回 True。而如果在检查过程中遇到无效的类型,则将引发 TypeError 异常。
嵌套的元组
参数 classinfo 的值允许为多个类型对象组成的 元组,并且该元组中还能够嵌套元组。对此,请参考如下示例:
result = isinstance(1, (list, (str, (bool, (tuple | int)))))
print(result)
result = isinstance(1, (list, (str, (bool, (tuple | set)))))
print(result)
执行效果
True
False
type
在 Python 中,你可以向 type() 传入一个参数,该函数将返回该 参数所属的类对象。type() 函数可以帮助我们在 程序运行时确定对象的类型,从而采取相应的操作或逻辑。通过使用 type() 函数,我们可以 了解一个对象所属的具体类型,这对于调试、验证输入数据或处理不同类型的对象时非常有用。
type() 函数返回一个 类对象,表示对象所属的类或数据类型。类型信息,即类对象的字符串表示为 <class '类型'>,例如 <class 'int'> 表示整数类型。
举个栗子
# 自定义一个类,该类的名称为 MyClass
class MyClass:
pass
# 实例化 MyClass() 得到 myClass 对象
myClass = MyClass()
# 将 MyClas 类对象的字符串形式输出至控制台中
print(myClass)
# 将 myClass 所属的类对象的字符串形式输出至控制台中
print(type(myClass))
# 将数值 1 所属的类对象的字符串形式输出至控制台中
print(type(1))
# type() 函数返回的值为一个类对象而非字符串
print(type(1) == "<class 'int'>")
执行效果
<__main__.MyClass object at 0x00000212CBAB5690>
<class '__main__.MyClass'>
<class 'int'>
False
isinstance() 与 type() 的区别
type() 与 isinstance() 函数一样,同样可以用于判断对象是否是由某一类对象实例化产生的。但也存在不同,type() 函数不考虑类的继承关系,而 isinstance() 函数会对此进行考虑。
class Grandpa:
pass
class Father(Grandpa):
pass
class Son(Father):
pass
grandpa = Grandpa()
father = Father()
son = Son()
print(isinstance(son, Grandpa))
print(type(son) == Grandpa)
print(isinstance(son, Father))
print(type(son) == Father)
print(isinstance(son, Son))
print(type(son) == Son)
执行效果
True
False
True
False
True
True
上述代码定义了三个类:Grandpa、Father 和 Son,并建立了继承关系,即 Son 是 Father 的子类,而 Father 是 Grandpa 的子类。
接下来,使用 isinstance() 和 type() 函数进行类型检查,输出了一系列结果。
让我们逐个分析输出的结果和其原因:
-
print(isinstance(son, Grandpa))输出True,这是因为Son是Grandpa的子类的实例。因此,son是Grandpa的实例。 -
print(type(son) == Grandpa)输出False,这是因为type(son)的结果是Son,而不是Grandpa。type()函数返回的是对象的实际类型,不会考虑继承关系。 -
print(isinstance(son, Father))输出True,这是因为Son是Father的子类的实例。因此,son是Father的实例。 -
print(type(son) == Father)输出False,这是因为type(son)的结果是Son,而不是Father。同样地,type()函数返回的是对象的实际类型,不会考虑继承关系。 -
print(isinstance(son, Son))输出True,这是因为son是Son的实例。 -
print(type(son) == Son)输出True,这是因为type(son)的结果是Son。
根据以上的示例和结果,可以总结出 isinstance() 和 type() 函数的应用场景:
-
isinstance()函数用于检查一个对象是否是指定类或其子类的实例。它会考虑继承关系,如果对象是指定类或其子类的实例,返回True,否则返回False。 -
type()函数用于获取对象的实际类型,不考虑继承关系。它返回的是对象的实际类型,而不是对象所属的类或其父类。
在实际应用中,根据需求来选择使用 isinstance() 还是 type()。如果需要考虑继承关系,判断一个对象是否是指定类或其子类的实例,可以使用 isinstance()。如果只关心对象的实际类型,不考虑继承关系,可以使用 type()。



















