当前位置 博文首页 > zy010101博客:python——赋值

    zy010101博客:python——赋值

    作者:[db:作者] 时间:2021-06-05 23:24

    赋值

    赋值操作,本来没有什么细节。但是python现在的赋值操作也是花里胡哨的,跟C++快一样烦人了,你不用这种方式,总有人用,因此还是有必要学一下。就像切片能够完成删除,增加一样,虽然很不好,但是python支持这种做法,就难免有人这么写。

    序列赋值

    直接看代码,
    其中第三行的赋值是可行的,合法的语句,不像表明上看到的A, B组成一个元组,元组是不可变对象,因此无法赋值。

    >>> a = 1
    >>> b = 2
    >>> A, B = 3, 4
    >>> [C, D] = [5, 6]
    >>> a
    1
    >>> b
    2
    >>> A
    3
    >>> B
    4
    >>> C
    5
    >>> D
    6
    

    接着再来看下一段代码

    >>> [C, D] = 7, 8
    >>> C
    7
    >>> D
    8
    

    左边是列表,右边是元组。赋值成功。
    这种操作是由于python会在赋值的时候发生解包操作,这个操作能够在赋值运算符左右两侧的序列长度是相等的情况下进行。结果就是赋值运算符左侧的序列从左到右被赋予赋值运算符右侧序列左到右的值。
    接着来看更高级的操作,这些操作虽然便利,但是大多数人应该不怎么喜欢。

    >>> string = 'abc'
    >>> a,b,c = string
    >>> a,b,c
    ('a', 'b', 'c')
    >>> (a, b),c = 'AB','CCC'
    >>> a,b,c
    ('A', 'B', 'CCC')
    

    虽然,有时候这些操作可能会显得很便利,但是这需要你花费时间学习这些语法,感觉和python的目的有些背道而驰,可能这样做会显得python比较高大上,而不是那么简单。

    python3中的扩展序列解包

    python3中对于那种将序列划分为“前面指定的一部分和剩余的部分”这种常见的编码模式提供了扩展序列解包方式。简而言之就是,使用一个带有*的变量,可以在赋值运算符左侧来将剩余部分的赋值接受。这么说可能不是很明白,看例子。

    L = 1,2,3,4,5,6,7,8,9
    >>> a,b,c,*d = L
    >>> a,b,c,d
    (1, 2, 3, [4, 5, 6, 7, 8, 9])
    

    d接受了L元组剩余的部分,并且d是一个列表。实际上d总会是一个列表。例如:

    >>> L = 1,2,3
    >>> a,b,c,*d = L
    >>> a,b,c,d
    (1, 2, 3, [])
    >>> L = 1,2,3,4
    >>> a,b,c,*d = L
    >>> a,b,c,d
    (1, 2, 3, [4])
    

    还可以有下面这种的骚操作,*b出现在待赋值序列的中间。但是不能在待赋值序列中出现两个及其以上的带*的变量。也不能只是一个单独的*变量。

    >>> L = 1,2,3,4
    >>> a,*b,c = L
    >>> a,*b,c
    (1, 2, 3, 4)
    >>> b
    [2, 3]
    >>> *d = L
      File "<stdin>", line 1
    SyntaxError: starred assignment     target must be in a list or tuple
    >>> a,*d,*f = L
      File "<stdin>", line 1
    SyntaxError: two starred    expressions in assignment
    >>> *d, = L     # OK
    >>> d
    [1, 2, 3, 4]
    

    多目标赋值

    多目标赋值操作很简单,但是需要注意,这些目标将会引用同一个对象。

    >>> a = b = c = [1,2,3]
    >>> id(a)
    140407591265984
    >>> id(b)
    140407591265984
    >>> id(c)
    140407591265984
    

    这种操作的对象是不可变的时候,对代码不会有任何影响,但是如果像上面这样,引用的对象是一个列表,那么一旦对象改变,那么可能会造成意料之外的效果。例如:

    >>> a.append(4)
    >>> b
    [1, 2, 3, 4]
    >>> c
    [1, 2, 3, 4]
    >>> a
    [1, 2, 3, 4]
    

    增量赋值

    这个操作是借鉴C语言的,因为该操作在数值计算的时候尤为方便。例如:

    x = x + 1
    x += 1
    

    上面这两个表达式是等价的,x += 1是上面的简写形式。
    当然了,增量赋值适用于任何支持二元表达式的对象类型。例如:

    x *= 2
    x /= 2
    x **= 100
    

    C/C++程序员注意,python没有支持x++(++x),x–(--x)这种自增或者自减方式。

    增量赋值和共享引用

    以+为例,进行说明。L = L + [3, 4]和L += [3, 4]在L本身是共享引用的时候可能会造成一些意外情况。下面直接看两段代码对比。

    +操作结果
    >>> L = [1,2]
    >>> M = L   # 共享引用
    >>> L = L + [3, 4]
    >>> L, M
    ([1, 2, 3, 4], [1, 2])
    
    
    +=操作结果
    >>> L = [1,2]
    >>> M = L   # 共享引用
    >>> L += [3, 4]
    >>> L, M
    ([1, 2, 3, 4], [1, 2, 3, 4])
    

    这种影响非常隐晦,但是一旦造成错误,那就是致命的。

    下一篇:没有了