常量

值不可以变化的量,即为常量。因为种种原因,Python并未提供如C,C++,Java一样的const修饰符来声明常量,换言之,Python中没有声明常量的语法。Python程序一般通过约定俗成的变量名全大写的形式来表示这是一个常量(实际上还是变量)。

例如:

1
2
3
4
5
6
7
MYNAME = "Python"  # 实际上,MYNAME还是一个变量。
print(type(MYNAME))
print(MYNAME)

MYNAME = 100
print(type(MYNAME))
print(MYNAME)

执行以上程序会输出如下结果:

1
2
3
4
<class 'str'>
Python
<class 'int'>
100

Python内置常量

Python内有一些内置常量(和前面介绍的大写表示的常量不同,内置常量的值是不可改变的),主要是以下。

False
bool类型,表示错误值。对False的赋值是非法的,并引发语法错误,抛出SyntaxError异常。

True
bool类型,表示正确值。对True的赋值是非法的,并引发语法错误,抛出SyntaxError异常。

None
NoneType类型的唯一的值。None通常用于表示缺少值,例如当默认参数未传递给函数时。对None的赋值是非法的,并引发语法错误,抛出SyntaxError异常。bool(None)结果是False。

NotImplemented
NotImplementedType类型,故名思议,就是“未实现”,一般是用在一些比较算法中的。如果二元比较算法(如__eq__(), __lt__(), __add__(), __rsub__(),__imul__(), __iand__()等)没有提供具体的比较实现时,应返回此值表示还没有实现。bool(NotImplemented)结果是True。

Ellipsis
与省略号文本”…“相同。主要与用户定义的容器数据类型的扩展切片语法一起使用的特殊值。bool(Ellipsis)结果是True。
这东西有啥用呢?据说它是Numpy的语法糖,不玩Numpy的人,可以说是没啥用的。在网上只看到用 “…” 代替 pass ,稍微有点用。

例如:

1
2
3
4
try:
    1/0
except ZeroDivisionError:
    ...    # 代替pass

debug
如果python不是以-o选项启动的,则此常量的值为是True。反之是False。

示例,打印内置常量的值和类型

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
print(False)             # 输出 False
print(True)              # 输出 True
print(None)              # 输出 None
print(NotImplemented)    # 输出 NotImplemented
print(Ellipsis)          # 输出 Ellipsis
print(__debug__)         # 输出 True

print(type(False))         # 输出 <class 'bool'>
print(type(True))          # 输出 <class 'bool'>
print(type(None))          # 输出 <class 'NoneType'>
print(type(NotImplemented))# 输出 <class 'NotImplementedType'>
print(type(Ellipsis))      # 输出 <class 'ellipsis'>

执行以上程序会输出如下结果:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
False
True
None
NotImplemented
Ellipsis
True
<class 'bool'>
<class 'bool'>
<class 'NoneType'>
<class 'NotImplementedType'>
<class 'ellipsis'>

示例,内置常量的bool类型转换

1
2
3
4
5
6
print(bool(False))         # 输出False
print(bool(True))          # 输出True
print(bool(None))          # 输出False
print(bool(NotImplemented))# 输出True
print(bool(Ellipsis))      # 输出True
print(bool(__debug__))     # 输出True。如果Python是以-o选项启动的话,结果是False。

执行以上程序会输出如下结果:

1
2
3
4
5
6
False
True
False
True
True
True

示例,Ellipsis和…

1
2
3
4
5
6
7
8
9
# 比较Ellipsis和...
result = Ellipsis is ...
print(result)           # 输出True

print(type(Ellipsis))
print(type(...))

print(bool(Ellipsis))   # 输出True
print(bool(...))        # 输出True

执行以上程序会输出如下结果:

1
2
3
4
5
True
<class 'ellipsis'>
<class 'ellipsis'>
True
True

注意: NotImplemented并不是异常,所以不能使用raise。当需要返回值时,应该是return NotImplemented。

我们看下面一个例子:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
class Person:  
    def __init__(self, age):  
        self.age = age

    def __eq__(self, other):  
        if not isinstance(other, Person):  
            return NotImplemented  
        return self.age == other.age

person = Person(10)  
print(person == 10) # 输出False

为啥结果是false呢?
NotImplemented对象向运行时环境发出一个信号,告诉运行环境如果当前操作失败,它应该再检查一下其他可行方法。例如在 a == b 表达式,如果 a.__eq__(b) 返回 NotImplemented,那么 Python 会尝试 b.__eq__(a)。如果调用 b 的__eq__() 方法可以返回 True 或者 False,那么该表达式就成功了。如果 b.__eq__(a) 也不能得出结果,那么 Python 会继续尝试其他方法,例如使用 != 来比较。

person == 10,首先person.__eq__(10)返回NotImplemented,接下来10.__eq__(person)返回false。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
class Person:  
    def __init__(self, age):  
        self.age = age

    def __eq__(self, other):  
        if not isinstance(other, Person):  
            return NotImplemented  
        return self.age == other.age

class Age:  
    def __init__(self, age):  
        self.age = age

    def __eq__(self, other):  
        return self.age == other.age

person = Person(10)  
age = Age(10)
print(person == age) # 输出True

首先person.__eq__(age)返回NotImplemented,接下来age.__eq__(person)返回True。

我们在写一些基础代码时,即使是没实现,也不要raise NotImplementedError,而是return NotImplemented,相当于提供给其它不同对象的比较接口,这对代码扩展非常有好处。


参考资料:
https://www.jianshu.com/p/23df8d592a31