《Python学习笔记本》第三章 表达式 笔记以及摘要(完结)

表达式(expression)由标识符、字面量和操作符组成。其完成运算、属性访问、以及函数调用等。表达式像数学公式那样,总是返回一个结果。

语句(statement)则由一到多行代码组成,其着重于逻辑过程,完成变量复制、类型定义,以及控制执行流方向等。说起来,表达式算是语句的一种,但语句不一定式表达式。

结单归纳:表达式完成计算,语句执行逻辑。

 

源文件

py2解释器都以ASCII为默认编码,如果源码里出现Unicode字符,就会导致其无法正常解析

所以要在头部加上专门的编码声明

# -*- coding: utf-8 -*-

 py3将默认编码位YTF8,免去了我们为每个原码文件添加头编码信息的麻烦。

shijianzhongdeMacBook-Pro:bin shijianzhong$ vim main.py
shijianzhongdeMacBook-Pro:bin shijianzhong$ python3 main.py 
你好
shijianzhongdeMacBook-Pro:bin shijianzhong$ mail.py
-bash: mail.py: command not found
shijianzhongdeMacBook-Pro:bin shijianzhong$ chmod a+x main.py 
shijianzhongdeMacBook-Pro:bin shijianzhong$ main.py 
你好
shijianzhongdeMacBook-Pro:bin shijianzhong$ main.py 
你好
shijianzhongdeMacBook-Pro:bin shijianzhong$ main.py 
你好
shijianzhongdeMacBook-Pro:bin shijianzhong$ cat main.py 
#! /usr/bin/env python3

print('你好')
shijianzhongdeMacBook-Pro:bin shijianzhong$ 

 

命令行

sys.flags(读取解释器的参数数量)、sys.argv(读取启动参数)

shijianzhongdeMacBook-Pro:bin shijianzhong$ python3 -O main.py 1 2 'hhello'
1
['main.py', '1', '2', 'hhello']
你好
shijianzhongdeMacBook-Pro:bin shijianzhong$ python3 -OO main.py 1 2 'hhello'
2
['main.py', '1', '2', 'hhello']
你好
shijianzhongdeMacBook-Pro:bin shijianzhong$ cat main.py 
#! /usr/bin/env python3

import sys
print(sys.flags.optimize)
print(sys.argv)
print('你好')
shijianzhongdeMacBook-Pro:bin shijianzhong$ 

 

对于简单的代码测试可以用python3 -c

shijianzhongdeMacBook-Pro:bin shijianzhong$ python3 -c 'import sys; print(sys.platform)'
darwin
shijianzhongdeMacBook-Pro:bin shijianzhong$ python3 -c 'import sys; print(sys.version_info)'
sys.version_info(major=3, minor=7, micro=4, releaselevel='final', serial=0)
shijianzhongdeMacBook-Pro:bin shijianzhong$ 

 

退出

常见的清零操作包括finally和atexit。前者是结构化异常字句,无论异常是否发生,它总被执行。

而atexit用于注册在进程退出前才执行的清理函数。

import atexit
import sys

atexit.register(print, 'atexit')

try:
  # 就算退出了,finally还是执行,atexit第二个执行 sys.exit() finally: print('finally')

 

代码

可阅读性和可测试性是代码的基本要求

builtins.end = None
print(end)


def sum(x):
    n = 0
    for i in x:
        n += 1
    end            # 块结束符
    return n

 在builtins模块中添加自己的属性,写在函数的最后面,这样的代码,别人看的会傻掉了。

 

语句

大多数代码规范在80字符,现在可以适当放宽到100字符

反斜杠续行符不能有空格和注释。

 

注释

通过#注释,分为块注释(block)和内联注释(inline)两类。块注释与代码块平级缩进,用于描述整块代码的逻辑意图和算法设计。内联注释在代码行尾部,补充说明其作用。

def test():
    
    # block comment
    # line 2
    # line 3
    print()
    
    x = 1          # inline comment

 

帮助

与被编译器忽略的注释不同,帮助属于基本元数据,可在运行期查寻和输出。除在交互环境手工查看外,还用于编辑智能提示,改善编码体验,或导出生成开发手册

建议使用''''''三引号

模块顶部为模块帮助,函数中为函数帮助,模块帮助不能放在shebang前面

帮助信息放在__doc__属性中,可直接输出,或通过help输出

In [4]: import test_demo                                                                                                                                          

In [5]: help(test_demo)                                                                                                                                           


In [6]: test_demo.__doc__                                                                                                                                         
Out[6]: '\n我是模块帮助\n\n'

In [7]: test_demo.run.__doc__                                                                                                                                     
Out[7]: '\n    我是函数帮助哈啊哈\n    :return:\n    '

In [8]: cat test_demo.py                                                                                                                                          
"""
我是模块帮助

"""


def run():
    '''
    我是函数帮助哈啊哈
    :return:
    '''
    ...
In [9]:   

 

shijianzhongdeMacBook-Pro:第三章 shijianzhong$ python -c 'import test_demo; print(test_demo.__doc__)'

abc

shijianzhongdeMacBook-Pro:第三章 shijianzhong$ python -OO -c 'import test_demo; print(test_demo.__doc__)'
None
shijianzhongdeMacBook-Pro:第三章 shijianzhong$ 

 当解释器以'OO'优化方式运行时,帮助信息被移除。

 

赋值

多名赋值

In [1]: a = b = c = '[]'                                                                                                                                          

In [2]: a is b is c                                                                                                                                               
Out[2]: True

In [3]:  

 用逗号赋值

In [4]: x = 1, 'abc' ,[123]                                                                                                                                       

In [5]: x                                                                                                                                                         
Out[5]: (1, 'abc', [123])

In [6]:  

 增量赋值

增量赋值视图直接修改原对象内容,实现累加效果。当谈,其前提是目标对象允许,否则会退化为普通赋值。

看一波执行码,虽然好像看不懂

In [13]: dis.dis(compile('a +=[1,2]', "","exec"))                                                                                                                 
  1           0 LOAD_NAME                0 (a)
              2 LOAD_CONST               0 (1)
              4 LOAD_CONST               1 (2)
              6 BUILD_LIST               2
              8 INPLACE_ADD
             10 STORE_NAME               0 (a)
             12 LOAD_CONST               2 (None)
             14 RETURN_VALUE

In [14]: dis.dis(compile('a +=(1,2)', "","exec"))                                                                                                                 
  1           0 LOAD_NAME                0 (a)
              2 LOAD_CONST               0 ((1, 2))
              4 INPLACE_ADD
              6 STORE_NAME               0 (a)
              8 LOAD_CONST               1 (None)
             10 RETURN_VALUE

In [15]:   

 

In [19]: '__iadd__' in dir((1,))                                                                                                                                  
Out[19]: False

In [20]: '__iadd__' in dir([1,])                                                                                                                                  
Out[20]: True

In [21]:   

 

序列解包

序列解包实际中,我还是用的比较多的。不多写,就写一条

多3个以内的(包含3个)的变量交换,编译器优化成ROT指令,直接交换栈帧数据,而不是构建元祖

In [21]: dis.dis(compile('a,b,c=c,b,a','','exec'))                                                                                                                
  1           0 LOAD_NAME                0 (c)
              2 LOAD_NAME                1 (b)
              4 LOAD_NAME                2 (a)
              6 ROT_THREE
              8 ROT_TWO
             10 STORE_NAME               2 (a)
             12 STORE_NAME               1 (b)
             14 STORE_NAME               0 (c)
             16 LOAD_CONST               0 (None)
             18 RETURN_VALUE

In [22]: dis.dis(compile('a,b,c,d=d,c,b,a','','exec'))                                                                                                            
  1           0 LOAD_NAME                0 (d)
              2 LOAD_NAME                1 (c)
              4 LOAD_NAME                2 (b)
              6 LOAD_NAME                3 (a)
              8 BUILD_TUPLE              4
             10 UNPACK_SEQUENCE          4
             12 STORE_NAME               3 (a)
             14 STORE_NAME               2 (b)
             16 STORE_NAME               1 (c)
             18 STORE_NAME               0 (d)
             20 LOAD_CONST               0 (None)
             22 RETURN_VALUE

In [23]:       

 

左右式可以以相同的方式嵌套

In [29]: a, ((b, c),(d, e)) = 1,[range(2),'ab']                                                                                                                   

In [30]: a,b,c,d,e                                                                                                                                                
Out[30]: (1, 0, 1, 'a', 'b')

In [31]:  

 

星号收集

In [31]: a,*b,c = range(5)                                                                                                                                        

In [32]: a,b,c                                                                                                                                                    
Out[32]: (0, [1, 2, 3], 4)

In [33]: a,*b,c = range(3)                                                                                                                                        

In [34]: a,b,c                                                                                                                                                    
Out[34]: (0, [1], 2)

In [35]: a,*b,c = range(2)                                                                                                                                        

In [36]: a,b,c                                                                                                                                                    
Out[36]: (0, [], 1)

In [37]:    

 收集不到的时候,返回空列表,这个还是蛮有意思的。

*号收集不能单独出现,要么与其他名字在一起,要么放入列表或元祖内

In [37]: [*a] = 1,2,3,4,5                                                                                                                                         

In [38]: a                                                                                                                                                        
Out[38]: [1, 2, 3, 4, 5]

In [39]: 

 序列解包和星号收集还用于空值表达式等场合

In [40]: for a, *b in ('abc',range(3)):print(a,b)                                                                                                                 
a ['b', 'c']
0 [1, 2]

In [41]:     

 

星号展开

星号还可用于展开可迭代(iterable)对象

简而言之,可迭代对象就是每次返回一个成员。所有序列类型,以及字典、集合、文件等都是可迭代类型。

In [41]: a = [1,2]                                                                                                                                                

In [42]: b = 'ab'                                                                                                                                                 

In [43]: c = range(5,9)                                                                                                                                           

In [44]: [*a,*b,*c]                                                                                                                                               
Out[44]: [1, 2, 'a', 'b', 5, 6, 7, 8]

In [45]:      

 对于字典,单星号展开主键,双星号展开键值

In [45]: d = {'a':1,'b':2}                                                                                                                                        

In [46]: (*d)                                                                                                                                                     
  File "<ipython-input-46-901b88e959e9>", line 4
SyntaxError: can't use starred expression here


In [47]: [*d]                                                                                                                                                     
Out[47]: ['a', 'b']

In [48]: {'c':1,**d}                                                                                                                                              
Out[48]: {'c': 1, 'a': 1, 'b': 2}

In [49]: {**d}                                                                                                                                                    
Out[49]: {'a': 1, 'b': 2}

In [50]:  

 可以用于给函数传递参数

In [50]: def test(a,b,c): 
    ...:     print(locals()) 
    ...:                                                                                                                                                          

In [51]: test(range(3))                                                                                                                                           
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-51-bb28b678f01f> in <module>
----> 1 test(range(3))

TypeError: test() missing 2 required positional arguments: 'b' and 'c'

In [52]: test(*range(3))                                                                                                                                          
{'a': 0, 'b': 1, 'c': 2}

In [53]: a = {'a':1,'b':2}                                                                                                                                        

In [54]: c = {'c':3}                                                                                                                                              

In [55]: test(**a,**c)                                                                                                                                            
{'a': 1, 'b': 2, 'c': 3}

In [56]:  

 

作用域

作为隐式规则,赋值操作默认总是针对当前名字空间。

同一作用域内,名字总属于单一名字空间,不会因执行顺序将其引用到不同名字空间。

In [59]: x = 10                                                                                                                                                   

In [60]: def test(): 
    ...:     print(x) 
    ...:     x += 10 
    ...:                                                                                                                                                          

In [61]: test()                                                                                                                                                   
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
<ipython-input-61-fbd55f77ab7c> in <module>
----> 1 test()

<ipython-input-60-d73a856c829b> in test()
      1 def test():
----> 2     print(x)
      3     x += 10
      4 

UnboundLocalError: local variable 'x' referenced before assignment

In [62]:     

 

In [62]: dis.dis(test)                                                                                                                                            
  2           0 LOAD_GLOBAL              0 (print)
              2 LOAD_FAST                0 (x)      # 本地
              4 CALL_FUNCTION            1
              6 POP_TOP

  3           8 LOAD_FAST                0 (x)       # 本地
             10 LOAD_CONST               1 (10)
             12 INPLACE_ADD
             14 STORE_FAST               0 (x)      # 本地
             16 LOAD_CONST               0 (None)
             18 RETURN_VALUE

In [63]:    

 

从反汇编结果看,函数test内的x统统从本地名字空间引用

 

global指向全局名字空间,nonlocal为外层嵌套(enclosing)函数

除非必要,否则应避免直接对外部变量赋值。可用返回值等方式,交由持有者处理.

示例代表比较简单不演示了。

看一下反编译的代码

In [63]: def test(): 
    ...:     global x 
    ...:     x = 10 
    ...:                                                                                                                                                          

In [64]: dis.dis(test)                                                                                                                                            
  3           0 LOAD_CONST               1 (10)
              2 STORE_GLOBAL             0 (x)         # 定义全局变量
              4 LOAD_CONST               0 (None)
              6 RETURN_VALUE

In [65]: x                                                                                                                                                        
Out[65]: 10

In [66]:   

 global还能给全局变量赋值。

nonlocal则自内向外依次检索嵌套函数,单不包括全局名字空间

如多层嵌套函数,存在同名变量,按就近原则处理。另nonlocal不能为外层嵌套函数新建变量。

In [66]: def outer(): 
    ...:     def inner(): 
    ...:         nonlocal x                                                                                                                                       
  File "<ipython-input-66-1c23c1da3645>", line 3
    nonlocal x
    ^
SyntaxError: no binding for nonlocal 'x' found

 

运算符

优先级用小括号就好了,是在记不住这么多

每个运算符有以特性的函数和方法实现,可以像普通对象作为传递

In [68]: from operator import mul                                                                                                                                 

In [69]: def my_mul(x,y,op): 
    ...:     return (op(x,y)) 
    ...:                                                                                                                                                          

In [70]: my_mul(1,2,mul)                                                                                                                                          
Out[70]: 2

In [71]: my_mul(4,2,mul)                                                                                                                                          
Out[71]: 8

In [72]:   

 标准库还提供了辅助函数,用简化定义类型运算符重新实现

使用functools.total_order装饰器,可基与__eq__,__lt__,自动补全摄于方法。

In [72]: import functools                                                                                                                                         

In [73]: @functools.total_ordering 
    ...: class X: 
    ...:     def __init__(self, n): 
    ...:         self.n = n 
    ...:     def __eq__(self, o): 
    ...:         return self.n == o.n 
    ...:     def __lt__(self, o): 
    ...:         return self.n < o.n 
    ...:                                                                                                                                                          

In [74]: a,b = X(1),X(2)                                                                                                                                          

In [75]: a<b                                                                                                                                                      
Out[75]: True

In [76]: a>b                                                                                                                                                      
Out[76]: False

In [77]: a>=b                                                                                                                                                     
Out[77]: False

 

链式比较

链式比较将多个比较表达式组合在一起,更符合人类的阅读习惯。该方式可有效缩短代码,并稍微提升性能。

In [78]: a,b=2,3                                                                                                                                                  

In [79]: a>0 and b>a and b<=5                                                                                                                                     
Out[79]: True

In [80]: 0<a<b<=5                                                                                                                                                 
Out[80]: True

In [81]:     

 反汇编不上了

 

切片

切片用于表达序列片段或整体。具体行为与其在语句中的位置有关,作为右值时复制序列数据,左值则表达操作范围。

In [81]: x = [1,[2],3]                                                                                                                                            

In [82]: y = x[1:]                                                                                                                                                

In [83]: y                                                                                                                                                        
Out[83]: [[2], 3]

In [84]: x[1].append(3)                                                                                                                                           

In [85]: y                                                                                                                                                        
Out[85]: [[2, 3], 3]

In [86]:   

 因列表存储的式元素指针,那么复制的自然也是指针,而非元素对象。切片所返回的新列表与原列表除共享部分元素对象外,其他毫无干系。

完整切片操作由3个参数构成

其以开始和结束索引构成一个半开半闭合,不含结束位置。

默认的起始位置为0;结束位置为len(x),以容纳最后一个元素。

索引0表示正向第一元素,反向缩影从-1开始

In [86]: x = list(range(100,107))                                                                                                                                 

In [87]: x                                                                                                                                                        
Out[87]: [100, 101, 102, 103, 104, 105, 106]

In [88]: x[2:5:1]                                                                                                                                                 
Out[88]: [102, 103, 104]

In [89]: x[::-1]                                                                                                                                                  
Out[89]: [106, 105, 104, 103, 102, 101, 100]

In [90]: x[-2:-5:-1]                                                                                                                                              
Out[90]: [105, 104, 103]

In [91]: x[5:2:-1]                                                                                                                                                
Out[91]: [105, 104, 103]

In [92]:    

 

删除

用切片指定要删除的序列范围

可切片删除,步进删除

In [101]: ll                                                                                                                                                      
Out[101]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [102]: del ll[3:7]                                                                                                                                             

In [103]: ll                                                                                                                                                      
Out[103]: [0, 1, 2, 7, 8, 9]

In [104]: ll = list(range(10))                                                                                                                                    

In [105]: ll                                                                                                                                                      
Out[105]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [106]: del ll[3:7:2]                                                                                                                                           

In [107]: ll                                                                                                                                                      
Out[107]: [0, 1, 2, 4, 6, 7, 8, 9]

In [108]:     

 赋值

以切片方式进行序列局部赋值,相当于先删除,后插入

In [110]: ll = list(range(10))                                                                                                                                    

In [111]: ll[3:7] = [100,200]                                                                                                                                     

In [112]: ll                                                                                                                                                      
Out[112]: [0, 1, 2, 100, 200, 7, 8, 9]

In [113]:   

 如设定步进,则删除和插入的元素数量必须相等

In [113]: ll = list(range(10))                                                                                                                                    

In [114]: ll                                                                                                                                                      
Out[114]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [115]: ll[::2]                                                                                                                                                 
Out[115]: [0, 2, 4, 6, 8]

In [116]: ll[::2] = [100,200,300,400,500]                                                                                                                         

In [117]: ll                                                                                                                                                      
Out[117]: [100, 1, 200, 3, 300, 5, 400, 7, 500, 9]

In [118]: ll[::2] = [100,200,300,400]                                                                                                                             
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-118-0435534aa2d3> in <module>
----> 1 ll[::2] = [100,200,300,400]

ValueError: attempt to assign sequence of size 4 to extended slice of size 5

In [119]:    

 

逻辑运算

逻辑运算用于判断多条件的布尔结构,或返回有效的操作数。

其中and返回最后,或导致短路的操作数;or返回第一真值,或最后的操作数数。

In [121]: 1 and {1:2}                                                                                                                                             
Out[121]: {1: 2}

In [122]: 3 and 0                                                                                                                                                 
Out[122]: 0

In [123]: 3 and 0 and 1                                                                                                                                           
Out[123]: 0

In [124]: 0 or 1 and 3                                                                                                                                            
Out[124]: 3

In [125]:  

 相同的逻辑运算符一旦短路,后续计算被终止

In [125]: def x(o): 
     ...:     print('op', o) 
     ...:     return o 
     ...:                                                                                                                                                         

In [126]: x(0) and x(1)                                                                                                                                           
op 0
Out[126]: 0

In [127]: x(0) or x(1)                                                                                                                                            
op 0
op 1
Out[127]: 1

In [128]: x(1) or x(2)                                                                                                                                            
op 1
Out[128]: 1

In [129]:  

 这个有意思,非常有意思。

反汇编代码来一波,假装看的懂

In [129]: dis.dis(compile('0 and 1 and 2 and 3','','eval'))                                                                                                       
  1           0 LOAD_CONST               0 (0)
              2 JUMP_IF_FALSE_OR_POP    14
              4 LOAD_CONST               1 (1)
              6 JUMP_IF_FALSE_OR_POP    14
              8 LOAD_CONST               2 (2)
             10 JUMP_IF_FALSE_OR_POP    14
             12 LOAD_CONST               3 (3)
        >>   14 RETURN_VALUE

In [130]: dis.dis(compile('5 or 1 or 2 or 3','','eval'))                                                                                                          
  1           0 LOAD_CONST               0 (5)
              2 JUMP_IF_TRUE_OR_POP     14
              4 LOAD_CONST               1 (1)
              6 JUMP_IF_TRUE_OR_POP     14
              8 LOAD_CONST               2 (2)
             10 JUMP_IF_TRUE_OR_POP     14
             12 LOAD_CONST               3 (3)
        >>   14 RETURN_VALUE

In [131]: dis.dis(compile('5 and 1 and 2 and 3','','eval'))                                                                                                       
  1           0 LOAD_CONST               0 (5)
              2 JUMP_IF_FALSE_OR_POP    14
              4 LOAD_CONST               1 (1)
              6 JUMP_IF_FALSE_OR_POP    14
              8 LOAD_CONST               2 (2)
             10 JUMP_IF_FALSE_OR_POP    14
             12 LOAD_CONST               3 (3)
        >>   14 RETURN_VALUE

In [132]:    

 不同的运算符须多次计算

In [133]: x(0) and x(1) or x(2)                                                                                                                                   
op 0
op 2
Out[133]: 2

In [134]: dis.dis(compile('0 and 1 and 2 or 3','','eval'))                                                                                                        
  1           0 LOAD_CONST               0 (0)
              2 POP_JUMP_IF_FALSE       12
              4 LOAD_CONST               1 (1)
              6 POP_JUMP_IF_FALSE       12
              8 LOAD_CONST               2 (2)
             10 JUMP_IF_TRUE_OR_POP     14
        >>   12 LOAD_CONST               3 (3)
        >>   14 RETURN_VALUE

In [135]:      

 条件表达式

常见逻辑愿运算是条件表达式,类似功能在其他语言被称为三元运算符

In [135]: 'T' if  2> 1 else 'f'                                                                                                                                   
Out[135]: 'T'

In [136]: 'T' if  2 <  1 else 'f'                                                                                                                                 
Out[136]: 'f'

In [137]: 2>1 and 'T' or 'F'                                                                                                                                      
Out[137]: 'T'

In [138]: 2<1 and 'T' or 'F'                                                                                                                                      
Out[138]: 'F'

In [139]:   

 下面暂时一种特殊情况

In [139]: [] if 2> 1 else ''                                                                                                                                      
Out[139]: []

In [140]: 2>1 and [] or ''                                                                                                                                        
Out[140]: ''

In [141]:    

 这种情况下,条件表达式没有任何问题。

运算符还常被用来简化默认值设置,这个很骚

In [147]: x = None                                                                                                                                                

In [148]: y = x or 100                                                                                                                                            

In [149]: y                                                                                                                                                       
Out[149]: 100

In [150]:                                                                                                                                                         

In [150]: x= None                                                                                                                                                 

In [151]: y = x and x*2 and 100                                                                                                                                   

In [152]: y                                                                                                                                                       

In [153]:    

 控制流

if elif else 多选择分支依次执行条件表达式,最终全部失败,或仅一条得以执行。

无论单个if有多少个分支,最多仅有一条得以执行。而多个if语句,则可能有多条,甚至全部被执行。两种的意义和执行方式完全不同,注意区别

 

应使用各种方式减少选择语句以及分支,减少缩进层次,避免流程控制里包含太多的细节。

将过长的分支代码重构为函数。相比于细节,有意义的函数名更友好

将复杂或过长的条件表达式重构为函数,更易阅读和维护

代码块阔度太长(比如需要翻屏),容易造成缩进错误

嵌套容易引发混乱,且层次太多可读性比较差,故应避免使用。

简单选择语句,用条件表达式或逻辑运算符替代。

 

死代码

In [153]: def test(x): 
     ...:     if x>0: 
     ...:         print('a') 
     ...:     elif x >5:     # 这个永远不会执行
     ...:         print('b') 
     ...:                                                                                                                                                         

In [154]: test(1)                                                                                                                                                 
a

In [155]: test(10)                                                                                                                                                
a

In [156]: test(3)                                                                                                                                                 
a

In [157]: dis.dis(test)                                                                                                                                           
  2           0 LOAD_FAST                0 (x)
              2 LOAD_CONST               1 (0)
              4 COMPARE_OP               4 (>)
              6 POP_JUMP_IF_FALSE       18

  3           8 LOAD_GLOBAL              0 (print)
             10 LOAD_CONST               2 ('a')
             12 CALL_FUNCTION            1
             14 POP_TOP
             16 JUMP_FORWARD            16 (to 34)

  4     >>   18 LOAD_FAST                0 (x)
             20 LOAD_CONST               3 (5)
             22 COMPARE_OP               4 (>)
             24 POP_JUMP_IF_FALSE       34

  5          26 LOAD_GLOBAL              0 (print)
             28 LOAD_CONST               4 ('b')
             30 CALL_FUNCTION            1
             32 POP_TOP
        >>   34 LOAD_CONST               0 (None)
             36 RETURN_VALUE

In [158]:    

 

循环

循环语句分为while、for两种,不存在替代关系。前者用于执行逻辑循环;而后者则偏于对象内容迭代。

 

可选分支

Python循环语句可自选else分支,在循环正常结束时执行。

正常结束是指循环没有被break、return中断。当然,循环体没被执行也属正常。

另外,执行continue是允许的,它不是中断。

In [166]: n = 3                                                                                                                                                   

In [167]: while n > 0: 
     ...:     n -= 1 
     ...: else: 
     ...:     print('over') 
     ...:                                                                                                                                                         
over

In [168]: n = 3                                                                                                                                                   

In [169]: while n > 0: 
     ...:     print('break') 
     ...:     break 
     ...: else: 
     ...:     print('over') 
     ...:      
     ...:                                                                                                                                                         
break

In [170]: n = 3                                                                                                                                                   

In [171]: while n > 4:            # 没有进入到while里面,算正常执行
     ...:     print('break') 
     ...:     break 
     ...: else: 
     ...:     print('over') 
     ...:                                                                                                                                                         
over

In [172]:   

 临时变量

循环语句没有单独的名字空间,其内部临时变量直接影响所在的上下文

In [172]: def test(): 
     ...:     while True: 
     ...:         x = 100 
     ...:         break 
     ...:     for i in range(20): 
     ...:         ... 
     ...:     print(locals()) 
     ...:     print(x,i) 
     ...:                                                                                                                                                         

In [173]: test()                                                                                                                                                  
{'x': 100, 'i': 19}
100 19

In [174]:  

 跳转

停止循环需要设定结束标志,然后在相应位置检查。

 

推导式

普通推导式用的比较多了,不写了

来一个嵌套的

In [175]: [f'{x}{y}' for x in 'abc' if x != 'c' for y in range(3) if y !=0]                                                                                       
Out[175]: ['a1', 'a2', 'b1', 'b2']

In [176]:  

 双层循环。

性能

除了语法因素外,推导式还有性能上的优势

临时变量

和普通循环语句不同,推导式临时变量不影响上下文名字空间

In [176]: def text(): 
     ...:     a = 'abc' 
     ...:     data = {a:b for a,b in zip('xyz',range(10,13))} 
     ...:     print(locals()) 
     ...:                                                                                                                                                         


In [179]: text()                                                                                                                                                  
{'a': 'abc', 'data': {'x': 10, 'y': 11, 'z': 12}}

In [180]:     

 因为推导式变量在编译器自动生成的函数内使用,而非test函数.

 

posted @ 2020-04-27 12:17  就是想学习  阅读(268)  评论(0编辑  收藏  举报