• 《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]: '
    我是模块帮助
    
    '
    
    In [7]: test_demo.run.__doc__                                                                                                                                     
    Out[7]: '
        我是函数帮助哈啊哈
        :return:
        '
    
    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函数.

  • 相关阅读:
    <img>标签
    <a>标签
    HTML标签类型
    HTML实体
    HTML颜色的三种写法
    HTML绝对路径和相对路径
    HTML基本结构及标签样式
    Java Activiti 工作流引擎 springmvc SSM 流程审批 后台框架源码
    java ssm 后台框架平台 项目源码 websocket IM quartz springmvc
    分批插入数据基于mybatis
  • 原文地址:https://www.cnblogs.com/sidianok/p/12785855.html
Copyright © 2020-2023  润新知