Python原型模式介绍、使用;浅拷贝/深拷贝原理

一、Python原型模式(Prototype Pattern)简介

  1. 概念

原型模式是一种创建型设计模式,它通过复制(克隆)现有对象来创建新对象。这样可以避免使用复杂的构造函数来创建对象,提高程序的性能和可维护性。

  1. 功能

原型模式的功能是通过复制现有对象来创建新对象,从而提高程序的性能和可维护性。

  1. 优点
  • 可以避免重复创建相同的对象,提高性能;
  • 可以更加方便地创建复杂对象,减少代码的量;
  • 可以通过克隆来获取对象,避免了使用复杂的对象构造函数。
  1. 缺点
  • 实现对象克隆方法需要一定的技巧性,对开发者的要求较高;
  • 克隆方法可能需要比使用构造函数创建对象更加复杂。
  1. 应用场景
  • 在需要频繁创建相同对象的场景中,原型模式可以提高程序的性能;
  • 在需要创建复杂对象的场景中,原型模式能够简化对象创建的过程。
  1. 使用方式

在 Python 中,可以通过实现 __copy__()__deepcopy__() 方法来实现原型模式。其中,__copy__() 方法用于浅拷贝,__deepcopy__() 方法用于深拷贝。

在 Python 中,许多内置的数据类型和标准库中的对象都实现了原型模式,如:字典、列表、集合、datetime 对象等。在自己的代码中,我们也可以使用原型模式来减少代码的量,提高程序的性能。特别是在需要创建大量相似对象的场景中,使用原型模式可以帮助我们大大提高效率。

二、原型模式使用:

原型模式是一种设计模式,它允许我们通过复制现有的对象来创建新的实例。在 Python 中,原型模式可以通过 copy 模块中的 copy()deepcopy() 函数来实现。

下面是一个简单的例子,说明如何使用原型模式创建新的对象:

我们定义了一个 Person 类,该类有一个 clone() 方法,该方法使用 deepcopy() 函数来复制 Person 对象并返回一个新的实例。此外,该方法还接受一个可选的 kwargs 参数,该参数是一个字典,可以用来更新新的对象的属性。

现在,我们可以创建 Person 对象,并使用 clone() 方法创建一个新的实例。例如:

python 复制代码
import copy
class Person():
    def __init__(self, name, age):
        self.name = name
        self.age = age

    # 使用 print() 函数或字符串格式化操作符 % 将对象打印为字符串时,实际上是调用了该对象的 __str__() 方法
    def __str__(self): # __str__() 用于返回类的字符串表示形式
        return 'Person(name={}, age={})'.format(self.name, self.age)

    def clone(self, **kwargs):
        print("*********开始克隆")
        clone_obj = copy.deepcopy(self)
        clone_obj.__dict__.update(kwargs)
        return clone_obj

p1 = Person("Alice", 28)
p2 = p1.clone(name="Bob")
p3 = p1.clone(name="Charlie", age=30)
print(p1, p1.name, p1.age)
print(p2, p2.name, p2.age)
print(p3, p3.name, p3.age)

运行上述代码,输出结果为:

*********开始克隆

*********开始克隆

Person(name=Alice, age=28) Alice 28

Person(name=Bob, age=28) Bob 28

Person(name=Charlie, age=30) Charlie 30

从上面的输出结果可以看出,我们可以通过原型模式创建新的对象,并使用可选的参数来修改属性。这种模式非常适用于那些需要创建大量相似对象的场景,例如许多游戏中的敌人或NPC对象。

三、浅拷贝/深拷贝

浅拷贝和深拷贝都是 Python 中用来复制对象的方式。

  1. 概念:

    1. 浅拷贝(Shallow Copy):复制对象时,创建一个新对象,但该对象的某些属性仍然引用原始对象中的属性对象。
    2. 深拷贝(Deep Copy):复制对象时,创建一个新对象,并对原始对象中的所有属性进行递归复制。
  2. 工作原理:

    1. 浅拷贝:浅拷贝创建的新对象,其属性对象还是和原始对象中的属性对象相同。这意味着,如果修改新对象的属性对象,则原始对象和其他浅拷贝对象中的相同属性对象也会发生变化。
    2. 深拷贝:深拷贝创建的新对象和原始对象完全独立。这意味着,如果修改新对象的属性对象,则原始对象和其他深拷贝对象中的相同属性对象不会受到影响。
  3. 优点:

    1. 浅拷贝:比起深拷贝,浅拷贝更加高效,因为它不需要递归复制所有属性。同时,浅拷贝可以避免不必要的内存占用。
    2. 深拷贝:深拷贝可以保证复制后的对象和原始对象完全独立,不会出现因为共享引用导致的修改冲突问题。
  4. 缺点:

    1. 浅拷贝:由于浅拷贝只是复制了对象的引用,所以在修改属性对象时,会影响到原始对象和其他浅拷贝对象中的相同属性对象。
    2. 深拷贝:由于递归复制对象属性,所以深拷贝可能会消耗大量的内存和时间。
  5. 使用场景:

    1. 浅拷贝:当需要复制对象,但不需要深入复制对象属性时使用。比如,复制一个列表,但不需要复制列表中的元素。
    2. 深拷贝:当需要完全独立的副本时使用。比如,复制一个对象,但需要修改复制后的对象而不会影响原始对象。

Python 中实现浅拷贝和深拷贝的方式分别是 copydeepcopy 方法。例如:

python 复制代码
import copy

# a = [1,2]
a = [[1,2], [3,4]]
b = copy.copy(a)
print(a,b)
# b[1] = 3
b[1][1] = 5
print(a,b)

a = [[1,2], [3,4]]
b = copy.deepcopy(a)
print(a,b)
b[1][1] = 5
print(a,b)

运行结果:

\[1, 2\], \[3, 4\]\] \[\[1, 2\], \[3, 4\]

\[1, 2\], \[3, 5\]\] \[\[1, 2\], \[3, 5\]

\[1, 2\], \[3, 4\]\] \[\[1, 2\], \[3, 4\]

\[1, 2\], \[3, 4\]\] \[\[1, 2\], \[3, 5\]

四、Python相关方法介绍

1. __str__() 方法介绍

在 Python 中,__str__() 方法是一种特殊的方法,用于返回类的字符串表示形式。当我们使用 print() 函数或字符串格式化操作符 % 将对象打印为字符串时,实际上是调用了该对象的 __str__() 方法。

通常情况下,__str__() 方法返回的字符串应该是可读性较好的字符串,方便人类阅读。比如,如果一个类 Person 表示一个人的信息,我们可以在该类中定义如下的 __str__() 方法:

python 复制代码
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        return 'Person(name={}, age={})'.format(self.name, self.age)

在上面的例子中,__str__() 方法返回了一个类似于 Person(name=Alice, age=28) 的字符串表示形式,表示该对象的名字和年龄信息。通过这种方式,我们可以方便地打印或记录对象的信息,便于开发和调试。

需要注意的是,__str__() 方法应该返回一个字符串类型的值,否则会抛出 TypeError 异常。

2.__init__(self) 方法介绍

在 Python 中,__init__(self) 是一种特殊的方法,用于在创建一个新的对象时初始化该对象的属性。该方法在类中只能被定义一次,通常用于定义类的属性及其初始值。

在 Python 中,每次创建一个新的对象时,都会自动调用该对象所属类的 __init__(self) 方法进行初始化。在 __init__(self) 方法中,可以通过 self 参数来访问该对象的属性,从而给属性设置初始值。

例如,假设我们有一个类 Person 表示一个人的信息,可以在该类中定义如下的 __init__(self) 方法:

python 复制代码
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

在上面的例子中,__init__(self) 方法定义了两个参数 nameage,并将它们分别赋值给了对象的 nameage 属性。在创建一个新的 Person 对象时,可以通过传递相应的参数来初始化该对象的属性,例如:

python 复制代码
p1 = Person('Alice', 28)
p2 = Person('Bob', 30)

在上面的例子中,我们分别创建了两个 Person 对象,并传递了不同的参数,从而初始化了这两个对象的属性。

3.del关键字介绍

在 Python 中,del 是一种关键字,用于删除对象或对象属性。当使用 del 关键字时,它会执行对应对象的 __del__() 方法,方法内可以进行一些清理操作,通常在不再需要对象时使用。

使用 del 关键字可以删除一个对象,例如:

python 复制代码
x = 10     # 创建一个整数对象
del x     # 删除该对象

使用 del 关键字也可以删除一个对象的属性,例如:

python 复制代码
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

p = Person('Alice', 28)
del p.age       # 删除 p 对象的 age 属性

在上面的例子中,我们先创建了一个 Person 对象 p,然后使用 del 关键字删除了它的 age 属性。删除属性时不会影响对象本身的存在,只是将属性删除。

需要注意的是,在类中定义了 __del__() 方法并不能确保它会被立即执行。对于垃圾回收机制,Python 中的实现是引用计数机制,当一个对象的引用计数为 0 时,Python 会自动调用它的 __del__() 方法。但是,由于引用计数并不是完全准确的,因此 __del__() 方法可能会有延迟执行的情况,不能依赖它进行一些重要的操作。

4.obj.dic.update(kwargs)介绍

在 Python 中,obj.__dict__ 是一个字典,用于存储对象的属性和值。而 kwargs 则是一个字典,包含键值对,表示要更新的属性和值。

obj.__dict__.update(kwargs) 表示将 kwargs 字典中的键值对更新到 obj 对象的 __dict__ 中。也就是说,使用 update() 方法可以动态地修改对象的属性值,这在某些情况下是非常有用的。

例如,在实例化对象的时候,如果需要动态地为对象设置属性,可以使用 __dict__update() 方法,如下所示:

python 复制代码
class Person:
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)

p = Person(name='Alice', age=28)
print(p.name)   # 输出:Alice
print(p.age)    # 输出:28

在上面的例子中,我们定义了一个 Person 类,可以接收任意数量的关键字参数。在实例化对象时,我们使用 __dict__update() 方法将关键字参数更新到对象的 __dict__ 中,从而动态地为对象设置属性。

相关推荐
Stara051138 分钟前
基于多头自注意力机制(MHSA)增强的YOLOv11主干网络—面向高精度目标检测的结构创新与性能优化
人工智能·python·深度学习·神经网络·目标检测·计算机视觉·yolov11
那雨倾城2 小时前
使用 OpenCV 将图像中标记特定颜色区域
人工智能·python·opencv·计算机视觉·视觉检测
LuckyTHP4 小时前
java 使用zxing生成条形码(可自定义文字位置、边框样式)
java·开发语言·python
mahuifa6 小时前
(7)python开发经验
python·qt·pyside6·开发经验
学地理的小胖砸7 小时前
【Python 操作 MySQL 数据库】
数据库·python·mysql
安迪小宝7 小时前
6 任务路由与负载均衡
运维·python·celery
Blossom.1187 小时前
使用Python实现简单的人工智能聊天机器人
开发语言·人工智能·python·低代码·数据挖掘·机器人·云计算
lisw057 小时前
Python高级进阶:Vim与Vi使用指南
python·vim·excel
ayiya_Oese7 小时前
[模型部署] 3. 性能优化
人工智能·python·深度学习·神经网络·机器学习·性能优化
SoraLuna7 小时前
「Mac畅玩AIGC与多模态40」开发篇35 - 用 Python 开发服务对接 SearxNG 与本地知识库
python·macos·aigc