前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >2017年8月28日技术日记

2017年8月28日技术日记

作者头像
阿章-python小学生
发布2018-05-18 17:00:43
6920
发布2018-05-18 17:00:43
举报
  1. python 列表 * 的坑
board = [['_'] * 3 for i in range(3)]
board
Out[46]:
[['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]
In [47]:

board
board[1][2] = 'X'
board
Out[47]:
[['_', '_', '_'], ['_', '_', 'X'], ['_', '_', '_']]

这个相当于

board = []
for i in range(3):
    row = ['_'] * 3
    board.append(row)
board
Out[57]:
[['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]
In [58]:

board[1][2] = 'X'
board
Out[58]:
[['_', '_', '_'], ['_', '_', 'X'], ['_', '_', '_']]

但是

weird_board = [['_'] * 3]  * 3
weird_board
weird_board = [['_'] * 3]  * 3
weird_board
Out[59]:
[['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]
In [60]:

weird_board[1][2] = 'X'
weird_board
Out[60]:
[['_', '_', 'X'], ['_', '_', 'X'], ['_', '_', 'X']]

相当于

row = ['_'] * 3
weird_board = []
for i in range(3):
    weird_board.append(row)
weird_board[1][2] = 'X'
weird_board
Out[62]:
[['_', '_', 'X'], ['_', '_', 'X'], ['_', '_', 'X']]
  1. python中 +=要注意的 首先 a+=b会调用a实现了的 __iadd__方法, 如果没有这个方法才会调用 __add__方法。而可变序列一般都实现了 __iadd__方法, 而不可变对象根本不支持这个操作。下面展示了 *=再不可变序列上的作用。
l = [1,2,3]
In [1]: l=[1,2,3]

In [2]: id(l)
Out[2]: 2396048446664

In [3]: l *= 2

In [4]: l
Out[4]: [1, 2, 3, 1, 2, 3]

In [5]: id(l)
Out[5]: 2396048446664

In [6]: t=(1,2,3)

In [7]: id(t)
Out[7]: 2396048383360

In [8]: t*=2

In [9]: t
Out[9]: (1, 2, 3, 1, 2, 3)

In [10]: id(t)
Out[10]: 2396048501448

出现这样的原因就是因为list的l调用了list里的 __iadd()__方法,而属于tuple的t由于不支持修改没有 __iadd()__方法而调用了 __add()__方法。

  1. 面试题选择
In [13]: t = (1, 2, [30, 40])

In [14]: t[2] += [50,60]

以上代码的输出是什么?

  1. t 变成 (1, 2, [30, 40, 50, 60])
  2. 因为tuple不支持对它的赋值操作,所以会抛出TypeError异常。
  3. 以上两个都不是
  4. a和b都是对的

答案是什么?你以为是b,其实是d,a和b都是对的。结果是

In [13]: t = (1, 2, [30, 40])
In [14]: t[2] += [50,60]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-14-fb586dd7f384> in <module>()
----> 1 t[2] += [50,60]
TypeError: 'tuple' object does not support item assignment
In [15]: t
Out[15]: (1, 2, [30, 40, 50, 60])

原因是+=不是原子操作,尽量不要再tuple里嵌套可变对象。可以查看字节码来真相了

In [11]: from dis import dis

In [12]: dis('s[a] += b')
  1           0 LOAD_NAME                0 (s)
              2 LOAD_NAME                1 (a)
              4 DUP_TOP_TWO
              6 BINARY_SUBSCR                   # 将s[a]的值压入栈顶TOS(Top of Stack)
              8 LOAD_NAME                2 (b)
             10 INPLACE_ADD                     # 计算TOS += b 这里能完成是因为TOS指向的是一个可变对象。
             12 ROT_THREE
             14 STORE_SUBSCR                    # 这一步失败,因为s是不可变元组
             16 LOAD_CONST               0 (None)
             18 RETURN_VALUE
  1. python:list.sort()会就地改变列表而返回None,sorted()不会就地改变列表会新生成一个列表而返回它。
  2. python: bisect.bisect(haystack,needle)haystack是干草垛的意思,needle是针的意思。会用二分查找法返回needle在haystack中之后的位置。 bisect.bisect_left(haystack,needle)返回的是needle在haystack中之前的位置。 bisect.insort(seq,item)可以插入元素。

bisect.bisect举例:

import bisect


def grade(score):
    breakpoints = [60, 70, 80, 90]
    grades = 'EDCBA'
    i = bisect.bisect(breakpoints, score)
    return grades[i]


print([grade(score) for score in [33, 99, 77, 70, 89, 90, 100]])
[Out] ['E', 'A', 'C', 'C', 'B', 'A', 'A']

bisect.insort举例:

import bisect
import random

SIZE = 7
random.seed(1729)
my_list = []
for i in range(SIZE):
    new_item = random.randrange(SIZE * 2)
    bisect.insort(my_list, new_item)
    print('%2d ->' % new_item, my_list)
[Out]
10 -> [10]
 0 -> [0, 10]
 6 -> [0, 6, 10]
 8 -> [0, 6, 8, 10]
 7 -> [0, 6, 7, 8, 10]
 2 -> [0, 2, 6, 7, 8, 10]
10 -> [0, 2, 6, 7, 8, 10, 10]
  1. 当列表不是首选时,可以使用数组(存放大量数据) set(频繁使用in判断,set对in进行了优化)。 数组除了支持.pop,.insert,.extend等可变序列上的操作外,还支持从文件读取或存入文件更快的方法。 如.frombytes和.tofile。数组存放的是C语言的数组而不是float对象,多以序列大的时候可以节省内存空间。
from array import array
from  random import random

floats = array('d', (random() for i in range(10 ** 7)))
print(floats[-1])
fp = open('floats.bin', 'wb')
floats.tofile(fp)
fp.close()
floats2 = array('d')
fp = open('floats.bin', 'rb')
floats2.fromfile(fp, 10 ** 7)
fp.close()
print(floats2[-1])
print(floats2 == floats)
[Out]
0.48178023314354956
0.48178023314354956
True

使用array.tofile和array.fromfile要比直接读取float对象要快很多。

  1. memoryview內存视图可以在不复制内容的情况下操作同一数组的不同切片,在数据结构之间共享内存。 memoryview.cast()会把同一块内存的内容打包成一个全新的memoryview对象给你。
from array import array

numbers = array('h', [-2, -1, 0, 1, 2])
memv = memoryview(numbers)
print(len(memv))
print(memv[0])
memv_dict = memv.cast('B')
print(memv_dict.tolist())
memv_dict[5] = 4
print(numbers)
[Out]
5
-2
[254, 255, 255, 255, 0, 0, 1, 0, 2, 0]
array('h', [-2, -1, 1024, 1, 2])

h是2个字节的有符号整型,B是1个字节无符号整型。因为我们把占两个字节的整数的高位变成了4,所以这个有符号整数的值就变成了1024. 1.numpy是优秀的库,实现了多维同质数组。代码举例

import numpy

a = numpy.arange(12)
print(a)
# [ 0  1  2  3  4  5  6  7  8  9 10 11]
print(type(a))  # <class 'numpy.ndarray'>
print(a.shape)  # 结果是一个一维数组,元素有12个
a.shape = 3, 4  # 把数组变成二维的
print(a)
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]
print(a[2])  # 打印第2行
# [ 8  9 10 11]
print(a[2, 1])  # 打印第2行第1列
# 9
print(a[:, 1])  # 打印第1列
# [1 5 9]
print(a.transpose())  # 行列交换
# [[ 0  4  8]
#  [ 1  5  9]
#  [ 2  6 10]
#  [ 3  7 11]]
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-08-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 python全栈布道师 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档