1. 运算符和表达式的应用方式

程序就是对数据进行处理 , 表示数据的值(对象)可以用变量给它们起名字(用变量名引用这些值(对象)) , 对这些变量或值进行处理可使用一些特殊的符号如+*等进行加法、乘法等运算 , 这些表示不同运算功能的特殊符号称为运算符(operators)。这些运算符操作的变量或值称为"运算数(operands)"。例如:

2+3
3/(5+2)
3*"world"

+/*()这些运算符对运算数进行运算的式子就是表达式(expression) , 即表达式是由运算数(值、变量、对象)和运算符构造的。

因为这些表示运算的运算符来自人们熟悉的符号 , 用它们构成的表达式的含义都很清楚。

不同类型的对象支持的运算符是不同的 , 如不能对 2str 字符串类型的变量应 用-*///等运算 , 也不能对 1 个字符串和 1 个整数进行如-+/等运算。例如 , 下面的都是非 法的:

'hi'-1 'Hello'/123 'hi'*'Hello' '15'+2 

即使可以对 2 个字符串应用+运算符 , 其含义也不同于 2 个整数的加法运算 , 而实际是对 2 个 字符串进行拼接。同样 , 对 1 个字符串和 1 个整数可以应用乘法运算符* , 其含义是产生一个重复复制的字符串。例如:

>>> s1 = "hello"
>>> s2 = s1+"world"
>>> s3 =3*"world"
>>> print(s2)
helloworld
>>> print(s3)
worldworldworld

不同运算符具有不同的优先级和结合性。例如:

3+5/2 #优先级:先乘除后加减
3+5-2 #结合性:从左向右计算

"3+5/2"中运算符/优先于+ , “3+5-2”中+-具有同样的优先级 , 但它们的结合性都是"从左向右" 。因此 , 先计算左边的+ , 再计算右边的-

2. 运算符种类

Python 有不同功能的各种运算符 , 如进行数学计算的"算术运算符" , 比较2 个运算数大小的"比较运算符" , 进行逻辑运算的"逻辑运算符" ,对二进制位进行操作的"二进制运算符" , 有对变量赋值的"赋值运算符" ,还有一些特殊的运算符。

  1. 算术运算符(arithmetic operators)

    //表示整数除法 , 而/表示的是浮点除法 , %用于求2个整数相除的余数。

    运算符

    含义

    示例

    结果

    +

    15+2

    17

    -

    2-15

    -13

    *

    15*2

    30

    /

    浮点除

    15/2

    7.5

    //

    整数除

    15//2

    7

    **

    2**15

    225

    %

    求余

    15%2

    1

    如:

    >>> print(15.3/2.5)
    6.12
    >>> print(15.3//2.5)      #转为整数除 , 相当于15//2
    6.0
    >>> print(15.3%2.5)      #15.3除2.5的余数
    0.3000000000000007
    >>> print(15.3**2.5)     #15.3的2.5次方
    915.6480546203329
    >>>
  2. 比较运算符(comparison operators)

    对两个量进行比较 , 产生的结果是一个表示"真"(True)或"假"(False)的bool(布尔)类型的值。例如:

    运算符

    含义

    示例

    结果

    >

    大于

    15>2

    True

    <

    小于

    15<2

    False

    ==

    等于

    15==2

    False

    !=

    不等于

    15!=2

    True

    >=

    大于等于

    15>=2

    True

    <=

    小于等于

    15<=2

    False

  3. 逻辑运算符(logical operators)

    逻辑运算符andornot分别表示逻辑与、逻辑或、逻辑非运算。 在逻辑运算中 , True、非0或非空对象就是真(True) , 而False0或空对象就是假(False)。 当一个对象x是真(True、非0值或非空值)时 , not x就是False , 当x是假(False0或空值) 时 , not x就是True(真)。例如:

    >>> print(not 0)
    True
    >>> print(not [])
    True
    >>> print(not False)
    True
    >>> print(not 2)
    False
    >>> print(not [3])
    False
    >>> print(not True)
    False
    >>>

    假设有2个对象xy , 当x是真时 , x or y的结果就是x , 当x是假时 , x or y的结果就是y。 例如:

    >>> print(3 or 5)      #因为3是真 , 所以3 or 5的结果就是3
    3
    >>> print(3 or 2)      #因为3是真 , 所以3 or 2的结果就是3
    3
    >>> print(0 or 2)      #因为0是假 , 所以0 or 2的结果就是2
    2
    >>> print(False or True)
    True
    >>> print(False or [])
    []
    >>> print({} or 2)     #因为{}是假 , {} or 2的结果就是2
    2
    >>>

    假设有2个对象xy , 当x是真时 , x and y的结果就是y , 当x是假时 , x and y的结果就是x。 例如:

    >>> print(3 and 5)      #因为3是真 , 所以3 and 5的结果就是5
    5
    >>> print(3 and 2)      #因为3是真 , 所以3 and 2的结果就是2
    2
    >>> print(0 and 2)      #因为0是假 , 所以0 and 2的结果就是0
    0
    >>> print(False and True)
    False
    >>> print(False and [])
    False
    >>> print({} and 2)     #因为{}是假 , 所以{} and 2的结果就是{}
    {}
    >>>

    逻辑运算符andornot的含义及其示例如下表所示 :

    运 算 符

    含义

    示例

    结果

    and

    x and y

    x是真时 , x and y的结果就是y ; 当x是假时 , x and y的结果就是x

    or

    x or y

    x是真时 , x or y的结果就是x ; 当x是假时 , x or y的结果就是y

    not

    not x

    x是真时 , not x的结果就是False ; 当x是假时 , not x的结果就是True

    3个逻辑运算符具有不同的优先级 , and优先于or , not优先于andor。例如 :

    >>> print(2 or 5 and 3)
    2
    >>> print( (2 or 5) and 3)  #可用圆括号()改变运算符的计算次序
    3
  4. 位运算符(bit operators)

    任何量在计算机内存里都是用1串二进制位表示的。 假如有2个数 , a = 37b = 22是用1字节表示的 , 则其内存的二进制位如下所示:

    a = 0 0 1 0 0 1 0 1 
    b = 0 0 0 1 0 1 1 0 

    "位运算" : 对运算数的二进制位进行相应的运算。其中 , &(位与)、|(位或)、^(异或)是对2 个运算数的对应二进制位进行运算 , 而~(取反)、<<(左移位)、>>(右移位)则是对1个运算数的二进制位进行运算。

    二元位运算符的运算规则如下表所示。3个二元位运算符的运算规则如下。

    p

    q

    p & q

    p | q

    p ^ q

    0

    0

    0

    0

    0

    0

    1

    0

    1

    1

    1

    0

    0

    1

    1

    1

    1

    1

    1

    0

    • &(位与)运算:只有pq都是1时 , p&q的结果才是1;如果有一个为0 , 则结果是0

    • |(位或)运算:只要pq有一个是1时 , p|q的结果就是1;如果pq都为0 , 则结果是0

    • ^(异或)运算:当pq不同(一个是0 , 另一个 是1)时 , p^q的结果是1 , 否则结果是0

    例如 , 对a、b的&|^运算是对它们的对应二进制位进行运算:

    a & b  = 0 0 0 0 0 1 0 0 
    a | b  = 0 0 1 1 0 1 1 1 
    a ^ b  = 0 0 1 1 0 0 1 1 

    下面对a,b&|^ 运算的代码

    >>> a = 37
    >>> b = 22
    >>> print('a = ','{:08b}'.format(a))
    a =  00100101
    >>> print('b = ','{:08b}'.format(b))
    b =  00010110
    >>> print('a&b=','{:08b}'.format(a&b))
    a&b= 00000100
    >>> print('a|b=','{:08b}'.format(a|b))
    a|b= 00110111
    >>> print('a^b=','{:08b}'.format(a^b))
    a^b= 00110011

    一元位运算符取反~、左移<<、右移>>的运算规则如下。

    • (取反) : 将每个二进制取反(0变成1 , 1变成0)。例如 , 对x , ~x的结果相当于-x-1 , 如22的补是-23。

    • <<(左移) : 各二进制位全部左移若干位 , 高位丢弃 , 低位补0

    • >> (右移) : 各二进制位全部左移若干位 , 无符号数 , 高位补0。

    例如 , 对b<<~运算的结果如下:

    b<<2 = 0 1 0 1 1 0 0 0 
    ~b   = 1 1 1 0 1 0 0 1

    下面代码输出了对b<<>>运算的二进制表示:

    >>> print('b =   ','{:08b}'.format(b))
    b =    00010110
    >>> print('b<<2: ','{:08b}'.format(b<<2))     #b的二进制左移2位 , 右边低位补充0
    b<<2:  01011000
    >>> print('b>>2: ','{:08b}'.format(b>>2))     #b的二进制右移2位 , 左边高位补充0
    b>>2:  00000101
    >>> print('~b:   ','{:08b}'.format(~b))       #~b就是-(b+1) , b=22的补是-23
    ~b:    -0010111
    >>> print(b)
    22
    >>> print(b<<2)
    88
    >>> print(b>>2)
    5
    >>> print(~b)
    -23
    >>>

    其中的取反运算~涉及1个数在计算机内部的二进制表示。数字在计算机中是以补码保存的 , 所以Python位运算是作用在补码上的。假如 , 用8位二进制表示 , 正整数1 , 其二进制的原码是 00000001 , 而负整数-1 , 其二进制的原码是10000001 , 即左边的最高位1表示这是一个负数。除原码外 , 1个数在计算机内部还可以用反码和补码表示。正数的反码与其补码和原码是一样的 , 如1 的反码和补码都是0000001 , 而负数的反码除左边最高位外 , 其他位都是原码的取反 , 如-1的反码是11111110 , 而补码就是在反码基础上加上1 , 即-1的补码是11111111

    b=22的原码、反码和补码都是00010110。对b的二进制取反的结果就是11101001 , 这个数实际上是-(b+1)的补码。因为-b的二进制原码是10010110 , 而-(b+1)的二进制原码是10010111 , 其补码就是11101001。但bin()strfromat()会将~b的补码表示转换成原码表示 , 因此 , 尽管~b 运算产生的二进制是11101001 , 但显示的仍是其二进制原码10010111

  5. 赋值运算符

    赋值运算符=是给1个对象起1个名字 , 如简单的赋值运算符=的语句"x=3" ,就是给对象3起 了一个变量名x。例如:

    x = 2
    x = x+3

    在表达式"x = x+3" 中 , 右边的变量x引用的是原先的对象 , 而左边的变量x引用的是新的结 果对象。

    简单赋值运算符可以和算术、位运算结合构成复合赋值运算符。例如:

    x = 2
    x += 3   

    "x += 3"实际上是"x = x+3"的简写 , 即"将x+3的结果赋值给x" , 也就是说 , 给x+3的结果对象起了一个名字x。变量x现在引用的是一个新的结果对象而不是原来的2 , 可以通过输出xid来验证这一点:

    >>> x=2
    >>> y = x      # y和x都是对象2的名字
    >>> print(x)
    2
    >>> print(id(x))
    2866222006544
    >>> x**=3   #相当于x = x**3
    >>> print(x)
    8
    >>> print(id(x))
    2866222006736
    >>> print(y)
    2
    >>> print(id(y))
    2866222006544
    >>>

    Python的赋值运算符如下表所示

    运算符

    示例

    等价于

    =

    x = 3

    x = 3

    +=

    x += 3

    x = x + 3

    -=

    x -= 3

    x = x - 3

    *=

    x *= 3

    x = x * 3

    /=

    x /= 3

    x = x / 3

    %=

    x %= 3

    x = x % 3

    //=

    x //= 3

    x = x // 3

    **=

    x **= 3

    x = x ** 3

    &=

    x &= 3

    x = x & 3

    |=

    x |= 3

    x = x | 3

    ^=

    x ^= 3

    x = x ^ 3

    >>=

    x >>= 3

    x = x >> 3

    <<=

    x <<= 3

    x = x << 3

  6. 成员运算符( in , not in)

    成员运算符innot in用于判断一个值(对象)是否在一个容器对象 , 如liststrtuple对象中 , 这2个运算符返回的结果是TrueFalse

    >>> alist = [2,5,7,8]
    >>> print(3 in alist)
    False
    >>> print(5 in alist)
    True
    >>> print(3 not in alist)
    True
    >>> print(5 not in alist)
    False
  7. 身份运算符(is , is not)

    身份运算符isis not用于判断2个变量(标识符)是不是引用的同一个对象。例如:

    >>> a = 10
    >>> b = 10
    >>> print(id(a))
    2866222006800
    >>> print(id(b))
    2866222006800
    >>> print(a is b)
    True
    >>> print(a is not b)
    False

    再如:

    >>> a = 1000
    >>> b = 1000
    >>> print(id(a))
    2866223030640
    >>> print(id(b))
    2866223030512
    >>> print(a is b)
    False
    >>> print(a is not b)
    True

    这是因为 , Python解释器执行时会将小整数驻留在内存中 , 将小整数赋值给多个变量 , 它们实际引用的是同一个对象。而将整数赋值给不同变量 , 这些变量将引用临时创建的不同对象。

3. 运算符的优先级

  1. 运算符的优先级

    当一个表达式中有多个运算符时 , 这些运算符的计算是有先后次序的 , 即运算符是具有不同的优先级的。例如 ,算术运算符总是"先乘除 , 后加减" , 同样级别的运算符 , 如+-则按照“自左往后的次序”计算。例如:

    3 + 5/2 - 4

    先做除法"5/2",然后做加法,即用"3"和"5/2"的结果相加,最后才做减法,即前面加法的结果和4相减。

    再比如,同样是逻辑运算,notand优先级高, 而andor优先级高。

    实际上,无须记忆这些运算符的优先级,如果 不清楚不同运算符的优先级,则可以简单地用圆括 号,使其按照希望的意图进行计算。例如:

    (3 + 5 ) / (2 - 4)
  2. 运算符的优先级表

    Python运算符的优先级表如下(从上到下 优先级从高变低)。

    运算符

    描述

    ()

    圆括号

    f(args)

    函数调用

    x[index:index]

    切片

    x[index]

    下标

    x.attribute

    属性引用

    **

    指数

    ~x

    +x-x

    一元正号、一元负号

    */%

    乘、除、求余

    +-

    加、减

    <<>>

    位左移、位右移

    &

    位与

    ^

    异或

    |

    位或

    innot inisnot is<<=>>==<>!===

    比较、成员、身份

    not x

    逻辑非

    and

    逻辑与

    or

    逻辑或

    lambda

    lambda表达式


熊熊