
最近,左右脑测试在朋友圈非常火爆,你只需要进入相应入口并回答几个设定的问题后,就会出现你左右脑两个年龄测试结果,到底这个测试靠谱吗? 对于测试结果的真实性,有程序员出面表示,其在认真研究这个测试的代码后发现,测出来的年龄其实只是随机数。 北京大学心理学教授沈政向北京青年报表示,人体大脑不存在左右分工的问题,从事比较复杂一点、高级一点的心理活动时,都是左右脑协同操作。 此外,沈政还强调,测试中的题目测试的重点是大脑的知觉和推理能力,但是不能够完全作为大脑测试题。 原文发布时间为:2017-10-26 本文作者:佚名 本文来自云栖社区合作伙伴“51CTO”,了解相关信息可以关注。
我最近在涉及大量数据处理的项目中频繁使用 sqlite3。我最初的尝试根本不涉及任何数据库,所有的数据都将保存在内存中,包括字典查找、迭代和条件等查询。这很好,但可以放入内存的只有那么多,并且将数据从磁盘重新生成或加载到内存是一个繁琐又耗时的过程。 我决定试一试sqlite3。 因为只需打开与数据库的连接, 这样可以增加可处理的数据量,并将应用程序的加载时间减少到零。此外,我可以通过 SQL 查询替换很多Python逻辑语句。 我想分享一些关于这次经历的心得和发现。 TL;DR 使用大量操作 (又名 executemany)。 你不需要使用光标 (大部分时间)。 光标可被迭代。 使用上下文管理器。 使用编译指示 (当它有意义)。 推迟索引创建。 使用占位符来插入 python 值。 1. 使用大量操作 如果你需要在数据库中一次性插入很多行,那么你真不应该使用 execute。sqlite3 模块提供了批量插入的方式:executemany。 而不是像这样做: for row in iter_data(): connection.execute('INSERT INTO my_table VALUES (?)', row) 你可以利用这个事实,即 executemany 接受元组的生成器作为参数: connection.executemany( 'INSERT INTO my_table VALUE (?)', iter_data() ) 这不仅更简洁,而且更高效。实际上,sqlite3 在幕后利用 executemany 实现 execute,但后者插入一行而不是多行。 我写了一个小的基准测试,将一百万行插入空表(数据库在内存中): executemany: 1.6 秒 execute: 2.7 秒 2. 你不需要游标 一开始我经常搞混的事情就是,光标管理。在线示例和文档中通常如下: connection = sqlite3.connect(':memory:') cursor = connection.cursor() # Do something with cursor 但大多数情况下,你根本不需要光标,你可以直接使用连接对象。 像 execute executemany 类似的操作可以直接在连接上调用。以下是一个证明此事的示例: import sqlite3 connection = sqlite3(':memory:') # Create a table connection.execute('CREATE TABLE events(ts, msg)') # Insert values connection.executemany( 'INSERT INTO events VALUES (?,?)', [ (1, 'foo'), (2, 'bar'), (3, 'baz') ] ) # Print inserted rows for row in connnection.execute('SELECT * FROM events'): print(row) 3. 光标(Cursor)可被用于迭代 你可能经常会看到使用fetchone或fetchall来处理 SELECT 查询结果的示例。但是我发现处理这些结果的最自然的方式是直接在光标上迭代: for row in connection.execute('SELECT * FROM events'): print(row) 这样一来,只要你得到足够的结果,你就可以终止查询,并且不会引起资源浪费。当然,如果事先知道你需要多少结果,可以改用 LIMIT SQL语句,但Python生成器是非常方便的,可以让你将数据生成与数据消耗分离。 4. 使用Context Managers(上下文管理器) 即使在处理SQL事务的中间,也会发生讨厌的事情。为了避免手动处理回滚或提交,你可以简单地使用连接对象作为上下文管理器。 在以下示例中,我们创建了一个表,并错误地插入了重复的值: import sqlite3 connection = sqlite3.connect(':memory:') with connection: connection.execute( 'CREATE TABLE events(ts, msg, PRIMARY KEY(ts, msg))') try: with connection: connection.executemany('INSERT INTO events VALUES (?, ?)', [ (1, 'foo'), (2, 'bar'), (3, 'baz'), (1, 'foo'), ]) except (sqlite3.OperationalError, sqlite3.IntegrityError) as e: print('Could not complete operation:', e) # No row was inserted because transaction failed for row in connection.execute('SELECT * FROM events'): print(row) connection.close() 5. 使用Pragmas …当它真的有用时 在你的程序中有几个 pragma 可用于调整 sqlite3 的行为。特别地,其中一个可以改善性能的是 synchronous : connection.execute('PRAGMA synchronous = OFF') 你应该知道这可能是危险的。如果应用程序在事务中间意外崩溃,数据库可能会处于不一致的状态。所以请小心使用! 但是如果你要更快地插入很多行,那么这可能是一个选择。 6. 推迟索引创建 假设你需要在数据库上创建几个索引,而你需要在插入很多行的同时创建索引。把索引的创建推迟到所有行的插入之后可以导致实质性的性能改善。 7. 使用占位符插入 Python 值 使用 Python 字符串操作将值包含到查询中是很方便的。但是这样做非常不安全,而 sqlite3 给你提供了更好的方法来做到这一点: # Do not do this! my_timestamp = 1 c.execute("SELECT * FROM events WHERE ts = '%s'" % my_timestamp) # Do this instead my_timestamp = (1,) c.execute('SELECT * FROM events WHERE ts = ?', my_timestamp) 此外,使用Python%s(或格式或格式的字符串常量)的字符串插值对于 executemany 来说并不是总是可行。所以在此尝试没有什么真正意义! 请记住,这些小技巧可能会(也可能不会)给你带来好处,具体取决于特定的用例。你应该永远自己去尝试,决定是否值得这么做。 原文发布时间为:2017-10-26 本文作者:佚名 本文来自云栖社区合作伙伴“51CTO”,了解相关信息可以关注。
上一篇我们介绍了如何使用Ribbon的earger-load配置加速Spring Cloud中对服务接口的第一次调用。可是这样只是解决了内部服务间的调用,另外一个问题依然经常困扰我们,那就是网关到内部服务的访问。由于Spring Cloud Zuul的路由转发也是通过Ribbon实现负载均衡的,所以它也会存在第一次调时比较慢的情况。那么这个时候我们要如何设置呢? Zuul中的Eager Load配置 在Spring Cloud Zuul中也提供了一个配置参数来实现earger-load,具体如下: zuul.ribbon.eager-load.enabled=true 但是,可能你尝试一下之后会发现,并没有起效?为什么呢?这是由于Spring Cloud Zuul中实现eager-load的时候同Ribbon中一样,都需要指定具体哪些服务需要饥饿加载。那么在Spring Cloud Zuul中如何具体指定呢? 在Spring Cloud Zuul的饥饿加载中没有设计专门的参数来配置,而是直接采用了读取路由配置来进行饥饿加载的做法。所以,如果我们使用默认路由,而没有通过配置的方式指定具体路由规则,那么zuul.ribbon.eager-load.enabled=true的配置就没有什么作用了。 因此,在真正使用的时候,我们可以通过zuul.ignored-services=*来忽略所有的默认路由,让所有路由配置均维护在配置文件中,以达到网关启动的时候就默认初始化好各个路由转发的负载均衡对象。 原文发布时间为:2017-10-20 本文作者:翟永超 本文来自云栖社区合作伙伴“51CTO”,了解相关信息可以关注。
1、下面这段代码的输出结果是什么?请解释。 def extendList(val, list=[]): list.append(val) return list list1 = extendList(10) list2 = extendList(123,[]) list3 = extendList('a') print "list1 = %s" % list1 print "list2 = %s" % list2 print "list3 = %s" % list3 怎样修改extendList的定义能够产生以下预期的行为? 上面代码输出结果将是: list1 = [10, 'a'] list2 = [123] list3 = [10, 'a'] 很多人都会误认为list1=[10],list3=[‘a’],因为他们以为每次extendList被调用时,列表参数的默认值都将被设置为[].但实际上的情况是,新的默认列表只在函数被定义的那一刻创建一次。 当extendList被没有指定特定参数list调用时,这组list的值随后将被使用。这是因为带有默认参数的表达式在函数被定义的时候被计算,不是在调用的时候被计算。因此list1和list3是在同一个默认列表上进行操作(计算)的。而list2是在一个分离的列表上进行操作(计算)的。(通过传递一个自有的空列表作为列表参数的数值)。 extendList的定义可以作如下修改。 尽管,创建一个新的列表,没有特定的列表参数。 下面这段代码可能能够产生想要的结果。 def extendList(val, list=None): if list is None: list = [] list.append(val) return list 通过上面的修改,输出结果将变成: list1 = [10] list2 = [123] list3 = ['a'] 2、下面这段代码的输出结果将是什么?请解释。 def multipliers(): return [lambda x : i * x for i in range(4)] print [m(2) for m in multipliers()] 你如何修改上面的multipliers的定义产生想要的结果? 上面代码输出的结果是[6, 6, 6, 6] (不是我们想的[0, 2, 4, 6])。 上述问题产生的原因是Python闭包的延迟绑定。这意味着内部函数被调用时,参数的值在闭包内进行查找。因此,当任何由multipliers()返回的函数被调用时,i的值将在附近的范围进行查找。那时,不管返回的函数是否被调用,for循环已经完成,i被赋予了最终的值3。 因此,每次返回的函数乘以传递过来的值3,因为上段代码传过来的值是2,它们最终返回的都是6(3*2)。碰巧的是,《The Hitchhiker’s Guide to Python》也指出,在与lambdas函数相关也有一个被广泛被误解的知识点,不过跟这个case不一样。由lambda表达式创造的函数没有什么特殊的地方,它其实是和def创造的函数式一样的。 下面是解决这一问题的一些方法。 一种解决方法就是用Python生成器。 def multipliers(): for i in range(4): yield lambda x : i * x 另外一个解决方案就是创造一个闭包,利用默认函数立即绑定。 def multipliers(): return [lambda x, i=i : i * x for i in range(4)] 还有种替代的方案是,使用偏函数: from functools import partial from operator import mul def multipliers(): return [partial(mul, i) for i in range(4)] 3、下面这段代码的输出结果将是什么?请解释。 class Parent(object): x = 1 class Child1(Parent): pass class Child2(Parent): pass print Parent.x, Child1.x, Child2.x Child1.x = 2 print Parent.x, Child1.x, Child2.x Parent.x = 3 print Parent.x, Child1.x, Child2.x 输出结果将是: 1 1 1 1 2 1 3 2 3 让很多人困惑或惊讶的是最后一行输出为什么是3 2 3 而不是 3 2 1.为什么在改变parent.x的同时也改变了child2.x的值?但与此同时没有改变Child1.x的值? 此答案的关键是,在Python中,类变量在内部是以字典的形式进行传递。 如果一个变量名没有在当前类下的字典中发现。则在更高级的类(如它的父类)中尽心搜索直到引用的变量名被找到。(如果引用变量名在自身类和更高级类中没有找到,将会引发一个属性错误。) 因此,在父类中设定x = 1,让变量x类(带有值1)能够在其类和其子类中被引用到。这就是为什么第一个打印语句输出结果是1 1 1 因此,如果它的任何一个子类被覆写了值(例如说,当我们执行语句Child1.x = 2),这个值只在子类中进行了修改。这就是为什么第二个打印语句输出结果是1 2 1 最终,如果这个值在父类中进行了修改,(例如说,当我们执行语句Parent.x = 3),这个改变将会影响那些还没有覆写子类的值(在这个例子中就是Child2)这就是为什么第三打印语句输出结果是3 2 3 4、下面这段代码在Python2下输出结果将是什么?请解释。 def div1(x,y): print "%s/%s = %s" % (x, y, x/y) def div2(x,y): print "%s//%s = %s" % (x, y, x//y) div1(5,2) div1(5.,2) div2(5,2) div2(5.,2.) 在Python3下结果会有怎样的不同?(当然,假设上述打印语句被转换成Python3的语法) 在Python2中,上述代码输出将是 5/2 = 2 5.0/2 = 2.5 5//2 = 2 5.0//2.0 = 2.0 默认情况下,Python 2 自动执行整形计算如果两者都是整数。因此,5/2 结果是2,而5./2结果是2.5 注意,在Python2中,你可以通过增加以下引用来覆写这个行为。 from future import division 同时要注意的是,//操作符将总是执行整形除法,不管操作符的类型。这就是为什么即使在Python 2中5.0//2.0的结果是2.0。然而在Python3中,没有此类特性, 例如,在两端都是整形的情况下,它不会执行整形除法 因此,在Python3中,将会是如下结果: 5/2 = 2.5 5.0/2 = 2.5 5//2 = 2 5.0//2.0 = 2.0 注: 在 Python 3 中,/ 操作符是做浮点除法,而 // 是做整除(即商没有余数,比如 10 // 3 其结果就为 3,余数会被截除掉,而 (-7) // 3 的结果却是 -3。这个算法与其它很多编程语言不一样,需要注意,它们的整除运算会向0的方向取值。而在 Python 2 中,/ 就是整除,即和 Python 3 中的 // 操作符一样) 5、下面代码的输出结果将是什么? list = ['a', 'b', 'c', 'd', 'e'] print list[10:] 下面的代码将输出[],不会产生IndexError错误。就像所期望的那样,尝试用超出成员的个数的index来获取某个列表的成员。 例如,尝试获取list[10]和之后的成员,会导致IndexError. 然而,尝试获取列表的切片,开始的index超过了成员个数不会产生IndexError,而是仅仅返回一个空列表。 这成为特别让人恶心的疑难杂症,因为运行的时候没有错误产生,导致bug很难被追踪到。 6、考虑下列代码片段: list = [ [ ] ] * 5 list # output? list[0].append(10) list # output? list[1].append(20) list # output? list.append(30) list # output? 2,4,6,8行将输出什么结果?试解释。 输出的结果如下: [[], [], [], [], []] [[10], [10], [10], [10], [10]] [[10, 20], [10, 20], [10, 20], [10, 20], [10, 20]] [[10, 20], [10, 20], [10, 20], [10, 20], [10, 20], 30] 解释如下: 第一行的输出结果直觉上很容易理解,例如 list = [ [ ] ] * 5 就是简单的创造了5个空列表。然而,理解表达式list=[ [ ] ] * 5的关键一点是它不是创造一个包含五个独立列表的列表,而是它是一个创建了包含对同一个列表五次引用的列表。只有了解了这一点,我们才能更好的理解接下来的输出结果。 list[0].append(10) 将10附加在第一个列表上。 但由于所有5个列表是引用的同一个列表,所以这个结果将是: [[10], [10], [10], [10], [10]] 同理,list[1].append(20)将20附加在第二个列表上。但同样由于5个列表是引用的同一个列表,所以输出结果现在是: [[10, 20], [10, 20], [10, 20], [10, 20], [10, 20]] 作为对比, list.append(30)是将整个新的元素附加在外列表上,因此产生的结果是: [[10, 20], [10, 20], [10, 20], [10, 20], [10, 20], 30] 7、Given a list of N numbers。 给定一个含有N个数字的列表。 使用单一的列表生成式来产生一个新的列表,该列表只包含满足以下条件的值: (a)偶数值 (b)元素为原始列表中偶数切片。 例如,如果list[2]包含的值是偶数。那么这个值应该被包含在新的列表当中。因为这个数字同时在原始列表的偶数序列(2为偶数)上。然而,如果list[3]包含一个偶数, 那个数字不应该被包含在新的列表当中,因为它在原始列表的奇数序列上。 对此问题的简单解决方法如下: [x for x in list[::2] if x%2 == 0] 例如,给定列表如下: list = [ 1 , 3 , 5 , 8 , 10 , 13 , 18 , 36 , 78 ] 列表生成式[x for x in list[::2] if x%2 == 0] 的结果是, [10, 18, 78] 这个表达式工作的步骤是,第一步取出偶数切片的数字, 第二步剔除其中所有奇数。 8、给定以下字典的子类,下面的代码能够运行么?为什么? class DefaultDict(dict): def __missing__(self, key): return [] d = DefaultDict() d['florp'] = 127 能够运行。 当key缺失时,执行DefaultDict类,字典的实例将自动实例化这个数列。 原文发布时间为:2017-10-27 本文作者:developers 本文来自云栖社区合作伙伴“51CTO”,了解相关信息可以关注。
西部数据公司发布了一款Ultrastar 14 TB磁盘驱动器,其中亦配备有主机应用软件以管理新增的叠瓦式写入模式。 这是全球首款14 TB磁盘驱动器,采取氦气填充设计,这一点与其它10 TB以上高容量驱动器保持一致。该磁盘配合叠瓦式介质记录(简称SMR)技术,其中写入磁道之间彼此重叠以将存储密度提升至每平方英寸1034 Gbit。此前推荐的He10(即10 TB氦气填充式驱动器)则未采用叠瓦式设计,而选择了垂直磁记录(简称PMR)技术,存储密度为每平方英寸816 Gbit; 另外同样采用PMR技术的升级产品He12则拥有每平方英寸864 Gbit的存储密度。在此基础之上,叠瓦式设计让新产品较He12拥有额外的2 TB存储容量。 西部数据公司此前的氦气填充式驱动器产品则以“He”作为品牌标识,例如He10; 而这一次的14 TB产品则采用“Hs”品牌。 西部数据公司HGST Ultastar Hs14 14 TB磁盘驱动器。 Ultrastar属于HGST旗下品牌,HGST的磁盘驱动器业务则于几年前被西部数据方面所收购。其曾于2016年12月推出了He12 PMR驱动器的样品,而西数公司当时指出其正在开发一款叠瓦式版本,容量将达到14 TB。这里所指的正是如今的Hs14——其中的“s”,根据我们猜测,代表的也许正是叠瓦“shingled”一词。 He12与Hs14两款驱动器皆采用八块存储碟片。与He12类似,Hs14驱动器同样为7200转设计,配备有一个每秒6 Gbit SATA或者每秒12 Gbit SAS接口,且平均故障前运行时和为250万小时。 He12的缓冲区为256 MB,而持续传输速度为每秒255 MB。Hs14的缓冲区为512 MB,然而目前公布的持续传输速度则为每秒233 MB; 看起来叠瓦式设计给其速度表现带来了拖累。 Hs14的读取/写入寻道时间分别为7.7/12.0微秒; 皆差于He12的8.0/8.6毫秒——这显然又是叠瓦式设计带来的牺牲。 由于需要额外托管这种堆叠磁道操作,Hs14在设计用途方面主要针对连续写入环境,且并不适合成为其它3.5英寸磁盘驱动器的替代性方案。 Hs14驱动器据称拥有极低的每TB运行功耗水平,最高每年可支持550 TB企业级工作负载处理能力,提供即时安全擦除功能,且目前已经开始向各OEM厂商提供样品。这是一款专用型企业级高容量驱动器,适合低/无数据重写用例,因此很可能出现在归档类磁盘驱动器阵列当中。 原文发布时间为:2017年10月4日 本文作者:至顶网存储频道 本文来自云栖社区合作伙伴“至顶网”,了解相关信息可以关注。