之前分享过一次我在学习Python的笔记,Python笔记【一】,最近有些新的收获,分享一下;
random.sample() 随机不重复的数
工作中,有时候是需要在数据库手动去造些数据的,有些字段类似 order_id ,一般都是不重复的(在不考虑有退款等其他异常的情况下),若要造超多数量、不重复的order_id,该如何来做?
推荐使用random.sample();
实际 在遇到生成随机整数的时候,我第一反应就是random.randint(),我们对比下:
循环random.randint(),实际会重复,而random.sample() 不会重复,具体原因:源码中注释
字符串find() != -1
find() 检测字符串中是否包含子字符串 sub,如果指定 start 和 end 范围,则在指定范围内 检查是否包含,如果包含子字符串 返回子字符串的索引值,否则返回-1。
这儿主要是想说下 :Return -1 on failure
因为 我往往不能确定子字符串的index,反而使用 str_xx.find('xxxx) != -1 会更多。
字符串开头、结尾 startswith() \endwith()
有时候确定 某字符串是否以某子字符串为开头、结尾,就要用到startswith()、 endswith();
这儿要说的是上面2图 鼠标所在那行 prefix can also be a tuple of strings to try 。suffix传参一个 全都为str的tuple,可以用来判断N个元素。
list.index() == -1 【错误用法】
标题是错误的(我在遇到第2次,才反应过来);
一直以来,访问列表的最后一个元素,我用的是list[-1],不知不觉就和list.index()用乱了。
list.index(obj):从列表中找出某个值第一个匹配项的索引位置
我之所以用list.index(obj) == -1, 是想当然认为 list的最后一个元素的索引是-1; 但实际索引是从0开始【大于等于0】;
def test_20200221b(self):
list_data = ['1', '2', '65', 'zy', 'zyooooxie', 'csdn']
check_ele = 'xie1111'
for d in list_data:
print(list_data.index(d))
if d.find(check_ele) != -1:
print('找到')
break
else:
if list_data.index(d) == -1:
# if d == list_data[-1]:
print('最后一个 没找到')
拿这个用例来做个说明,想看下list_data下面哪个元素可以find(check_ele),如果找到就结束for循环;如果最后那个元素也不符合,就 print没找到;
实际执行结果:
为什么没有 print‘没找到’? 实际就是 else里面 if判断出了问题【列表的索引 不会等于 -1】;
字符串 replace()
先看下源码:
我是很喜欢用replace() 的,总结:
1.replace() 返回一个字符串的副本,其中出现的旧字符(old)被替换为新的(new),可选地将替换数count限制为最大值;
2.不传count,会把当前所有符合的old都替换为new ;
3.old的参数不存在,不报错,生成的新字符串和原 string 保持一致 ;
4.可以多次replace() ;
5.replace 不会改变原 string 的内容;
6.count 传超过 实际替换次数,也不会报错;
递归
说起递归,就想起以前面试的时候遇到过2次这样的考题,很有印象的;
这儿说一个情景:我今天发生5笔交易【-10,+20,-15,+124,-156】,最初手上是50块钱,每笔交易之后我手上多少钱?
思路:50-10 为第一笔交易后的钱【期初 + 第一笔】; 50-10+20 为第二笔交易的钱【第一笔交易后的钱 + 第二笔】; 50-10+20-15 为第三笔交易的钱【第二笔交易后的钱 + 第三笔】,依此类推;
def fun_Recursive(self, x, x_list, opening):
if x == 0:
return round(opening + x_list[0], 2)
else:
return round(self.fun_Recursive(x-1, x_list, opening) + x_list[x], 2)
这样就可以得到: 每笔交易后 手上的钱数 40, 60, 45, 169, 13。
若干笔交易,是不是也很容易得到结果呢?
实际,递归次数太多,会报错 maximum recursion depth exceeded;
针对这问题,咋解决? 手动设置 递归次数限制:
代码如下:
import sys
sys.setrecursionlimit(10000)
这儿虽然设置为10000次,但我电脑在3200次左右,内存差不多吃不消;【下图和前面的是同一条用例,只是设置了setrecursionlimit】
倘若 交易量真为数千笔呢?数万笔呢?
def test_20200222_abc(self):
amount_list = random.sample(range(6000, 600000000000), 359162)
# 单笔交易Amount在6000-600000000000,共发生359162笔交易;期初设置为500
opening = 500
if len(amount_list) <= 3000: # 将3000作为1次递归的长度
# dg_last_value = self.fun_Recursive(len(amount_list) - 1, amount_list, opening)
# print(dg_last_value)
dg_value = [self.fun_Recursive(d, amount_list, opening) for d in range(len(amount_list))]
Log.info(dg_value)
else:
# ci_shu = math.ceil(len(amount_list) / 3000)
ci_shu = int(math.ceil(len(amount_list) / 3000)) # 加不加int一样
last_list = [list() for o in range(ci_shu)]
for a in range(ci_shu):
if a == 0:
print(a * 3000, (a+1) * 3000)
new_list = amount_list[a * 3000:(a+1) * 3000]
dg_value_0 = [self.fun_Recursive(i, new_list, opening) for i in range(len(new_list))]
last_list[a].extend(dg_value_0)
else:
print(a * 3000, (a+1) * 3000)
new_list = amount_list[a * 3000:(a+1) * 3000]
dg_value_other = [self.fun_Recursive(i, new_list, last_list[a - 1][-1]) for i in range(len(new_list))]
last_list[a].extend(dg_value_other)
Log.info('每一笔交易后的钱数, 以3000笔为一组, {}'.format(last_list))
Log.info('直接sum() 计算结果:{}'.format(sum(amount_list) + opening))
Log.info('多次递归,最后一组 最后一笔交易后的钱数:{}'.format(last_list[-1][-1]))
计算过程:
最后的结果:
期初设置为500;单笔交易Amount在6000-600000000000,共发生359162笔交易;
sum()
前面递归那一块的代码,最后面我写的是 ‘直接sum() 计算结果:{}’.format(sum(amount_list) + opening),
现在再看下 sum()
result=sum(iterable[, start])
sum() 是返回序列iterable的总和,可选参数start表示从该值开始加起来,默认为0;
换个角度想,sum()来做那个情景是不是更好呢?
【某一笔的交易后的钱数,都是amount_list此元素之前all元素的和 + 期初】
如果跑几十万的amount呢?
出现了数据量太大【将近36w】,迟迟拿不到结果的情况;(可能是我电脑配置不够的原因)
把每次传的amount_list 改动下:
def test_20200225a(self):
amount_list = random.sample(range(6000, 600000000000), 173219)
# 单笔交易Amount在6000-600000000000,共发生173219笔交易;期初设置为500
opening = 500
last_list = list()
if len(amount_list) >= 10000:
cishu = int(math.ceil(len(amount_list) / 10000))
for i in range(cishu):
if i == 0:
print(i * 10000, (i+1) * 10000)
new_list = [sum(amount_list[0: a], opening) for a in range(1, 10001)]
last_list.extend(new_list)
else:
print(i * 10000, (i + 1) * 10000)
new_list = [sum(amount_list[i * 10000: i * 10000 + a], last_list[-1]) for a in range(1, 10001)]
last_list.extend(self.delete_repeat(new_list)) # 删除重复元素
else:
last_list = [sum(amount_list[:a], opening) for a in range(1, len(amount_list) + 1)]
# Log.info(last_list)
# Log.info(len(last_list))
Log.info('直接sum() 计算结果:{}'.format(sum(amount_list) + opening))
Log.info('最后一笔交易后的钱数:{}'.format(last_list[-1]))
交流技术 欢迎+ QQ\微信 153132336 zy
个人博客 https://blog.csdn.net/zyooooxie
来源:CSDN
作者:zyooooxie
链接:https://blog.csdn.net/zyooooxie/article/details/103815286