• 《Python数据科学手册》抄书笔记,第一章: Ipython 超越Python


    首先启动IPython shell 和Jupyter Notebook

    在命令行输入ipython启动IPython

    mac启动Jupyter使用Python3 -m IPython notebook

    在IPython中,符号?用于浏览文档,??用于浏览源代码,而Tab用于自动补全。

    每一个Python对象独有一个字符串的引用,该字符串即为docstring。大多数情况下,该字符串包含对象的简要介绍和使用方法。

    内置的help()函数可以获取这些信息。

    ?可以查看对象的相关信息

    In [5]: len?                                                                    
    Signature: len(obj, /)
    Docstring: Return the number of items in a container.
    Type:      builtin_function_or_method
    
    In [6]: l = []                                                                  
    
    In [7]: l?                                                                      
    Type:        list
    String form: []
    Length:      0
    Docstring:  
    Built-in mutable sequence.
    
    If no argument is given, the constructor creates a new empty list.
    The argument must be an iterable if specified.
    
    In [8]: l.index?                                                                
    Signature: l.index(value, start=0, stop=9223372036854775807, /)
    Docstring:
    Return first index of value.
    
    Raises ValueError if the value is not present.
    Type:      builtin_function_or_method
    
    In [9]:     
    

     无论是函数,方法还是具体实例对象。

    在自己编写函数的时候,写好相关docstring

    1.2.2通过符号??获取源代码。

    1.2.3用Tab补全的方式探索模块

    1.对象内容的Tab自动补全(相对简单)

    2.导入时的Tab自动补全

    3.超越Tab自动补全:通配符适配

    当想适配中间或者末尾的几个字符时,可以通过*符号来实现

    列举除名字空间中以Warning结尾的所有对象。

    In [11]: *Warning?                                                              
    BytesWarning
    DeprecationWarning
    FutureWarning
    ImportWarning
    PendingDeprecationWarning
    ResourceWarning
    RuntimeWarning
    SyntaxWarning
    UnicodeWarning
    UserWarning
    Warning
    

     不要忘记了后面有一个?

    寻找一个字符串方法,它的名字中有find

    In [12]: str.*find*?                                                            
    str.find
    str.rfind
    
    In [13]:     
    

    1.3IPython shell中的快捷键

    书中分为:导航快捷键、文本输入快捷键、命令历史快捷键和其他快捷键

    1.3.1 导航快捷键

    Crrl+a 光标移到本行开始处

    Ctrl+e 光标移动本行结尾处

    Ctrl+b(或左箭头键) 光标向后移动一个

    Ctrl+f(或右箭头键) 光标向前移动一个

    1.3.2 文本输入快捷键

    Backspace键   删除前一个字符

    Ctrl + d        删除后一个字符

    Ctrl + k     从光标开始剪切至行的末尾

    Ctrl + u     从行的开头剪切至光标

    Ctrl + y     yank(即粘贴)之前剪切的文本

    Ctrl + t     transpose(即交换)前两个字符

    1.3.3 命令历史快捷键

    Ctrl + p  (向上箭头)  获取前一个历史命令

    Ctrl + n  (向下箭头)  获取下一个历史命令

    Ctrl + r        对历史命令的反向搜索

    这是一个非常好用的功能,对话框中输入关键字会自动匹配相关信息。

    使用Ctrl + P与Ctrl + N 可以上下查看相关搜索记录。

    使用上下箭头可以查看匹配到的相关信息。

    1.3.4 其他快捷键

    Ctrl + l 清楚终端屏幕的内容

    Ctrl + c 中断当前的Python命令

    Ctrl + d  退出IPython会话

    1.4 IPython魔法命令

    1.4.1粘贴代码块: %paste和%cpaste

    当复制,粘贴的时候,出现了多于的符号,解释器报错

    可以用%paste与%cpaste来进行复制,粘贴

    1.4.2 执行外部代码: %run

    执行外部的模块文件

    In [2]: %run myscript.py                                                        
    1 squared is 1
    2 squared is 4
    3 squared is 9
    
    In [3]: square(55)                                                              
    Out[3]: 3025
    
    In [4]:      
    

     square函数定义在myscript.py模块中,这感觉也是一种比较好的加载模块内对象的方式。

    myscript.py文件内容:

    def square(x):
        """square a number"""
        return x ** 2
    
    for N in range(1, 4):
        print(N, "squared is", square(N))
    

    1.4.3 计算代码运行时间: %timeit

    In [4]: %timeit L = [n ** 2 for n in range(1000)]                               
    241 µs ± 4.27 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    
    In [5]:  
    

     这个命令会多次执行简短命令,以获取更加稳定的结果。

    多行的输入测试,可以使用两个%%来实现.

    %%timeit
       ...: L = []
       ...: for n in range(1000):
       ...:     L.append(n ** 2)
    
    ## -- End pasted text --
    
    278 µs ± 2.05 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    

    1.4.4 魔法函数的帮助:?、%magic、 %lsmagic

    获取文档注释

    %timeit?

    为了获得可用魔法函数的通用描述以及一些示例,可以输入一下命令

    %magic

    为了快速而简单地获取所有可用魔法函数的列表,可以输入以下命令:

    %lsmagic

    1.5 输入和输出历史

    前面已经讲过可以使用Ctrl+p或者Ctrl+n来翻看历史

    1.5.1IPython的输入和输出对象

    In [1]: import math                                                             
    
    In [2]: math.sin(2)                                                             
    Out[2]: 0.9092974268256817
    
    In [3]: math.cos(2)                                                             
    Out[3]: -0.4161468365471424
    
    In [4]: print(in)                                                               
      File "<ipython-input-4-7f51abe8dfc1>", line 1
        print(in)
               ^
    SyntaxError: invalid syntax
    
    
    In [5]: print(In)                                                               
    ['', 'import math', 'math.sin(2)', 'math.cos(2)', 'print(in)', 'print(In)']
    
    In [6]: print(Out)                                                              
    {2: 0.9092974268256817, 3: -0.4161468365471424}
    
    In [7]:       
    

     Ipython里面有一对In与Out的输入与输出。,在Ipython中会自动添加In和Out的Python变量,其中In为list实例,Out为Dict实例

    任何返回值是None的命令都不会加到Out变量中(所以print输出不会添加到Out中)。

    In [7]: print()                                                                 
    
    
    In [8]: print                                                                   
    Out[8]: <function print>
    
    In [9]: print(In)                                                               
    ['', 'import math', 'math.sin(2)', 'math.cos(2)', 'print(in)', 'print(In)', 'print(Out)', 'print()', 'print', 'print(In)']
    
    In [10]: print(Out)                                                             
    {2: 0.9092974268256817, 3: -0.4161468365471424, 8: <built-in function print>}
    
    In [11]: 
    

     这样,如果利用之前的结果可以方便的拿出来使用。

    1.5.2 下划线快捷和以前的输出

    如果想获取上一次的输出可以用_来表示,倒数第二个用__,以此类推

    通过_x,其中的x为Out输出中的key,开获取第几次的值

    In [27]: Out[2]                                                                 
    Out[27]: 0.9092974268256817
    
    In [28]: _2                                                                     
    Out[28]: 0.9092974268256817
    

    1.5.3 禁止输出

    就是在输入命令行中,在末尾添加;分号

    In [32]: math.sin(2) + math.cos(2);                                             
    
    In [33]: 32 in Out                                                              
    Out[33]: False
    
    In [34]:   
    

     在Out的输出字典中,根本没有key32的存在,说明没有输出。

    1.5.4 相关的魔法命令

    %history 来获取所有的历史命令输入。

    通过-n可以显示命令行的输入索引编号,通过n-m开业获取n到m号的输入命令情况。

    In [35]: %history 1-4                                                           
    import math
    math.sin(2)
    math.cos(2)
    print(in)
    
    In [36]: %history -n 1-4                                                        
       1: import math
       2: math.sin(2)
       3: math.cos(2)
       4: print(in)
    
    In [37]:        
    

    1.6 IPython和shell命令

    1.6.2 IPython中的shell命令

    只需要在命令之前+!感叹号

    In [45]: !pwd                                                                   
    /Users/shijianzhong
    
    In [46]: !echo "printing from the shell"                                        
    printing from the shell
    
    In [47]:  
    

    1.6.3 在shell中传入或传出值

    通过变量接收shell命令的输出值

     contents = !ls                                                         
    
    In [48]: print(contents)                                                        
    ['Applications', 'Compute-Question', 'Desktop', 'Documents', 'Downloads', 'Java_Home', 'Library', 'Movies', 'Music', 'Pictures', 'Postman', 'Public', 'PycharmProjects', 'Untitled Folder', '__pycache__', 'books', 'c_study', 'codeintel', 'django_venv', 'dump.rdb', 'eclipse-workspace', 'exec_new3.sh', 'flasky', 'group_git_tips', 'image', 'java_error_in_pycharm.hprof', 'java_error_in_pycharm_958.log', 'learn_crystal', 'learn_django', 'learn_git', 'learn_ruby', 'learn_shell', 'learngit', 'mbox', 'mprun_demo.py', 'my_home', 'my_software', 'mycentos.tar', 'myscript.py', 'nohup.out', 'pyalgo_two', 'pyalgotrade', 'ruby_study', 'scrapy_venv', 'show_p_path.py', 'ssh_test', 'study', 'tmp', 'work_space']
    
    In [49]: contents                                                               
    Out[49]: 
    ['Applications',
     'Compute-Question',
     'Desktop',
     'Documents',
     'Downloads',
     'Java_Home',
     'Library',
     'Movies',
     'Music',
     'Pictures',
     'Postman',
     'Public',
     'PycharmProjects',
     'Untitled Folder',
     '__pycache__',
     'books',
     'c_study',
     'codeintel',
     'django_venv',
     'dump.rdb',
     'eclipse-workspace',
     'exec_new3.sh',
     'flasky',
     'group_git_tips',
     'image',
     'java_error_in_pycharm.hprof',
     'java_error_in_pycharm_958.log',
     'learn_crystal',
     'learn_django',
     'learn_git',
     'learn_ruby',
     'learn_shell',
     'learngit',
     'mbox',
     'mprun_demo.py',
     'my_home',
     'my_software',
     'mycentos.tar',
     'myscript.py',
     'nohup.out',
     'pyalgo_two',
     'pyalgotrade',
     'ruby_study',
     'scrapy_venv',
     'show_p_path.py',
     'ssh_test',
     'study',
     'tmp',
     'work_space']
    
    In [50]: type(contents)                                                         
    Out[50]: IPython.utils.text.SList
    
    In [51]: message = "hello from the Python"                                      
    
    In [52]: !echo {message}                                                        
    hello from the Python
    

     变量接收的shell命令输出的对象是一个类似与列表的对象,Python中的变量名,也可以通过{}的形式传递给shell

    1.7与shell相关的魔法方法

    Notebook中的shell命令是在一个临时的分支shell中执行的。如果你希望以一种更持久的方式运行,可以使用%魔法命令

    通过%后面执行的命令,不能与Python进行交互

    一般的shell命令,会通过%automagic模范函数进行翻转。当automagic被打开,一些常用的命令直接省略%就可以跟shell中使用一样

    cd cat cp ls man mkdir more mv pwd rm rmdir

    In [76]: mkdir tmpe                                                             
    
    In [77]: cp myscript.py tmp                                                     
    
    In [78]: cp myscript.py tmpe/                                                   
    
    In [79]: ls tmpe                                                                
    myscript.py
    
    In [80]:                                                                        
    
    In [80]: rm -r tmpe                                                             
    
    In [81]: 
    

    1.8错误和调试

    1.8.1控制异常:%xmode

    当一个Python脚本未执行通过时,会抛出一个异常。当解释器捕获到这些异常中的一个时,可以在轨迹追溯(traceback)中找到引起这个错误的原因。

    利用%xmode魔法函数,IPython允许你在异常发生时控制打印信息的数量。

    In [1]: def func1(a, b): 
       ...:     return a / b 
       ...:  
       ...: def func2(x): 
       ...:     a = x 
       ...:     b = x - 1 
       ...:     return func1(a, b) 
       ...:                                                                         
    
    In [2]: func2(1)                                                                
    ---------------------------------------------------------------------------
    ZeroDivisionError                         Traceback (most recent call last)
    <ipython-input-2-7cb498ea7ed1> in <module>
    ----> 1 func2(1)
    
    <ipython-input-1-84841e495819> in func2(x)
          5     a = x
          6     b = x - 1
    ----> 7     return func1(a, b)
          8 
    
    <ipython-input-1-84841e495819> in func1(a, b)
          1 def func1(a, b):
    ----> 2     return a / b
          3 
          4 def func2(x):
          5     a = x
    
    ZeroDivisionError: division by zero
    
    In [3]: %xmode?                                                                 
    Docstring:
    Switch modes for the exception handlers.
    
    Valid modes: Plain, Context, Verbose, and Minimal.
    
    If called without arguments, acts as a toggle.
    File:      /Library/Python/3.7/site-packages/IPython/core/magics/basic.py
    

     xmode有4中选项,默认就时Context

    接下来显示Plain

    In [4]: %xmode Plain                                                            
    Exception reporting mode: Plain
    
    In [5]: func2(1)                                                                
    Traceback (most recent call last):
      File "<ipython-input-5-7cb498ea7ed1>", line 1, in <module>
        func2(1)
      File "<ipython-input-1-84841e495819>", line 7, in func2
        return func1(a, b)
      File "<ipython-input-1-84841e495819>", line 2, in func1
        return a / b
    ZeroDivisionError: division by zero
    

     接下来显示Verbose

    In [7]: func2(1)                                                                
    ---------------------------------------------------------------------------
    ZeroDivisionError                         Traceback (most recent call last)
    <ipython-input-7-7cb498ea7ed1> in <module>
    ----> 1 func2(1)
            global func2 = <function func2 at 0x101fb9e18>
    
    <ipython-input-1-84841e495819> in func2(x=1)
          5     a = x
          6     b = x - 1
    ----> 7     return func1(a, b)
            global func1 = <function func1 at 0x101fb9c80>
            a = 1
            b = 0
          8 
    
    <ipython-input-1-84841e495819> in func1(a=1, b=0)
          1 def func1(a, b):
    ----> 2     return a / b
            a = 1
            b = 0
          3 
          4 def func2(x):
          5     a = x
    
    ZeroDivisionError: division by zero
    
    In [8]:                                                                         
    

     最后时Minimal模式

    In [8]: %xmode Minimal                                                          
    Exception reporting mode: Minimal
    
    In [9]: func2(1)                                                                
    ZeroDivisionError: division by zero
    

     显然Verbose时显示最丰富的。

    1.8.2 调试:当阅读轨迹追溯不足以解决问题时

    IPython的调试器时Ipdb,Python的时pdb,我现在还不是很熟悉pdb。。。

    IPython中最方便的调试界面可能就时%debug魔法命令了。如果你在捕获异常后调用该调试器,它会在异常点自动打开一个交互式调试提示符。

    ipdb提示符让你可以探索栈空间当前状态,探索可用变量,设置运行Python命令

    In [10]: %debug                                                                 
    > <ipython-input-1-84841e495819>(2)func1()
          1 def func1(a, b):
    ----> 2     return a / b
          3 
          4 def func2(x):
          5     a = x
    
    ipdb> print(a)                                                                  
    1
    ipdb> print(b)                                                                  
    0
    ipdb>        
    

     这个交互式调试器的功能不止如此,我们甚至可以设置单步入栈和出栈来查看各变量的值

    In [11]: %debug                                                                 
    > <ipython-input-1-84841e495819>(2)func1()
          1 def func1(a, b):
    ----> 2     return a / b
          3 
          4 def func2(x):
          5     a = x
    
    ipdb> up                                                                        
    > <ipython-input-1-84841e495819>(7)func2()
          4 def func2(x):
          5     a = x
          6     b = x - 1
    ----> 7     return func1(a, b)
          8 
    
    ipdb> print(x)                                                                  
    1
    ipdb> up                                                                        
    > <ipython-input-9-7cb498ea7ed1>(1)<module>()
    ----> 1 func2(1)
    
    ipdb> down                                                                      
    > <ipython-input-1-84841e495819>(7)func2()
          4 def func2(x):
          5     a = x
          6     b = x - 1
    ----> 7     return func1(a, b)
          8 
    
    ipdb> down                                                                      
    > <ipython-input-1-84841e495819>(2)func1()
          1 def func1(a, b):
    ----> 2     return a / b
          3 
          4 def func2(x):
          5     a = x
    
    ipdb> print(x)                                                                  
    *** NameError: name 'x' is not defined
    ipdb> quit       
    

     ipdb 中的提示框后面的<ipython-input-1-84841e495819>(2)func1()

    这种, 表示运行的栈的区域,上面的就是表示运行在func1区域。

    如果你希望在任何异常时都自动启动调试器,可以用%pdb魔法函数来启动这个自启动过程

    In [15]: %pdb on                                                                
    Automatic pdb calling has been turned ON
    
    In [16]: func2(1)                                                               
    ZeroDivisionError: division by zero
    
    > <ipython-input-1-84841e495819>(2)func1()
          1 def func1(a, b):
    ----> 2     return a / b
          3 
          4 def func2(x):
          5     a = x
    
    ipdb> print(b)                                                                  
    0
    ipdb> q        
    

    部分调试命令

    list    显示文件的当前路径

    h(elp)   显示命令列表,或查找特定命令的帮助信息

    q(uit)   退出调试器和程序

    c(ontinue)    退出调试器,继续运行程序

    n(ext)     跳到程序的下一步

    <enter>  重复前一个命令

    p(rint)    打印变量

    s(tep)     步进子进程

    r(eturn)     从子进程跳出

    1.9 代码的分析和计时

    %time

    对单个语句的执行时间进行计时

    %timeit

    对单个语句的重复执行进行计时,以获取更高的精准度

    %prun

    利用分析器运行代码

    %lprun

    利用逐行分析器运行代码

    %memit

    测量单个语句的内存使用

    %mprun

    通过逐行的内存分析器运行代码

    • %time: Time the execution of a single statement
    • %timeit: Time repeated execution of a single statement for more accuracy
    • %prun: Run code with the profiler
    • %lprun: Run code with the line-by-line profiler
    • %memit: Measure the memory use of a single statement
    • %mprun: Run code with the line-by-line memory profiler

    1.9.1 代码段计时:%timeit和%time

    首先使用%timeit 使用很简单

    In [1]: %timeit sum(range(100))                                                 
    1.1 µs ± 27.4 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
    

     因为这个操作很快,所以%timeit自动让代码重复运行了很多次。对于慢的,会自动调整并减少重复执行的次数。

    In [2]: %%timeit 
       ...: total = 0 
       ...: for i in range(1000): 
       ...:     for j in range(1000): 
       ...:         total += i * (-1) ** j 
       ...:                                                                         
    303 ms ± 2.79 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
    

    有时候重复操作并不是一个最佳选择。例如,如果有一个列表需要排序,我们可能会被重复操作误导。对一个预先排好序的列表进行排序,比对一个无序的列表进行排序要快,所以重复运作将使结果出现偏差。

    In [16]: import random 
        ...: L = [random.random() for i in range(100000)] 
        ...: %timeit L.sort()                                                       
    410 µs ± 4.27 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    

     1000次循环,第一次排序了以后,后面的L就使一个有序的列表了。

    这样的情况下,可以使用%time来尝试

    In [16]: import random 
        ...: L = [random.random() for i in range(100000)] 
        ...: %timeit L.sort()                                                       
    410 µs ± 4.27 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    
    In [17]: %time L.sort()                                                         
    CPU times: user 896 µs, sys: 24 µs, total: 920 µs
    Wall time: 970 µs
    
    In [18]:  
    

     上面是对已经排序的列表再次进行排序,下面是全新的随机列表进行排序的时间

    In [18]: L = [random.random() for i in range(100000)]                           
    
    In [19]: %time L.sort()                                                         
    CPU times: user 14.7 ms, sys: 49 µs, total: 14.7 ms
    Wall time: 14.8 ms
    

    %time就执行一次,由于%timeit会进行一些优化,比如阻止清理未利用的Python对象(即垃圾回收),所有通常情况下%timeit会比%time得到的结果要快

    In [20]: %%time 
        ...: total = 0 
        ...: for i in range(1000): 
        ...:     for j in range(1000): 
        ...:         total += i * (-1) ** j 
        ...:                                                                        
    CPU times: user 354 ms, sys: 1.57 ms, total: 356 ms
    Wall time: 356 ms
    

    1.9.2分析整个脚本

    一个程序右很多的单个语句组成,有时候对整个脚本计时比单个语句计时更重要。IPython可以通过%prun这个魔法函数实现

    In [24]: def sum_of_lists(N): 
        ...:     total = 0 
        ...:     for i in range(5): 
        ...:         L = [j ^ (j >> i) for j in range(N)] 
        ...:         total += sum(L) 
        ...:     return total 
        ...:                                                                        
    
    In [25]: %prun sum_of_lists(1000000)                                            
             14 function calls in 0.530 seconds
    
       Ordered by: internal time
    
       ncalls  tottime  percall  cumtime  percall filename:lineno(function)
            5    0.452    0.090    0.452    0.090 <ipython-input-24-c8a2c5fe2cd3>:4(<listcomp>)
            5    0.041    0.008    0.041    0.008 {built-in method builtins.sum}
            1    0.028    0.028    0.521    0.521 <ipython-input-24-c8a2c5fe2cd3>:1(sum_of_lists)
            1    0.009    0.009    0.530    0.530 <string>:1(<module>)
            1    0.000    0.000    0.530    0.530 {built-in method builtins.exec}
            1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
    

    1.9.3 用%lprun进行逐行分析

    用%prun对代码中的每个函数分析非常有用,但有时候逐行代码分析报告更加方便。该功能需要通过安装第三方的包来实现。首相安装line_profier包

    pip install line_profiler
    

    接着用IPython导入line_profiler包提供的IPython扩展

    本来mac电脑装了老半天一直装不上去这个包,后面查寻后通过pip3 install Cython git+https://github.com/rkern/line_profiler.git --user进行了安装

    In [3]: %load_ext line_profiler
    
    In [5]: %lprun -f sum_of_lists sum_of_lists(5000)
    Timer unit: 1e-06 s
    
    Total time: 0.004989 s
    File: <ipython-input-2-c8a2c5fe2cd3>
    Function: sum_of_lists at line 1
    
    Line #      Hits         Time  Per Hit   % Time  Line Contents
    ==============================================================
         1                                           def sum_of_lists(N):
         2         1          3.0      3.0      0.1      total = 0
         3         6          6.0      1.0      0.1      for i in range(5):
         4         5       4820.0    964.0     96.6          L = [j ^ (j >> i) for j in range(N)]
         5         5        159.0     31.8      3.2          total += sum(L)
         6         1          1.0      1.0      0.0      return total
    

    1.9.4 用%memit和%mprun进行内存分析

    与前面line_profiler差不多,首先进行导包,后面进行魔法函数进行运行

    内存分析扩展包有两个有用的魔法函数:%memit魔法函数(它提供的内存消耗计算功能类似于%timeit)和%mprun魔法函数(它提供的内存消耗计算功能类似于%lprun)。

    %menit的使用很简单

    In [7]: %load_ext memory_profiler
    
    In [8]: def sum_of_lists(N):
       ...:     total = 0
       ...:     for i in range(5):
       ...:         L = [j ^ (j >> i) for j in range(N)]
       ...:         total += sum(L)
       ...:     return total
       ...: 
    
    In [9]: %memit sum_of_lists(1000000)
    peak memory: 152.33 MiB, increment: 79.62 MiB
    

     这个函数消耗了150m内存

    对于逐行代码内存消耗,可以用%mprun魔法函数。但很可惜,这个魔法函数仅仅对独立模块内部的函数有效,而对于Notebook本身不起作用。

    所以后面先生成一个文件

    In [14]: %%file mprun_demo.py
        ...: def sum_of_lists(N):
        ...:     total = 0
        ...:     for i in range(5):
        ...:         L = [j ^ (j >> i) for j in range(N)]
        ...:         total += sum(L)
        ...:         del L # remove reference to L
        ...:     return total
        ...: 
    Overwriting mprun_demo.py
    
    In [15]: from mprun_demo import sum_of_lists
    
    In [17]: %mprun -f sum_of_lists sum_of_lists(10000)
    Filename: /Users/shijianzhong/mprun_demo.py
    
    Line #    Mem usage    Increment   Line Contents
    ================================================
         1     91.4 MiB     91.4 MiB   def sum_of_lists(N):
         2     91.4 MiB      0.0 MiB       total = 0
         3     91.4 MiB      0.0 MiB       for i in range(5):
         4     91.4 MiB      0.0 MiB           L = [j ^ (j >> i) for j in range(N)]
         5     91.4 MiB      0.0 MiB           total += sum(L)
         6     91.4 MiB      0.0 MiB           del L # remove reference to L
         7     91.4 MiB      0.0 MiB       return total
    
  • 相关阅读:
    Java 日志
    编写用例文档
    uml用例关系
    地址线和数据线
    Android总结
    DbUtil数据库连接
    PropertiesUtil
    log4j.properties配置
    自定义博客样式
    css给文字加下划线
  • 原文地址:https://www.cnblogs.com/sidianok/p/13782556.html
Copyright © 2020-2023  润新知