python學(xué)習(xí)筆記04

python學(xué)習(xí)筆記之04.

迭代器和生成器

迭代器

迭代是Python最強(qiáng)大的功能之一秆撮,是訪問集合元素的一種方式。
迭代器是一個可以記住遍歷的位置的對象船侧。
迭代器對象從集合的第一個元素開始訪問欠气,直到所有的元素被訪問完結(jié)束。迭代器只能往前不會后退镜撩。
迭代器有兩個基本的方法:iter() 和 next()预柒。

字符串,列表或元組對象都可用于創(chuàng)建迭代器:

實例(Python 3.0+)

>>>list=[1,2,3,4]
>>> it = iter(list)    # 創(chuàng)建迭代器對象
>>> print (next(it))   # 輸出迭代器的下一個元素
1
>>> print (next(it))
2
>>>

迭代器對象可以使用常規(guī)for語句進(jìn)行遍歷:

實例(Python 3.0+)
#!/usr/bin/python3
 
list=[1,2,3,4]
it = iter(list)    # 創(chuàng)建迭代器對象
for x in it:
    print (x, end=" ")

執(zhí)行以上程序袁梗,輸出結(jié)果如下:

1 2 3 4

也可以使用 next() 函數(shù):

實例(Python 3.0+)
#!/usr/bin/python3

import sys         # 引入 sys 模塊
 
list=[1,2,3,4]
it = iter(list)    # 創(chuàng)建迭代器對象
 
while True:
    try:
        print (next(it))
    except StopIteration:
        sys.exit()

執(zhí)行以上程序宜鸯,輸出結(jié)果如下:

1
2
3
4
生成器

在 Python 中,使用了 yield 的函數(shù)被稱為生成器(generator)遮怜。

跟普通函數(shù)不同的是淋袖,生成器是一個返回迭代器的函數(shù),只能用于迭代操作奈泪,更簡單點理解生成器就是一個迭代器适贸。

在調(diào)用生成器運行的過程中,每次遇到 yield 時函數(shù)會暫停并保存當(dāng)前所有的運行信息涝桅,返回 yield 的值, 并在下一次執(zhí)行 next() 方法時從當(dāng)前位置繼續(xù)運行拜姿。
調(diào)用一個生成器函數(shù),返回的是一個迭代器對象冯遂。

以下實例使用 yield 實現(xiàn)斐波那契數(shù)列:

實例(Python 3.0+)
#!/usr/bin/python3
 
import sys
 
def fibonacci(n): # 生成器函數(shù) - 斐波那契
    a, b, counter = 0, 1, 0
    while True:
        if (counter > n): 
            return
        yield a
        a, b = b, a + b
        counter += 1
f = fibonacci(10) # f 是一個迭代器蕊肥,由生成器返回生成
 
while True:
    try:
        print (next(f), end=" ")
    except StopIteration:
        sys.exit()

執(zhí)行以上程序,輸出結(jié)果如下:

0 1 1 2 3 5 8 13 21 34 55

裝飾器

引用知乎大神非常形象的比喻:
https://www.zhihu.com/question/26930016

內(nèi)褲可以用來遮羞,但是到了冬天它沒法為我們防風(fēng)御寒壁却,聰明的人們發(fā)明了長褲批狱,有了長褲后寶寶再也不冷了,裝飾器就像我們這里說的長褲展东,在不影響內(nèi)褲作用的前提下赔硫,給我們的身子提供了保暖的功效。

裝飾器本質(zhì)上是一個Python函數(shù)盐肃,它可以讓其他函數(shù)在不需要做任何代碼變動的前提下增加額外功能爪膊,裝飾器的返回值也是一個函數(shù)對象。它經(jīng)常用于有切面需求的場景砸王,比如:插入日志推盛、性能測試、事務(wù)處理谦铃、緩存耘成、權(quán)限校驗等場景。裝飾器是解決這類問題的絕佳設(shè)計驹闰,有了裝飾器瘪菌,我們就可以抽離出大量與函數(shù)功能本身無關(guān)的雷同代碼并繼續(xù)重用。概括的講疮方,裝飾器的作用就是為已經(jīng)存在的對象添加額外的功能控嗜。

下面是一個重寫了特殊方法 getattribute 的類裝飾器, 可以打印日志:

def log_getattribute(cls):
    # Get the original implementation
    orig_getattribute = cls.__getattribute__

    # Make a new definition
    def new_getattribute(self, name):
        print('getting:', name)
        return orig_getattribute(self, name)

    # Attach to the class and return
    cls.__getattribute__ = new_getattribute
    return cls

# Example use
@log_getattribute
class A:
    def __init__(self,x):
        self.x = x
    def spam(self):
        pass

下面是使用效果:

>>> a = A(42)
>>> a.x
getting: x
42
>>> a.spam()
getting: spam
>>>

作業(yè)

員工信息管理程序
staffs.txt

3,Rain Wang,21,13451054608,IT,2017‐04‐01
4,Mack Qiao,44,15653354208,Sales,2016‐02‐01
5,Rachel Chen,23,13351024606,IT,2013‐03‐16
6,Eric Liu,19,18531054602,Marketing,2012‐12‐01
7,Chao Zhang,21,13235324334,Administration,2011‐08‐08
8,Kevin Chen,22,13151054603,Sales,2013‐04‐01
9,Shit Wen,20,13351024602,IT,2017‐07‐03
10,Shanshan Du,26,13698424612,Operation,2017‐07‐02
11,Libai,26,134435366,IT,2015‐10‐2
12,Libai,26,134435366,IT,2015‐10‐23

StaffManage.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Created by master on  2018/5/21 16:45.
import codecs
import os
from tabulate import tabulate


class StaffManage(object):
    file_path = "staffs.txt"

    # 增刪改查入口
    def manage(self, sql):
        lower_sql = sql.lower()
        if lower_sql.startswith("add"):
            self.add(sql)
        elif lower_sql.startswith("del"):
            self.remove(sql)
        elif lower_sql.startswith("update"):
            self.update(sql)
        elif lower_sql.startswith("find"):
            self.find(sql)
        elif lower_sql.startswith("exit"):
            exit("退出程序")
        else:
            log("命令不存在或者輸入錯誤骡显,請仔細(xì)檢查后重新輸入疆栏!", "error")

    # 查詢
    def find(self, sql):
        '''
        find name,age from staff_table where age > 22
        find * from staff_table where dept = "IT"
        find * from staff_table where enroll_date like "2013"
        '''
        lower_sql = sql.lower()
        lower_sql = lower_sql.replace("find", "").replace("*", "").replace("from", "") \
            .replace("staff_table", "").replace('"', "").replace("'", "").strip()
        list_param = lower_sql.split("where")
        new_staffs = []
        if list_param[0]:
            log("沒有這個命令,請確認(rèn)惫谤!", "error")
        else:
            list_staff = self.load_file()
            if "=" in list_param[1]:
                key = list_param[1].split("=")[0].strip()
                value = list_param[1].split("=")[1].strip()
                for staff in list_staff:
                    if staff[key].lower() == value:
                        new_staffs.append(staff)
            elif "like" in list_param[1]:
                key = list_param[1].split("like")[0].strip()
                value = list_param[1].split("like")[1].strip()
                for staff in list_staff:
                    if value in staff[key].lower():
                        new_staffs.append(staff)
            else:
                if ">" in list_param[1]:
                    key = list_param[1].split(">")[0].strip()
                    value = list_param[1].split(">")[1].strip()
                    for staff in list_staff:
                        if int(staff[key]) > int(value):
                            new_staffs.append(staff)
                elif "<" in list_param[1]:
                    key = list_param[1].split("<")[0].strip()
                    value = list_param[1].split("<")[1].strip()
                    for staff in list_staff:
                        if int(staff[key]) < int(value):
                            new_staffs.append(staff)
        print_table(new_staffs)

    # 添加紀(jì)錄
    def add(self, sql):
        #  "add staff_table Alex Li,25,134435344,IT,2015‐10‐29"
        sql = "0," + sql.replace("add", "").replace("ADD", "").replace("staff_table", "").strip()
        d_staff = self.__split_line(sql)
        if not self.phone_exist(self.load_file(), d_staff["phone"]):
            d_staff["staff_id"] = str(int(self.__get_last_staff_id()) + 1)
            self.__insert([d_staff])
            log("影響了1行")
        else:
            log("存在重復(fù)的手機(jī)號碼壁顶,請確認(rèn)!", "error")

    # 判斷手機(jī)號是否存在
    def phone_exist(self, staffs, phone):
        phones = []
        for staff in staffs:
            phones.append(staff["phone"])
        return phone in phones

    # 插入記錄
    def __insert(self, staffs, mode="a+"):
        with codecs.open(self.file_path, mode, "utf-8") as f:
            for i in range(len(staffs)):
                staff = staffs[i]
                record = ""
                len_values = len(staff.values())
                for j in range(len_values):
                    v = list(staff.values())[j]
                    if j < len_values - 1:
                        record += v + ","
                    else:
                        record += v
                if i > 0:
                    f.write("\n" + record)
                else:
                    f.write(record)

    # 更新記錄
    def update(self, sql):
        effect_lines = 0
        lower_sql = sql.lower()
        lower_sql = lower_sql.replace("update", "").replace("staff_table", "") \
            .replace('"', "").replace('set', "").replace("'", "").strip()
        list_param = lower_sql.split("where")
        u_key = list_param[0].split("=")[0].strip()
        u_value = list_param[0].split("=")[1].strip()
        o_key = list_param[1].split("=")[0].strip()
        o_value = list_param[1].split("=")[1].strip()
        list_staff = self.load_file()
        for staff in list_staff:
            if staff[o_key].lower() == o_value:
                staff[u_key] = u_value
                effect_lines += 1

        log("影響了%s行" % effect_lines)
        self.__insert(list_staff, "w")

    # 刪除記錄
    def remove(self, sql):
        # del from staff where id=3
        effect_lines = 0
        sql = sql.lower().replace("del", "").replace("from", "").replace("staff_table", "") \
            .replace("where", "").strip()
        list_param = sql.split("=")
        id = list_param[1].strip()
        list_staff = self.load_file()
        for staff in list_staff:
            if staff["staff_id"] == id:
                list_staff.remove(staff)
                effect_lines += 1
            else:
                return
        log("影響了%s行" % effect_lines)
        self.__insert(list_staff, "w")

    # 切分sql,提取有效字段
    def __split_line(self, line):
        list_param = line.split(",")
        d_staff = {}
        for i in range(len(list_param)):
            if i == 0:
                d_staff["staff_id"] = list_param[i].strip()
            elif i == 1:
                d_staff["name"] = list_param[i].strip()
            elif i == 2:
                d_staff["age"] = list_param[i].strip()
            elif i == 3:
                d_staff["phone"] = list_param[i].strip()
            elif i == 4:
                d_staff["dept"] = list_param[i].strip()
            elif i == 5:
                d_staff["enroll_date"] = list_param[i].strip()
        return d_staff

    # 加載數(shù)據(jù)表
    def load_file(self):
        if os.path.exists(self.file_path):
            list_staffs = []
            with codecs.open(self.file_path, "r", "UTF-8") as staff_list:
                for line in staff_list:
                    staff = self.__split_line(line)
                    list_staffs.append(staff)
                return list_staffs

    # 讀取數(shù)據(jù)表的最后一行
    def __read_last_line(self):
        with codecs.open(self.file_path, 'r', "UTF-8") as f:  # 打開文件
            lines = f.readlines()
            return lines[-1]  # 取最后一行

    # 獲取最后一個id溜歪,實現(xiàn)id自增
    def __get_last_staff_id(self):
        line = self.__read_last_line()
        d_staff = self.__split_line(line)
        return d_staff["staff_id"]


# 日志工具
def log(msg, log_type="info"):
    if log_type == 'info':
        print("\033[32;1m%s\033[0m" % msg)
    elif log_type == 'error':
        print("\033[31;1m%s\033[0m" % msg)


# 打印表格
def print_table(staffs):
    print(tabulate(staffs, tablefmt="grid"))


if __name__ == '__main__':
    staffManage = StaffManage()
    while True:
        sql_eval = input(">>>")
        staffManage.manage(sql_eval)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末若专,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蝴猪,更是在濱河造成了極大的恐慌调衰,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件自阱,死亡現(xiàn)場離奇詭異嚎莉,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)沛豌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進(jìn)店門趋箩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事叫确√迹” “怎么了?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵竹勉,是天一觀的道長飞盆。 經(jīng)常有香客問我,道長饶米,這世上最難降的妖魔是什么桨啃? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮檬输,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘匈棘。我一直安慰自己丧慈,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布主卫。 她就那樣靜靜地躺著逃默,像睡著了一般。 火紅的嫁衣襯著肌膚如雪簇搅。 梳的紋絲不亂的頭發(fā)上完域,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天,我揣著相機(jī)與錄音瘩将,去河邊找鬼吟税。 笑死,一個胖子當(dāng)著我的面吹牛姿现,可吹牛的內(nèi)容都是我干的肠仪。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼备典,長吁一口氣:“原來是場噩夢啊……” “哼异旧!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起提佣,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤吮蛹,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后拌屏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體潮针,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年槐壳,在試婚紗的時候發(fā)現(xiàn)自己被綠了然低。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖雳攘,靈堂內(nèi)的尸體忽然破棺而出带兜,到底是詐尸還是另有隱情,我是刑警寧澤吨灭,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布刚照,位于F島的核電站,受9級特大地震影響喧兄,放射性物質(zhì)發(fā)生泄漏无畔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一吠冤、第九天 我趴在偏房一處隱蔽的房頂上張望浑彰。 院中可真熱鬧,春花似錦拯辙、人聲如沸郭变。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽诉濒。三九已至,卻和暖如春夕春,著一層夾襖步出監(jiān)牢的瞬間未荒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工及志, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留片排,地道東北人。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓困肩,卻偏偏與公主長得像划纽,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子锌畸,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,435評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 〇勇劣、前言 本文共108張圖,流量黨請慎重潭枣! 歷時1個半月比默,我把自己學(xué)習(xí)Python基礎(chǔ)知識的框架詳細(xì)梳理了一遍。 ...
    Raxxie閱讀 18,966評論 17 410
  • 今天7點鐘就上班了盆犁,奮戰(zhàn)了一天命咐,最后還加了一個小時的班。 下午陳睿去白云區(qū)了谐岁,搬了一點東西走醋奠,回到家后榛臼,感覺家里 ...
    清和簡閱讀 182評論 0 0
  • 《一路同行》 原曲:羅大佑 《明天會更好》 填詞:鄺鑒萍 演唱:【光明頂】鄺鑒萍、關(guān)炳剛窜司、周鉑淏沛善、張宇 不愿看你遠(yuǎn)...
    鄺鑒萍閱讀 220評論 0 6
  • 夜幕拉開放飛幾粒星辰 湖水蛹動筑起幾道波紋 月與月的對稱忽略了軸心 我一個人,披著霧踏著林 蛐蛐大概因為貪嗅了花粉...
    靠勁兒閱讀 239評論 0 0
  • 高考成績已經(jīng)出爐,不管你們成績?nèi)绾我樾剑家宄嚷晒Σ槐刈詽M,失敗不必傷心斯议。因為产捞,人生就是不斷清零的過程。 但有些事...
    f5c8375254c2閱讀 433評論 0 9