起因

在一些函数中,我们有时候只想要指定的几个输入,但是在代码/函数 交给别人使用的时候,别人还需要看文档,甚至不知道该传什么值,这个有一点不友好。

所以,我们想在代码中定义一些常量,供代码使用者调用。

使用变量

# const.py

CAT = 'cat'
DOG = 'dog'

这个时候,我们就可以使用了

import const

const.CAT

image

嗯。。。。。这个时候我们又有一个类型了

# const.py

CAT = 'cat'
DOG = 'dog'

MAC = 'mac'
WIN = 'windows'
LINUX = 'linux'

我们再来看一下

image

???(黑人问号脸),改选哪一个,CAT 是什么鬼?

使用类 + property

现在的常量代码如下

# const.py


class _Animal(object):
    @property
    def cat(self):
        return 'cat'

    @property
    def dog(self):
        return 'dog'


class _Platform(object):
    @property
    def mac(self):
        return 'mac'

    @property
    def win(self):
        return 'windows'

    @property
    def linux(self):
        return 'linux'


Animal = _Animal()
Platform = _Platform()

使用: image

image

嗯。。很好,现在有了刚刚吐槽的 分类 的功能。

不过有一天,有一个二货改了你的常量!!!

const.Platform.mac = 'windows'

你是不是是不是傻了?

不过这是不可能的,嘿嘿,因为没有设置 @mac.setter修饰器的方法! image

但是呢,这里还有一个问题,就是这代码也太长了吧,为了定义一个常量,需要 3 行代码,假如有 20 个常量呢。。。不仅写起来麻烦,看代码也很烦啊!!

使用类修饰器

# const.py


class _Platform(object):
    mac = 'mac'
    windows = 'windows'
    linux = 'linux'


Platform = _Platform()

代码是减了不少,但是值可以改变。所以为了避免这样的情况,需要给类加一个修饰器~

# const.py

from functools import wraps


def Const(cls):
    @wraps(cls)
    def new_setattr(self, name, value):
        raise Exception('const : {} can not be changed'.format(name))

    cls.__setattr__ = new_setattr
    return cls


@Const
class _Platform(object):
    mac = 'mac'
    windows = 'windows'
    linux = 'linux'


Platform = _Platform()

image

最终的代码

# const.py

from functools import wraps


def Const(cls):
    @wraps(cls)
    def new_setattr(self, name, value):
        raise Exception('const : {} can not be changed'.format(name))

    cls.__setattr__ = new_setattr
    return cls


@Const
class _Animal(object):
    cat = 'cat'
    dog = 'dog'


@Const
class _Platform(object):
    mac = 'mac'
    windows = 'windows'
    linux = 'linux'


@Const
class _Const(object):
    animal = _Animal()
    platform = _Platform()


CONST = _Const()