之前分享過一次我在學習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