Python赋值、表达式和打印

赋值、表达式和打印

本文学习Python中的赋值语句,以及表达式和打印语句。

赋值语句

将等号右侧的对象的引用赋值给等号左侧的变量名

需记住:

  • 赋值语句建立对象的引用值,也就是赋值语句是将对象的引用值存储在变量名或者数据结构的元素内
  • 变量名在首次赋值时被创建,出现在表达式中的变量名,被其所引用的对象的值取代;
  • 变量名在引用前一定先赋值;
  • Python也执行隐式赋值,如:模块导入、函数和类的定义、for语句以及函数参数全是隐式赋值;

赋值语句的形式

赋值语句形式表

运算 解释
spam = 'Spam' 基本形式
spam, ham = 'yum', 'YUM' 元组赋值(位置性)
[spam, ham] = ['yum', 'YUM'] 列表赋值(位置性)
a, b, c, d = 'spam' 序列赋值,通用性
a, *b = 'spam' 扩展的序列解包
spam = ham = 'ok' 多目标赋值
spam += 2 增强赋值

表中第一种是最常见的,现在对其他几种做一些解释:

  • 元组及列表分解赋值
    • 表中第二第三种,Python按照位置将右边的对象和左边的目标从左到右配对。从内部实现来看,Python先在右边制作元素的元组。
  • 序列赋值语句
    • 元组及列表分解赋值语句已经统一成现在序列赋值语句。任何变量名的序列都可以赋值给任何值的序列。
  • 扩展的序列解包
    • 左边变量前加“*”号,可以将右侧剩余的对象匹配赋值,如表中第五行。
  • 多重目标赋值
    • Python赋值相同对象的引用值给左侧的所有变量。同样的对象具有不同的引用值变量。
  • 增强赋值语句
    • 以一种简洁的方式结合表达式和赋值语句的简写形式,如“+=”。这种形式输入少,执行快。
    • Python中,每个二元表达式运算符都有增强赋值语句。操作的主题若是可变的并且支持这一操作,增强赋值选择原处修改而不是对象副本,所以执行快。

结合上表,解析不同的赋值语句。

序列赋值

  • 常见序列赋值

    • 举例

      1
      2
      3
      4
      5
      name, age = 'wk', 18 //元组赋值
      [name, age] = ['wk', 18] //列表赋值
      // 进阶应用
      [name, age] = ('wk', 18)
      (n1, n2) = "wk"
  • 高级序列赋值语句模式

    • 举例,左右两侧数量应相等

      1
      2
      3
      string = 'spam'
      a, b, c, d = string
      a, b, c = string //error:ValueError
    • 这里的错误采用切片可以解决

      1
      2
      3
      4
      5
      a, b, c = string[0], string[1], string[2:]
      a, b, c = list(string[:2]) + [string[2:]]
      a, b = string[:2]
      c = string[2:]
      (a, b), c = string[:2], string[2:]
    • 最后给出的示例,可以应用到for语句

      1
      2
      for (a, b, c) in [(1, 2, 3), (4, 5, 6)]:
      for ((a, b), c) in [((1, 2), 3), ((4, 5), 6)]:
    • 函数的参数传递中也可以使用

      1
      2
      def f(((a, b), c)):
      f(((1, 2), 3))
    • 其他使用

      1
      2
      3
      4
      5
      6
      r, g, b = range(3)
      // while语句
      L = [1, 2, 3, 4]
      while L:
      front, L = L[0], L[1:]
      print(front, L)

Python 3中的扩展序列解包

类似于使用切片操作进行对象引用的赋值,将对象序列拆解成“前面的”和“剩余的”两部分,赋值给左侧变量,其中带有“*”的变量得到序列部分。

  • 常见解包应用

    • 举例

      1
      2
      L = [1, 2, 3, 4]
      a, *b = L // b = [2, 3, 4]
      1
      2
      3
      *a, b = L // a = [1, 2, 3]
      a, *b, c = L // b = [2, 3]
      a, b, *c = L // c = [3, 4]
    • 不仅是列表,对任何序列类型都有用

      1
      2
      3
      4
      a, *b = 'spam' // b = ['p', 'a', 'm']
      // 类似于切片,可有区别
      S = 'spam'
      S[0], S[1:] // S[1:] = 'pam'

      解包赋值得到的是多个匹配项的一个列表,切片是相同类型的一个序列

      while语句可以这样写:

      1
      2
      3
      4
      L = [1, 2, 3, 4]
      while L:
      front, *L = L
      print(front, L)
  • 边界情况

    • 假如超出边界,Python赋值空列表

      1
      2
      L = [1, 2]
      a, b, *c = L // c = []

多目标赋值语句

多目标赋值需要注意的是共享引用

因为同一个对象应用赋值给不同的变量,多个变量对同一个对象享有引用,其中一个对对象作修改的时候,可能直接改变原始对象引用值。

  • 不可变对象
1
2
a = b = 0
a += 1 // a = 1, b = 0
  • 可变对象
1
2
a = b = []
a.append(1) // a = [1], b = [1]

增强赋值语句

如下表:

x += y x &= y x -= y x |= y
X *= Y X ^= Y X /= Y X >>= Y
X %= Y X <<= Y X **= Y X //= Y

增强赋值语句有三个优点:

  1. 减少输入;
  2. 左侧只计算一次;
  3. 支持原处修改的对象,增强形式直接执行原处的修改操作;

对3的进阶:

队列表的操作,增加列表元素时,有合并操作+,以及有原处修改的追加append()extend(),合并操作+需创建列表复制,执行较慢。所以增强赋值语句选择的是可以原处修改的append()extend()

所以,增强赋值可以影响共享引用

变量命名

记住以下几点:

  • 语法
    • (‘‘ or 字母) + (任意数目的数字、字母 or ‘\‘)
  • 区分大小写
  • 禁止使用保留字
    以下是Python 3中保留字列表:
False class finally is return
None continue for lambda try
True def from nonlocal while
and del global not with
as elif if or yield
assert else import pass ``
break except in raise ``

对比Python 2

  • print是一个保留字,是一条语句,不是内置函数;
  • exec是一个保留字,是一条语句,不是内置函数;
  • nonlocal不是保留字,不可用;

表达式语句

两种情况下,表达式用作语句:

  1. 调用函数和method
  2. 交互模式提示符下打印值

常见Python表达式语句:

spam(x, y) 函数调用
spam.x(y) method调用
spam 交互模式打印
print(a, b, c, sep = '') Python 3打印
yield x ** 2 产生表达式语句

表达式语句和原处修改

队列表调用append()\sort()\reverse()可以直接在原处修改列表

打印操作

Python中,print语句可以实现打印,打印只是对程序员友好的标准输出流的接口而已。

从技术角度:打印是将一个或多个对象转成文本表达形式,然后发送给标准输出或另一个类似文件的流。

  • 文件对象方法

文件对象的写入:file.write(str)。打印操作类似,文件写入是将字符串写入到任意文件,print默认将对象打印到stdout流。不需将对象转成字符串。

  • 标准输出流

通常也叫stdout,只是发送一个程序的文本输出的默认地方。还有标准输入流和错误流。

打印printPython 2Python 3显著的区别:

  • Python 3中,打印是一个内置函数,有参数可以表示特定模式;
  • Python 2中,打印是语句,拥有自己的特定语法;

由于差异比较大,所以内容较多。

Python 3中的print函数

print内置函数通常在其自身的一行调用,从技术上讲,return None。参数提供特殊操作模式。

  • 调用格式

    print([object, ...][, sep=' '][, end='\n'][, file=sys.stdout])

    其中,[]内的项都是可选,并提供缺省值。意思是:用sep分割object的文本表示,后跟字符串end,都打印到流file中。

    • sep是在每个对象的文本之间插入的一个字符串,默认是空格;
    • end是打印文件行结束的一个字符串,默认是\n
    • file指定文本将要发送到的文件、标准流护着其他类似的文件对象,默认是sys.stdout

应用

尝试使用每一个参数。

1
2
3
4
5
6
7
8
9
10
11
print() // return None
n = 'wk'
a = 18
m = ['wk', 18]
print(n, a, m)
print(n, a, m, sep='')
print(n, a, m, sep=', ')
print(n, a, m, end='')
print(n, a, m, end='...\n')
print(n, a, m, sep='...', end='!\n')
print(n, a, m, end='!\n', sep='...')

file参数有些特殊:

1
2
print(n, a, m, end='!\n', sep='...', file=open('data.txt', 'w'))
// 将内容直接打印输出到文本文件data.txt

Python 2 print语句

print是语句,而不是内置函数。

Python print语句形式:

Python 2 Python 3 解释
print x, y print(x, y) 文本形式打印到sys.stdout,各项间加空格
print x, y, print(x, y, end='') 同上,行末不加\n
pirnt >> file, x, y print(x, y, file='') 文本内容写到file.write

应用

1
2
3
4
5
6
7
name = 'minikui'
age = 18
print name, age
print name, age,
pirnt name, age
print name + age
print '%s...%s' % (name, age)

打印流重定向

即是将打印输出到一个文本文件。

1
2
3
4
5
print ('hello world')
print 'hello world'
// 等价于
import sys
sys.stdout.write('hello world\n')

sys.stdout是Python print的技术基础:

1
2
3
print(X, Y)
import sys
sys.stdout.write(str(X) + ' ' + str(Y) + '\n')

所以,sys.stdout可以被赋值:

1
2
3
4
import sys
sys.stdout = open('log.txt', 'a')
...
print(X)

这样,以后的每一句print()都是将文本追加到log.txt文件。

Python 3中只需要指定file参数即可,只影响指定了file参数的调用。

tips

  • 在Python 2中导入

    from __future__ import print_function

    即可像Python 3一样使用。

  • Python 2打印时使用(),得到的是元组

    print ('', '')