Python实现常量

Python实现常量

一、 概述

很多高级编程语言都提供了定义常量的方法,一个常量一旦被定义,就无法再修改,这样做的意义在于防止其他人修改一些关键参数和配置。在C++,C#, php可以使用const关键字,java可以使用final,python没有提类似供定义常量的关键字,但我们可以通过一些技术手段实现类似的效果。

对于常量,有两个要求:

  1. 常量的命名必须都是大写字母,可以使用下划线连接单词
  2. 变量一旦赋值后,不可再修改

思路上,定义一个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 # 按照要求进行配置账号就可以了,注意,项目名需要是惟一的,不然会发布失败

发布完成后,我们就可以使用我们自己创建的插件了。

posted @   Kenny_LZK  阅读(358)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示