Python实现常量
Python实现常量
一、 概述
很多高级编程语言都提供了定义常量的方法,一个常量一旦被定义,就无法再修改,这样做的意义在于防止其他人修改一些关键参数和配置。在C++,C#, php可以使用const关键字,java可以使用final,python没有提类似供定义常量的关键字,但我们可以通过一些技术手段实现类似的效果。
对于常量,有两个要求:
- 常量的命名必须都是大写字母,可以使用下划线连接单词
- 变量一旦赋值后,不可再修改
思路上,定义一个Const类,重写魔法方法__setattr__
, 这个方法可以对对象的属性赋值进行干预。创建一个Const类的对象,所有想要定义的常量都是这个对象的属性,这样一来,我们还要防止生成多个Const类的对象,因此,需要实现单例模式。
魔法方法:https://blog.csdn.net/qq_62789540/article/details/127416850
单例模式有三种实现方式,元类、装饰器、魔法方法,这里我们使用魔法方法来实现单例模式。
二、 实现
1、 单例模式
首先,我们来回顾一下单例模式的实现方法,三种方式都回顾一下:
1.1 元类
from typing import Any from threading import RLock single_lock = RLock() class Meta(type): def __init__(self, *args: Any, **kwargs: Any) -> Any: self.__instance = None super(Meta, self).__init__(*args, **kwargs) def __call__(self, *args: Any, **kwds: Any) -> Any: with single_lock: if self.__instance is None: self.__instance = super(Meta, self).__call__(*args, **kwds) return self.__instance class Single(metaclass=Meta): pass
这个实现单例模式的原理是,元类只会初始化一次,但是,每实例化一个类,都会回调一次元类对象
1.2 装饰器
from multiprocessing import Lock from threading import RLock single_lock = RLock() def Singleton(cls): instance = {} def _singleton_wrapper(*args, **kargs): with single_lock: if cls not in instance: instance[cls] = cls(*args, **kargs) return instance[cls] return _singleton_wrapper @Singleton class Single(): pass
使用局部变量来记录是否创建了一个类
1.3 魔法方法
from typing import Type, Any from threading import RLock from typing_extensions import Self single_lock = RLock() class Single(): def __new__(cls: Type[Self], *args: Any, **kwargs: Any) -> Self: with single_lock: if not hasattr(cls, "__instance"): setattr(cls, "__instance", super(Single, cls).__new__(cls)) return getattr(cls, "__instance")
原理是,将
__instance
数据绑定到类中,实现单例模式
2、 常量类
在constant.py
文件中,写入如下代码:
from typing import Type, Any from threading import RLock from typing_extensions import Self import sys single_lock: RLock = RLock() # 线程锁 class Const(object): def __new__(cls: Type[Self], *args: Any, **kwargs: Any) -> Self: """实现单例模式""" with single_lock: if not hasattr(cls, "__instance"): setattr(cls, "__instance", super(Const, cls).__new__(cls)) return getattr(cls, "__instance") class ConstValueError(PermissionError): pass class ConstCaseError(PermissionError): pass def __setattr__(self: Type[Self], __name: str, __value: Any) -> None: if __name in self.__dict__: """不能进行二次修改""" raise self.ConstValueError(f"不能修改常量 {__name} 的值 ") if not __name.isupper(): """规范性验证""" raise self.ConstCaseError(f"常量名称 {__name} 必须大写") self.__dict__[__name] = __value # 设置值 def __getattr__(self: Type[Self], __name) -> Any: """通过点获取元素""" return self.__dict__[__name] def __setitem__(self: Type[Self], __name: str, __value: Any) -> None: if __name in self.__dict__: """不能进行二次修改""" raise self.ConstValueError(f"不能修改常量 {__name} 的值 ") if not __name.isupper(): """规范性验证""" raise self.ConstCaseError(f"常量名称 {__name} 必须大写") self.__dict__[__name] = __value # 设置值 def __getitem__(self: Type[Self], __name: str) -> Any: """通过字典的键值对获取元素""" return self.__dict__[__name] sys.modules[__name__]: Const = Const() # 将类添加到模块中
测试文件:
import constant as const const.A = "asd" # 定义一个常量 print(const.A) const.A = "asdq"
三、 打包
最后,我们还可以将我们的项目进行打包,发布到pypi里面,供大家使用:
这里使用的是poetry进行包管理
在项目根目录下:
poetry publish --build # 按照要求进行配置账号就可以了,注意,项目名需要是惟一的,不然会发布失败
发布完成后,我们就可以使用我们自己创建的插件了。
本文来自博客园,作者:Kenny_LZK,转载请注明原文链接:https://www.cnblogs.com/liuzhongkun/p/16823281.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?