New方法、单例模式、装饰器
类中的_ _new_ _(魔术方法/构造器)
在Python中,__new__
方法确实是一个特别的方法,但它和__init__
方法有着明显的区别。__new__
是一个静态方法(虽然通常不明确地声明为静态方法),而__init__
是一个实例方法。
_ _new_ _方法的作用
__new__
方法主要用于创建一个新的实例对象。它是类的一个静态方法,即便不明确声明也是如此。__new__
在__init__
方法之前被调用,用于生成实例对象。通常情况下,我们不需要自己编写__new__
方法,但在某些特殊情况下,修改__new__
方法能够提供额外的灵活性。
_ _new_ _ 方法的基本结构
1 | class MyClass(object): |
类定义
1 | class MyClass(object): |
这行代码定义了一个名为MyClass
的新类,它继承自Python内置的object
类。在Python 3中,所有的类默认继承自object
,所以即使不显式地继承,它仍然会继承自object
。
_ _new_ _ 方法
1 | def __new__(cls, *args, **kwargs): |
这是__new__
方法的定义。__new__
是一个特殊方法,用于在一个对象实例化时创建并返回这个对象。
cls
:这个参数是对当前类MyClass
的引用,这与实例方法中的self
参数类似,但cls
是在对象创建之前使用的。*args
和**kwargs
:这两个参数允许传递任意数量的位置参数和关键字参数。这些参数将会被传递给__init__
方法。
创建实例的逻辑
1 | instance = super(MyClass, cls).__new__(cls, *args, **kwargs) |
这行代码是创建类实例的核心。
super(MyClass, cls)
:这部分调用了MyClass
的父类的方法。在这个例子中,父类是object
。super
函数是用来获取父类定义,以便调用其方法的一种方式。.__new__(cls, *args, **kwargs)
:这部分实际上调用了父类object
的__new__
方法,并传递了必要的参数。这个调用负责创建一个新的实例。instance
:__new__
方法返回的是一个实例对象,这里我们将其赋值给变量instance
。
返回实例
1 | return instance |
最后,__new__
方法返回了新创建的实例instance
。这个实例接下来将被用来调用__init__
方法,以便进行进一步的初始化。
总结
这个MyClass
类示例展示了如何在Python中自定义__new__
方法。通常,不需要重写__new__
,除非有改变实例创建方式的特殊需求,比如实现单例模式、返回一个不同的类的实例或者在创建实例之前做一些额外的操作。在大多数情况下,只需要关注__init__
方法来初始化实例。
使用场景
__new__
方法通常在下面的情况下使用:
- 单例模式:确保一个类只有一个实例。
- 不可变类型的子类:例如扩展某些内置不可变类型,如
tuple
或str
。 - 控制实例的创建:在某些复杂的情况下,可能需要在对象创建时进行额外的处理。
单例模式
单例模式是一种常见的软件设计模式,其核心思想是确保一个类在应用程序中只有一个实例,并提供一个全局访问点来获取这个实例。这种模式在需要控制资源的访问或管理共享资源时特别有用,如数据库连接或文件系统的操作。
单例模式的特点
- 唯一实例:单例类只允许创建一个实例。
- 全局访问点:单例类提供一个全局访问的方法,全局的代码都可以通过这个方法访问到这个唯一实例。
- 自我管理:单例类负责创建、初始化和管理自己的唯一实例。
Python中实现单例模式
在Python中,单例模式可以通过多种方法实现,如使用模块级别的变量、装饰器、元类或重写__new__
方法等。以下是通过重写__new__
方法实现单例模式的一个示例:
1 | class Singleton: |
- 类变量
_instance
用于存储类的唯一实例。 - 在
__new__
方法中,首先检查_instance
是否已经被创建。如果没有,则创建一个新实例并将其赋值给_instance
。 - 之后的所有实例化操作都将返回这个已创建的实例。
单例模式的使用场景
单例模式通常用于以下场景:
- 管理共享资源,如数据库连接、日志记录、配置信息等。
- 控制资源的访问,确保资源的一致性和状态的同步。
- 减少资源的重复创建和销毁,提高效率。
注意事项
- 单例模式在多线程环境下可能需要特别的处理来保证线程安全。
- 过度使用单例模式可能导致代码间的耦合度过高,应当谨慎使用。
- 在分布式系统中,单例模式的使用需要考虑到进程间的通信和资源共享的问题。
单例模式是一种简单但强大的设计模式,能够有效地管理共享资源和全局状态,但也需要注意其带来的限制和潜在问题。
私有属性
在Python中,私有属性(Private Attributes)是指仅能在其所属的类内部访问的属性,而无法从类外部直接访问。这是面向对象编程中封装的一个重要概念,用于隐藏类的内部实现细节,并保护类的状态免受外部干扰。
如何定义私有属性
在Python中,私有属性通常是通过在属性名前加上双下划线(__
)来定义的。
1 | class MyClass: |
在这个例子中,__private_attribute
就是一个私有属性。由于它的名字以双下划线开头,它只能在MyClass
内部访问。
访问和修改私有属性
私有属性只能在定义它们的类的内部访问和修改。如果你试图从类外部访问或修改这些属性,将会导致AttributeError
。
1 | obj = MyClass() |
要在类外部访问或修改私有属性的值,你需要在类内部提供公共的方法(例如getter和setter方法)。
1 | class MyClass: |
名称改写(Name Mangling)
在Python中,私有属性的名称实际上会被改写,这个过程称为名称改写(Name Mangling)。Python解释器自动地把属性名__private_attribute
转换为_MyClass__private_attribute
。这意味着理论上你可以通过改写过的名称来访问私有属性,但这并不是一个好的做法,因为它违反了封装的原则。
1 | print(obj._MyClass__private_attribute) # 可行,但不推荐 |
为什么使用私有属性
使用私有属性的主要理由是封装和抽象。通过限制对类内部状态的直接访问,你可以防止外部代码无意中破坏类的内部状态,从而保持对象的完整性和一致性。
总结
私有属性是面向对象编程中的一个重要概念,它有助于实现封装和数据隐藏。在Python中,私有属性通过在属性名前加双下划线来定义,并且只能通过类内部定义的方法进行访问和修改。尽管技术上可以通过名称改写访问私有属性,但这并不符合封装的原则,应当避免这样做
装饰器
装饰器(Decorators)是Python中一个非常强大且有用的功能,它们允许程序员修改或增强函数和方法的行为,而不需要改变其本身的代码。装饰器在很多高级Python应用中都有广泛的使用,如Web框架、事件监听、日志处理等。
装饰器的基本原理
在Python中,装饰器本质上是一个Python函数,它可以接收一个函数作为参数并返回一个新的函数。使用装饰器可以在不修改原函数的情况下,增加额外的功能。
1 | def my_decorator(func): |
在上面的例子中,my_decorator
是一个装饰器,它在say_hello
函数前后添加了额外的打印操作。
使用@
语法糖
Python提供了一个简单的方式来应用装饰器,即使用@
符号,这也被称为语法糖。这让代码更加简洁易读。
1 |
|
使用@my_decorator
语法,上面的代码与之前例子中的功能完全相同。
带参数的装饰器
装饰器也可以带参数,这需要在其外层再加一层函数。这种装饰器也称为装饰器工厂。
1 | def repeat(number=3): |
在这个例子中,repeat
是一个带参数的装饰器,它接受一个参数number
,指定了函数执行的次数。
装饰器的用途
- 日志记录:添加日志功能,以跟踪函数的调用细节。
- 性能测试:检测函数执行时间,用于性能优化。
- 权限验证:检查用户是否有权执行某个操作。
- 缓存:缓存函数的返回结果,提高程序性能。
总结
装饰器是Python中非常有用的工具,可以在不修改原有函数代码的情况下,给函数增加新的功能。它通过语法简单但功能强大的方式,提高了代码的可读性和可维护性。在Python的日常使用中,熟练运用装饰器是一个非常有价值的技能。
信息
在Python中,装饰器的实现通常依赖于闭包的概念。
闭包(Closure)简介
闭包是一种在动态编程语言中常见的概念,它指的是一个函数记住了它的词法作用域,即使这个函数在自己的词法作用域之外执行。在Python中,闭包表现为一个内嵌函数记住了其外部函数的状态或环境。
装饰器中的闭包
在装饰器中使用闭包,是为了在装饰器函数内创建一个包装函数(wrapper),这个包装函数能够记住并访问其外部函数(即装饰器函数)的变量和参数。这使得装饰器能够在不修改被装饰函数的情况下增加额外的功能。
my_decorator
是一个装饰器函数。wrapper
是一个内嵌函数,它是闭包的体现。wrapper
能够记住并访问func
,即使在my_decorator
函数的执行已经完成之后。- 当我们使用
@my_decorator
装饰say_hello
函数时,实际上是将say_hello
作为参数传递给了my_decorator
,并将返回的wrapper
函数赋值给了say_hello
。
闭包的作用
闭包在装饰器中的主要作用是让我们能够延伸或修改函数的行为。闭包使得装饰器内部的包装函数能够访问到装饰器接收的原始函数,从而在不改变原始函数定义的前提下,对其进行包装,增加额外的操作和逻辑。
总结
简言之,装饰器中的闭包是Python中一种强大的函数式编程特性,它允许内嵌函数捕获并保持外部函数的状态,从而使得我们可以在不修改原函数的情况下,为其增加新的功能。这种特性在Python中广泛用于日志记录、性能测试、权限校验等场景。
详见函数篇 闭包
- 标题: New方法、单例模式、装饰器
- 作者: Yiuhang Chan
- 创建于 : 2018-09-15 17:24:27
- 更新于 : 2024-02-28 18:49:10
- 链接: https://www.yiuhangblog.com/2018/09/15/20180915New单例模式装饰器/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。