在实际的程序开发中,我们通常会将一个不可变的变量声明为一个常量。在很多高级语言中都会提供常量的关键字来定义常量,如 C++ 中的 constJava 中的 final 等,但是 Python 语言因为变量无类型,所以也就不存在这样的修饰符,其本身并未提供任何机制来进行常量的定义。因此我们只能通过自己定义类的方法来定义一个符合常量规则的类,使得该类定义的成员属性满足常量的属性。常量一般符合以下两条规则:

  1. 常量的各个字母使用大写字母表示,中间以下划线连接:如 MAX_VALUE;
  2. 常量的值一旦绑定则不可以再修改。

由于常量的值一旦绑定则不可再修改,所以也就是说对常量二次赋值时需要抛出异常。因此我们显然需要改写自定义的常量类的赋值方法。在 Python 中,当我们对类的属性进行赋值时,会自动调用 object 类的 __setattr__() 函数,该函数的定义如下:

object.__setattr__(self, name, value)

其中的 name 表示属性的名称,value 是试图赋值给 name 的值,其中 object 类的 object.__dict__ 以字典的形式保存了所有已赋值的属性。

因此我们可以通过定义一个常量类 constant 类(默认继承自object),并对 object.__setattr__() 方法进行重写。由于常量有两条规则,所以我们需要根据这两条规则自定义两个异常处理,分别是二次赋值的异常处理和名称非大写的异常处理。

异常处理的定义方式请参看:Python 错误和异常

定义常量类:

constant.py

import sys

class _const:
# 自定义异常处理
class ConstError(PermissionError):
pass
class ConstCaseError(ConstError):
pass
# 重写 __setattr__() 方法
def __setattr__(self, name, value):
if name in self.__dict__: # 已包含该常量,不能二次赋值
raise self.ConstError("Can't change const {0}".format(name))
if not name.isupper(): # 所有的字母需要大写
raise self.ConstCaseError("const name {0} is not all uppercase".format(name))
self.__dict__[name] = value # 将系统加载的模块列表中的 constant 替换为 _const() 实例
sys.modules[__name__] = _const()

在其它文件中定义常量,test.py

import constant
constant.VALUE = 5
constant.VALUE = 4 # ConstError
constant.vaLue = 1 # ConstCaseError

当我们识图修改常量 VALUE 的值或者定义一个名称不是全部大写的常量时,都会抛出异常,这样就达到了不可更改常量的值的目的。

Python 定义自己的常量类的更多相关文章

  1. Python 定义常量

    常量在编写程序的时候,一旦设定就不能再进行变动,常量一种约定俗成的方式,所有字母大写并用下划线分隔单词的方式(如MAX_VALUE, OUT_TIME等),但是python没有提供设置常量用法,需要自 ...

  2. python的异常处理及异常类定义

    python的异常处理语法和大多数语言相似: try: try块的语句... except exceptiontype1 as var:#使用as语句获得本次捕获到的异常的实例var except块语 ...

  3. python定义接口继承类

    zxq547 python定义接口继承类invalid syntax解决办法 1 2 3 4 5 6 7 class s_all(metaclass=abc.ABCMeta):     #python ...

  4. Python语法基础-函数,类以及调试处理

    [TOC] 1. 函数的定义 python中函数有两种: python自带的函数 用户定义函数 返回多个值 原来返回值是一个tuple!但是,在语法上,返回一个tuple可以省略括号,而多个变量可以同 ...

  5. python基础——实例属性和类属性

    python基础——实例属性和类属性 由于Python是动态语言,根据类创建的实例可以任意绑定属性. 给实例绑定属性的方法是通过实例变量,或者通过self变量: class Student(objec ...

  6. python 静态方法,类方法 ,类的继承

    转自:  http://cowboy.1988.blog.163.com/blog/static/75105798201091141521583/ 1.关于定义类的一些奇特之处  今天在Python中 ...

  7. Python 中的函数与类的方法

    注:本文转译自 Stackoverflow 上 Adding a Method to an Existing Object 的最佳回答. 在 python 中,def 定义的函数与类中的方法有很大的不 ...

  8. python学习小结4:类

    虽然Python是解释性语言,但是它是面向对象的,能够进行对象编程. 类和对象是面向对象编程的两个主要方面.类:创建一个新类型,而对象是这个类的实例,类使用class关键字创建.类的域和方法被列在一个 ...

  9. Python属性、方法和类管理系列之----属性初探

    在学习dict的时候,肯定听过dict是Python中最重要的数据类型,但是不一定知道为什么.马上你就会明白原因了. Python中从模块.到函数.到类.到元类,其实主要管理方法就是靠一个一个的字典. ...

随机推荐

  1. WPF Calendar 日历控件 样式自定义

    原文:WPF Calendar 日历控件 样式自定义 粗略的在代码上做了些注释 blend 生成出来的模版 有的时候 会生成 跟 vs ui界面不兼容的代码 会导致可视化设计界面 报错崩溃掉 但是确不 ...

  2. python socket 客服端服务端编程

    客服端编程 import socket try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) except socket.error a ...

  3. Win8 Metro(C#)数字图像处理--2.62图像对数增强

    原文:Win8 Metro(C#)数字图像处理--2.62图像对数增强  [函数名称]   对数增强      WriteableBitmap LogenhanceProcess(Writeabl ...

  4. Android零基础入门第1节:Android的前世今生

    原文:Android零基础入门第1节:Android的前世今生 现在网上有很多各色Android资料了,但相对来说还是比较零散,Android覆盖的范围极广,最近刚好有机会全部拉通整理一遍,也保存起来 ...

  5. 龙芯GO!龙芯平台上构建Go语言环境指南

    龙芯软件生态系列——龙芯GO!龙芯平台上构建Go语言环境指南2016-07-05 龙芯中科1初识Go语言Go语言是Google公司于2009年正式推出的一款开源的编程语言,是由Robert Gries ...

  6. C# System.Windows.Forms.WebBrowser中判断浏览器内核和版本

    参考 [完美]原生JS获取浏览器版本判断--支持Edge,IE,Chrome,Firefox,Opera,Safari,以及各种使用Chrome和IE混合内核的浏览器 利用js来判断 namespac ...

  7. ASP.NET MVC控制器Controller中参数

    前述文章参见:ASP.NET MVC控制器Controller 绪论 之前的控制器返回的均为常量字符串,接下来展示如何获取请求传来的参数,而返回"动态"的字符串. 可以在操作方法B ...

  8. 【码云周刊第 23 期】Web 高效开发必备的 PHP 框架(从这里学起)good

    码云项目推荐 1.项目名称:多功能 THinkPHP 开源框架 项目简介:使用 THinkPHP 开发项目的过程中把一些常用的功能或者第三方 sdk 整合好,开源供亲们参考,如 Auth 权限管理.支 ...

  9. Qt:正确判断文件、文件夹是否存在的方法

    一直对Qt的isFile.isDir.exists这几个方法感到混乱,不知道到底用哪个,网上搜了下资料,也是用这几个方法但是都没有对其深究,经过测试发现会存在问题,先看看下面的测试代码 { QFile ...

  10. DELPHI之关于String的内存分配(引)

    在函数.过程或者方法中定义一个字符串变量时,由于我们知道在函数.过程或者方法中定义的变量为局部变量,它的内存 是在栈中分配的,但是这里有个小细节我们要注意,对于一个局部的字符串变量,它的大小为4字节, ...