首页 > 编程语言 >Python实现常量

Python实现常量

时间:2022-10-24 22:36:52浏览次数:83  
标签:__ 常量 instance Python self 实现 cls Any name

目录

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

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

标签:__,常量,instance,Python,self,实现,cls,Any,name
From: https://www.cnblogs.com/liuzhongkun/p/16823281.html

相关文章

  • JWT鉴权如何实现
    如何实现jwt鉴权机制?JWT(JSONWebToken),本质就是一个字符串书写规范,作用是用来在用户和服务器之间传递安全可靠的信息为什么需要token在后台管理系统中,我们通常使用cook......
  • 【python】装饰器基础
    什么是装饰器?装饰器本质上是一个函数,该函数用来处理其他函数,它可以让其他函数在不需要修改代码的前提下增加额外的功能,装饰器的返回值也是一个函数对象。它经常用于有切......
  • react是如何实现事件代理的
    _版本:v18.2.0本文为我花了大半年的时间潜心研究所写,转载请注明出处,谢谢react是如何实现事件代理的createRoot函数**用户在index.tsx中执行ReactDOM.createRoot创建roo......
  • 学习笔记:python公约数和公倍数
    python学习题目:输出两个数的最大公约数和最小公倍数,解题思路先将较大的数和较小的数求出来创建一个空列表然后对小的数做循环找两个数的公因数加入空列表中在用max......
  • Python 中3.6及之前版本datetime没有fromisoformat()的解决方法
    Python中可以使用datetime的fromisoformat()方法将字符串转成datetime对象,但只有Python3.7以上才支持,Python3.6及之前的版本不支持,调用会报错:AttributeError:typeobje......
  • python -c 执行单行命令或脚本
    python-c执行单行命令或脚本背景:最新在编写shell脚本实现数据库的自动巡检功能,在某些巡检项需要处理json类型的数据。使用不擅长处理字符串的shell来处理json,各......
  • Python教程Day12-函数(一)
    函数(一)一、函数的作用​​需求​​:用户到ATM机取钱输入密码后显示"选择功能"界面查询余额后显示"选择功能"界面取2000钱后显示"选择功能"界面特点:显示“选择功能”界面需要......
  • Python教程Day12-函数(二)
    函数(二)一、变量作用域一个程序的所有的变量并不是在哪个位置都可以访问的。访问权限决定于这个变量是在哪里赋值的。变量作用域指的是变量生效的范围,主要分为两类:局部变量......
  • 利用一个字符数组作函数参数,实现字符串(最大长度为80个字符 )的逆序存放。
    利用一个字符数组作函数参数,实现字符串(最大长度为80个字符)的逆序存放。要求如下:(1)在子函数Inverse中实现字符串的逆序存放。函数原型为:voidInverse(charstr[]);(2......
  • python之第三方库netifaces库:netifaces 模块用于提供有关网络接口及其状态的信息(①获
    前言1、 在系统运维等过程中,网络永远是离不开的话题。网络中比较基础的是网络接口,每个网络接口都有一个名字,并且有它的ip地址,还有关于从这个接口出去的包的路由。我们可......