From d2a3042d1cd5e75dab66b1390a05d71334269411 Mon Sep 17 00:00:00 2001 From: Hong <8720whyc@gmail.com> Date: Thu, 3 Aug 2017 14:53:08 +0800 Subject: [PATCH 1/2] new a package name is second ,and add a file 2-5seq_plus_multi.p this test the plus + and * of using --- .gitignore | 45 +++++++++++++++++++++++++++ second/2-5seq_plus_multi.py | 62 +++++++++++++++++++++++++++++++++++++ second/__init__.py | 26 ++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 second/2-5seq_plus_multi.py create mode 100644 second/__init__.py diff --git a/.gitignore b/.gitignore index 27757cf..b234f57 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # Created by .ignore support plugin (hsz.mobi) __pycache__/ +.idea/* *.py[cod] *$py.class *.so @@ -55,3 +56,47 @@ ENV/ .ropeproject /site .mypy_cache/ +### Python template +# Byte-compiled / optimized / DLL files + +# C extensions + +# Distribution / packaging + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. + +# Installer logs + +# Unit test / coverage reports + +# Translations + +# Django stuff: + +# Flask stuff: + +# Scrapy stuff: + +# Sphinx documentation + +# PyBuilder + +# Jupyter Notebook + +# pyenv + +# celery beat schedule file + +# SageMath parsed files + +# Environments + +# Spyder project settings + +# Rope project settings + +# mkdocs documentation + +# mypy diff --git a/second/2-5seq_plus_multi.py b/second/2-5seq_plus_multi.py new file mode 100644 index 0000000..7e51d3d --- /dev/null +++ b/second/2-5seq_plus_multi.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python2 +# encoding: utf-8 + +""" +@version: v1.0 +@author: whyc +@license: Apache Licence +@contact: 8720whyc@gmail.com +@site: +@software: PyCharm +@file: 2-5seq_plus_multi.py +@time: 17-8-3 下午1:08 +@description : + test t序列使用 + 和 * 的应用 +""" + + +def func(): + """ + + 和 * 都遵循这个规律, 不修改原有的操作对象, 而是构建一个全新的 + 序列。 + 如果在 a * n 这个语句中, 序列 a 里的元素是对其他可变 + 对象的引用的话, 你就需要格外注意了, 因为这个式子的结果可能 + 会出乎意料。 比如, 你想用 my_list = [[]] * 3 来初始化一个 + 由列表组成的列表, 但是你得到的列表里包含的 3 个元素其实是 3 + 个引用, 而且这 3 个引用指向的都是同一个列表。 这可能不是你想 + 要的效果 + :return: + """ + li = [1, 2, 3] + print("5*'abc': ",5*'abc') + print("test * 符号的引用 li * 5: li =[1,2,3] ", li * 5) + + #3X3 的列表推导 ,其中应用了 * 来表达 + board =[['_']*3 for i in range(3)] #➊ + print("board: ",board) + board[2][1]="wwwwwd" # ➋ + print("赋值给 board[2][1]:%s"%board) + + """ + ➊ 建立一个包含 3 个列表的列表, 被包含的 3 个列表各自有 3 个元 + 素。 打印出这个嵌套列表。 + ➋ 把第 1 行第 2 列的元素标记为 X, 再打印出这个列表。 + 示例 2-13 展示了另一个方法, 这个方法看上去是个诱人的捷径, 但实 + 际上它是错的。 + """ + # 不使用列表推导式 + weird_board=[['_']*3]*3 + print("wired_board: ",weird_board) + # 赋值一个元素值 + weird_board[1][1]='00o' + print("赋值后的序列:",weird_board) + + +class Main(): + def __init__(self): + pass + func() + + +if __name__ == "__main__": + Main() \ No newline at end of file diff --git a/second/__init__.py b/second/__init__.py new file mode 100644 index 0000000..a8efc9b --- /dev/null +++ b/second/__init__.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python2 +# encoding: utf-8 + +""" +@version: v1.0 +@author: whyc +@license: Apache Licence +@contact: 8720whyc@gmail.com +@site: +@software: PyCharm +@file: __init__.py.py +@time: 17-8-3 下午1:07 +""" + + +def func(): + pass + + +class Main(): + def __init__(self): + pass + + +if __name__ == "__main__": + pass \ No newline at end of file -- Gitee From d23559cf6d6e4cc3383aa4ab86cb47c6822622ee Mon Sep 17 00:00:00 2001 From: Hong <8720whyc@gmail.com> Date: Thu, 3 Aug 2017 23:40:41 +0800 Subject: [PATCH 2/2] new 3 files and modify 2-5seq_plus_multi.py file 2-6idd 2-7list_sort_sorted.py 2-8-bisect-manger.py --- second/2-5seq_plus_multi.py | 132 ++++++++++++++++++++++++++++++++-- second/2-6idd.py | 126 ++++++++++++++++++++++++++++++++ second/2-7list_sort_sorted.py | 92 ++++++++++++++++++++++++ second/2-8-bisect-manger.py | 74 +++++++++++++++++++ 4 files changed, 418 insertions(+), 6 deletions(-) create mode 100644 second/2-6idd.py create mode 100644 second/2-7list_sort_sorted.py create mode 100644 second/2-8-bisect-manger.py diff --git a/second/2-5seq_plus_multi.py b/second/2-5seq_plus_multi.py index 7e51d3d..d2d80fe 100644 --- a/second/2-5seq_plus_multi.py +++ b/second/2-5seq_plus_multi.py @@ -15,7 +15,7 @@ """ -def func(): +def func25(): """ + 和 * 都遵循这个规律, 不修改原有的操作对象, 而是构建一个全新的 序列。 @@ -30,7 +30,7 @@ def func(): li = [1, 2, 3] print("5*'abc': ",5*'abc') print("test * 符号的引用 li * 5: li =[1,2,3] ", li * 5) - + ## 实例 2-12 #3X3 的列表推导 ,其中应用了 * 来表达 board =[['_']*3 for i in range(3)] #➊ print("board: ",board) @@ -44,19 +44,139 @@ def func(): 示例 2-13 展示了另一个方法, 这个方法看上去是个诱人的捷径, 但实 际上它是错的。 """ - # 不使用列表推导式 - weird_board=[['_']*3]*3 + ##实例 2-13 + #--------------------------------------- + # 不使用列表推导式 直接使用 * 乘积来计算 + weird_board=[['_']*3]*3 #➊ print("wired_board: ",weird_board) # 赋值一个元素值 - weird_board[1][1]='00o' + weird_board[1][1]='00o' #➋ print("赋值后的序列:",weird_board) + """ + ➊ 外面的列表其实包含 3 个指向同一个列表的引用。 当我们不做修改 + 的时候, 看起来都还好。 + ➋ 一旦我们试图标记第 1 行第 2 列的元素, 就立马暴露了列表内的 3 + 个引用指向同一个对象的事实。 + """ + ######################################## + #--------------------------------------- + #实例 2-12,和2-13 的相同 执行方式: + #实例 2-12.1 ,与 2-12 相同 结果 + board1 = [] + for i in range(3): + row = ['_'] * 3 #➊ #相当与每次循环都重新创建了一个数组对象 + board1.append(row) # + print("----------------------------") + print(board1) + board1[1][1] = "new" + print(board1) # ➋ + """ + ➊ 每次迭代中都新建了一个列表, 作为新的一行( row) 追加到游戏板 + ( board) 。 + ➋ 正如我们所期待的, 只有第 2 行的元素被修改。 + 如果你觉得这一节里所说的问题及其对应的解决方法都有点 + 云里雾里, 没关系。 第 8 章里我们会详细说明引用和可变对象背后 + 的原理和陷阱。 + 我们一直在说 + 和 *, 但是别忘了我们还有 += 和 *=。 随着目标序列的 + 可变性的变化, 这个两个运算符的结果也大相径庭。 + + """ + + #实例2-13.1 与实例 + #相反, 示例 2-13 中的方法等同于这样做: + row=['_']*3 + board2 = [] + for i in range(3): + board2.append(row) #➊ #在这里式每次引用的都式同一个对象, + print(board2) + board2[1][1] = "new two" + print(board2) # + """ + ➊ 追加同一个行对象( row) 3 次到游戏板( board) 。 + """ + +""" +2.6 序列的增量赋值 + +""" +def func26(): + """ + 增量赋值运算符 += 和 *= 的表现取决于它们的第一个操作对象。 简单起 + 见, 我们把讨论集中在增量加法( +=) 上, 但是这些概念对 *= 和其他 + 增量运算符来说都是一样的。 + += 背后的特殊方法是 __iadd__ ( 用于“就地加法”) 。 但是如果一个类 + 没有实现这个方法的话, Python 会退一步调用 __add__ 。 + a += b + -------------------------------------------------- + 如果 a 实现了 __iadd__ 方法, 就会调用这个方法。 同时对可变序列 + ( 例如 list、 bytearray 和 array.array) 来说, a 会就地改动, 就 + 像调用了 a.extend(b) 一样。 但是如果 a 没有实现 __iadd__ 的话, a + += b 这个表达式的效果就变得跟 a = a + b 一样了: 首先计算 a + + b, 得到一个新的对象, 然后赋值给 a。 也就是说, 在这个表达式中, + 变量名会不会被关联到新的对象, 完全取决于这个类型有没有实现 + __iadd__ 这个方法。 + 总体来讲, 可变序列一般都实现了 __iadd__ 方法, 因此 += 是就地加 + 法。 而不可变序列根本就不支持这个操作, 对这个方法的实现也就无从 + 谈起。 + :return: NOTHING + """ + li = [1,2,3] + print("id(li): ",id(li)) #❶ + li *= 2 + print("li*=2 : ",li) # + print("id(li) 通过乘法之后的ID:",id(li)) #❷ + #元组不可变 + t = (1,2,3) + print("id(t): ", id(t))# ❸ + t *= 2 + print("id(t): t 元组通过增量乘法之后的id值: ", id(t))#❹ + + """ + ❶ 刚开始时列表的 ID。 + ❷ 运用增量乘法后, 列表的 ID 没变, 新元素追加到列表上。 + ❸ 元组最开始的 ID。 + ❹ 运用增量乘法后, 新的元组被创建。 + 对不可变序列进行重复拼接操作的话, 效率会很低, 因为每次都有一个 + 新对象, 而解释器需要把原来对象中的元素先复制到新的对象里, 然后 + 再追加新的元素 + str 是一个例外, 因为对字符串做 += 实在是太普遍了, 所以 CPython 对它做了优化。 为 str + 初始化内存的时候, 程序会为它留出额外的可扩展空间, 因此进行增量操作的时候, 并不会涉 + 及复制原有字符串到新位置这类操作 + """ + class Main(): def __init__(self): pass - func() + #func25() + func26() + +""" +THIS IS THE PRINT RESULTS FOR THIS TEST FILE: +#-------------------------------------------------- +func25() 的输出结果 +5*'abc': abcabcabcabcabc +test * 符号的引用 li * 5: li =[1,2,3] [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3] +board: [['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']] +赋值给 board[2][1]:[['_', '_', '_'], ['_', '_', '_'], ['_', 'wwwwwd', '_']] +wired_board: [['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']] +赋值后的序列: [['_', '00o', '_'], ['_', '00o', '_'], ['_', '00o', '_']] +---------------------------- +[['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']] +[['_', '_', '_'], ['_', 'new', '_'], ['_', '_', '_']] +[['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']] +[['_', 'new two', '_'], ['_', 'new two', '_'], ['_', 'new two', '_']] +#---------------------------------------------------- +func26() 的输出结果 +id(li): 139857721897416 +li*=2 : [1, 2, 3, 1, 2, 3] +id(li) 通过乘法之后的ID: 139857721897416 +id(t): 139857721905512 +id(t): t 元组通过增量乘法之后的id值: 139857747237672 + +""" if __name__ == "__main__": Main() \ No newline at end of file diff --git a/second/2-6idd.py b/second/2-6idd.py new file mode 100644 index 0000000..6c97dae --- /dev/null +++ b/second/2-6idd.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python2 +# encoding: utf-8 +""" +------------------------------------------------- + @version : v1.0 + @File Name : 2-6idd + @Author : whyc + @date : 17-8-3 + @license : Apache Licence + @contact : 8720whyc@gmail.com + @site : + @software : PyCharm + @file : 2-6idd.py +------------------------------------------------- + Change Activity : + @time : 17-8-3 下午3:53 17-8-3: +------------------------------------------------- + @Description : + + +------------------------------------------------- + +""" +__author__ = 'whyc' + +# ------------------------------------------------ +""" + 我们已经认识了 += 的一般用法, 下面来看一个有意思的边界情况。 这 + 个例子可以说是突出展示了“不可变性”对于元组来说到底意味着什么。 + 一个关于+=的谜题 + 读完下面的代码, 然后回答这个问题: 示例 2-14 中的两个表达式到底 + 会产生什么结果? 回答之前不要用控制台去运行这两个式子。 +""" + +def func(): + """ + 实例 2-15 关于 += 的一个谜题 + + :return: + """ + t = (1,2,3,[30,40]) + try: + t[3] += [50, 60] + except Exception as e: + print(e) + print(t) + #使用 t[3].extent([90,10o]) + t[3].extend([90,100]) + print(t) + + # 书中的结果 + """ + a. t 变成 (1, 2, [30, 40, 50, 60])。 + b. 因为 tuple 不支持对它的元素赋值, 所以会抛出 TypeError 异常。 + c. 以上两个都不是。 + d. a 和 b 都是对的。 + 我刚看到这个问题的时候, 异常确定地选择了 b, 但其实答案是 d, 也 + 就是说 a 和 b 都是对的! 示例 2-15 是运行这段代码得到的结果, 用的 + Python 版本是 3.4, 但是在 2.7 中结果也一样。 + 示例 2-15 没人料到的结果: t[2] 被改动了, 但是也有异常抛出 + >>> t = (1, 2, [30, 40]) + >>> t[2] += [50, 60] + Traceback (most recent call last): + File "", line 1, in + TypeError: 'tuple' object does not support item assignment + >>> t + (1, 2, [30, 40, 50, 60]) + """ + # 本实例测试结果 符合A,b 选项, + """ + t = (1, 2, 3, [30, 40]) + t[3] += [50, 60] + Traceback (most recent call last): + File "/home/whyc/softwares/anaconda3/lib/python3.6/site-packages/IPython/core/interactiveshell.py", line 2881, in run_code + exec(code_obj, self.user_global_ns, self.user_ns) + File "", line 2, in + t[3] += [50, 60] + TypeError: 'tuple' object does not support item assignment + t + Out[5]: (1, 2, 3, [30, 40, 50, 60]) + + """ + + # 查看Python执行的字节码 + import dis + print(dis.dis("s[a]+=b")) + + """ + 生成的字节码 + + 1 0 LOAD_NAME 0 (s) + 2 LOAD_NAME 1 (a) + 4 DUP_TOP_TWO + 6 BINARY_SUBSCR #➊ + 8 LOAD_NAME 2 (b) + 10 INPLACE_ADD #➋ + 12 ROT_THREE + 14 STORE_SUBSCR #➌ + 16 LOAD_CONST 0 (None) + 18 RETURN_VALUE +None + + ➊ 将 s[a] 的值存入 TOS( Top Of Stack, 栈的顶端) 。 + ➋ 计算 TOS += b。 这一步能够完成, 是因为 TOS 指向的是一个可变对 + 象( 也就是示例 2-15 里的列表) 。 + ➌ s[a] = TOS 赋值。 这一步失败, 是因为 s 是不可变的元组( 示例 2-15 + + 至此我得到了 3 个教训。 + 不要把可变对象放在元组里面。 + 增量赋值不是一个原子操作。 我们刚才也看到了, 它虽然抛出了异 + 常, 但还是完成了操作。 + 查看 Python 的字节码并不难, 而且它对我们了解代码背后的运行机 + 制很有帮助 + """ + +#把要运行的发放放在这里面 式逻辑运行 +def run(): + func() + +class Main(): + def __init__(self): + pass + + +if __name__ == "__main__": + run() \ No newline at end of file diff --git a/second/2-7list_sort_sorted.py b/second/2-7list_sort_sorted.py new file mode 100644 index 0000000..1956142 --- /dev/null +++ b/second/2-7list_sort_sorted.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python2 +# encoding: utf-8 +""" +------------------------------------------------- + @version : v1.0 + @File Name : 2-7list_sort_sorted.py + @Author : whyc + @date : 17-8-3 下午9:07 + @license : + @contact : 8720whyc@gmail.com + @site : https://github.com/WhyCWen + @software : PyCharm + @file : 2-7list_sort_sorted.py +------------------------------------------------- + @Description : + list.sort 方法会就地排序列表, 也就是说不会把原列表复制一份。 这 + 也是这个方法的返回值是 None 的原因, 提醒你本方法不会新建一个列 + 表。 在这种情况下返回 None 其实是 Python 的一个惯例: 如果一个函数 + 或者方法对对象进行的是就地改动, 那它就应该返回 None, 好让调用 + 者知道传入的参数发生了变动, 而且并未产生新的对象。 例 + 如, random.shuffle 函数也遵守了这个惯例。 + + 与 list.sort 相反的是内置函数 sorted, 它会新建一个列表作为返回 + 值。 这个方法可以接受任何形式的可迭代对象作为参数, 甚至包括不可 + 变序列或生成器( 见第 14 章) 。 而不管 sorted 接受的是怎样的参 + 数, 它最后都会返回一个列表。 + + 不管是 list.sort 方法还是 sorted 函数, 都有两个可选的关键字参 + 数。 + reverse + 如果被设定为 True, 被排序的序列里的元素会以降序输出( 也就 + 是说把最大值当作最小值来排序) 。 这个参数的默认值是 False。 + key + 一个只有一个参数的函数, 这个函数会被用在序列里的每一个元素 + 上, 所产生的结果将是排序算法依赖的对比关键字。 比如说, 在对一些 + 字符串排序时, 可以用 key=str.lower 来实现忽略大小写的排序, 或 + 者是用 key=len 进行基于字符串长度的排序。 这个参数的默认值是恒 + 等函数( identity function) , 也就是默认用元素自己的值来排序。 +------------------------------------------------- + Modifictions : Change Activity @Times + @Description : 17-8-3 下午9:07 + : +------------------------------------------------- + +""" +__author__ = 'whyc' + + +def func(): + fruits = ['grape', 'raspberry', 'apple', 'banana'] #❶ + print("fruits sored: ",sorted(fruits)) # ❷ + print("reverse sorted:" ,sorted(fruits,reverse=True)) # ❸ + print("ken=len sorted: ",sorted(fruits,key=len)) #❹ + print("ken=len ,reverse = True sorted: ",sorted(fruits,key=len,reverse=True)) #❺ + #---------------------------------- + #使用 sort 排序 + print(fruits) # ❻ + + fs = fruits.sort() + print("sort return None:",fs) #❼ + print("sort : ",fruits) #❽ + """ + ❶ 新建了一个按照字母排序的字符串列表。 + ❷ 原列表并没有变化。 + ❸ 按照字母降序排序。 + ❹ 新建一个按照长度排序的字符串列表。 因为这个排序算法是稳定 + 的, grape 和 apple 的长度都是 5, 它们的相对位置跟在原来的列表里是 + 一样的。 + ❺ 按照长度降序排序的结果。 结果并不是上面那个结果的完全翻转, + 7 + 7 + 因为用到的排序算法是稳定的, 也就是说在长度一样时, grape 和 apple + 的相对位置不会改变。 + ❻ 直到这一步, 原列表 fruits 都没有任何变化。 + ❼ 对原列表就地排序, 返回值 None 会被控制台忽略。 + ❽ 此时 fruits 本身被排序。 + 已排序的序列可以用来进行快速搜索, 而标准库的 bisect 模块给我们 + 提供了二分查找算法。 下一节会详细讲这个函数, 顺便还会看看 + bisect.insort 如何让已排序的序列保持有序。 + """ +#把要运行的发放放在这里面 式逻辑运行 +def run(): + func() + + +class Main(): + def __init__(self): + pass + + +if __name__ == "__main__": + run() \ No newline at end of file diff --git a/second/2-8-bisect-manger.py b/second/2-8-bisect-manger.py new file mode 100644 index 0000000..2cc3a0d --- /dev/null +++ b/second/2-8-bisect-manger.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python2 +# encoding: utf-8 +""" +------------------------------------------------- + @version : v1.0 + @File Name : 2-8-bisect-manger.py + @Author : whyc + @date : 17-8-3 下午10:24 + @license : + @contact : 8720whyc@gmail.com + @site : https://github.com/WhyCWen + @software : PyCharm + @file : 2-8-bisect-manger.py +------------------------------------------------- + @Description : + bisect 模块包含两个主要函数, bisect 和 insort, 两个函数都利用 + 二分查找算法来在有序序列中查找或插入元素。 + bisect(haystack, needle) 在 haystack( 干草垛) 里搜索 + needle( 针) 的位置, 该位置满足的条件是, 把 needle 插入这个位置 + 之后, haystack 还能保持升序。 也就是在说这个函数返回的位置前面 + 的值, 都小于或等于 needle 的值。 其中 haystack 必须是一个有序的 + 序列。 你可以先用 bisect(haystack, needle) 查找位置 index, 再 + 用 haystack.insert(index, needle) 来插入新值。 但你也可用 + insort 来一步到位, 并且后者的速度更快一些。 +------------------------------------------------- + Modifictions : Change Activity @Times + @Description : 17-8-3 下午10:24 + : + : +------------------------------------------------- + +""" +__author__ = 'whyc' + +import bisect +import sys + +HAYSTACK = [1, 2, 3, 9, 6, 8, 2, 9, 10, 6, 8, 10, 25, 13, 24] +NEEDLES = [0, 1, 2, 5, 8, 10, 13, 24,25] +ROW_FMT = '{0:2d} @ {1:4} {2}{0:<2d}' + +def demo(bisect_fn): + for needle in reversed(NEEDLES): + position = bisect_fn(HAYSTACK,needle) #➊ + offset = position * ' |' #➋ + print(ROW_FMT.format(needle,position,offset)) #➌ +def func(): + if sys.argv[-1] == 'left':#➍ + bisect_fn = bisect.bisect_left + else: + bisect_fn = bisect.bisect + print('DEMO:', bisect_fn.__name__) #➎ + print('haystack ->', ' '.join('%2d' % n for n in HAYSTACK)) + demo(bisect_fn) + +""" + ❶ 用特定的 bisect 函数来计算元素应该出现的位置。 + ❷利用该位置来算出需要几个分隔符号。 + ❸ 把元素和其应该出现的位置打印出来。 + ❹ 根据命令上最后一个参数来选用 bisect 函数。 + ❺ 把选定的函数在抬头打印出来。 +""" +#把要运行的发放放在这里面 式逻辑运行 +def run(): + func() + + +class Main(): + def __init__(self): + pass + + +if __name__ == "__main__": + run() \ No newline at end of file -- Gitee