Python筆記【二】

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章