Python.學習筆記.md

1、Python學習筆記

1. 第一章 計算機基礎

1-1. 1.1 硬件

計算機基本的硬件由:CPU / 內存 / 主板 / 硬盤 / 網卡 / 顯卡 等組成,只有硬件但硬件之間沒法進行交流和通訊。html

1-2. 1.2 操做系統

操做系統用於協同或控制硬件之間進行工做,常見的操做系統有那些:前端

  • windows
    • win xp
    • win7
    • win10
    • Windows sever
  • linux
    • centos 【公司線上通常用】
    • Redhat 企業級
    • Ubuntu 適合我的開發,圖形化好
  • mac

1-3. 1.3 解釋器或編譯器

編程語言的開發者寫的一個工具,將用戶寫的代碼轉換成010101交給操做系統去執行。java

1-3-1. 1.3.1 解釋和編譯型語言

解釋型語言就相似於: 實時翻譯,表明:Python / PHP / Ruby / Perlpython

編譯型語言相似於:說完以後,總體再進行翻譯,表明:C / C++ / Java / Go ...linux

1-4. 1.4 軟件(應用程序)

軟件又稱爲應用程序,就是咱們在電腦上使用的工具,相似於:記事本 / 圖片查看 / 遊戲git

1-5. 1.5 進制

對於計算機而言不管是文件存儲 / 網絡傳輸輸入本質上都是:二進制(010101010101),如:電腦上存儲視頻/圖片/文件都是二進制; QQ/微信聊天發送的表情/文字/語言/視頻 也所有都是二進制。面試

進制:正則表達式

  • 2進制,計算機內部。
  • 8進制, 逢8進1
  • 10進制,人來進行使用通常狀況下計算機能夠獲取10進制,而後再內部會自動轉換成二進制並操做。
  • 16進制,通常用於表示二進制(用更短的內容表示更多的數據),一版是:\x 開頭。10-15:ABCDEF

1-6. 1.6 單位換算

1TB=1024GB 1GB=1024MB 1MB=1024KB 1KB=1024B 1B=8bredis

2. 第二章 Python入門

2-1. 2.1 環境的安裝

  • 解釋器:py2 / py3 (環境變量)算法

    • python 2.7.16(2020官方再也不維護)
    • python 3.6.8(推薦,不用最新版本)

    最好安裝在根目錄下,若是同時安裝2.7版本,更改解釋器exe名字並作區分

    Linux解釋器路徑 #!/usr/bin/env python

  • 開發工具:pycharm

    • ctrl+?能夠快速註釋多行pycharm

    • Ctrl+D快速複製能夠快速複製上一行

2-2. 2.2 編碼

2-2-1. 2.2.1 編碼基礎

編碼 簡介
ASCII 英文及符號,8bit表示一內容,2**8=1byte
Unicode 萬國碼,32bit表示一內容,2**32=4byte
UTF-8 壓縮的Unicode,8bit爲一單位,省去高位0. 中文:3byte=24bit
GBK 支持簡體中文和繁體中文,中文是2字節
GB2312 簡體中文

2-2-2. 2.2.2 python編碼相關

對於Python默認解釋器編碼:

  • py2: ascii
  • py3: utf-8

若是想要修改默認編碼,則可使用:

# -*- coding:utf-8 -*- 

注意:對於操做文件時,要按照:以什麼編寫寫入,就要用什麼編碼去打開。

2-3. 2.3 變量

2-3-1. 2.3.1 變量的做用

爲某個值建立一個「外號」,之後在使用時候經過此外號就能夠直接調用。

2-3-2. 2.3.2變量命名要求

  1. 變量名只能包含:字母/數字/下劃線

  2. 數字不能開頭

  3. 不能是python的關鍵字。

    [‘and’, ‘as’, ‘assert’, ‘break’, ‘class’, ‘continue’, ‘def’, ‘del’, ‘elif’, ‘else’,‘except’, ‘exec’, ‘finally’, ‘for’, ‘from’, ‘global’, ‘if’, ‘import’, ‘in’, ‘is’,‘lambda’, ‘not’, ‘or’, ‘pass’, ‘print’, ‘raise’, ‘return’, ‘try’, ‘while’, ‘with’,‘yield’]

  4. 建議:

    1. 見名知意: name = "alex" age= 18

    2. 用下劃線鏈接:alex_dad = "吳佩其"

    3. 補充:AlexDad = '吳佩其' (駝峯式命名)

      # 建議變量名不要用:str/int/list/tuple/set/dict/float
      # user_list = [11,22,33] # 推薦
      # list = [11,22,33] # 不推薦
      # list = 'alex'
      # v = (11,22,33)
      # v1 = list(v)

2-4. 2.4 註釋

  • 單行註釋 #註釋
  • 多行註釋 """註釋"""
  • 文件註釋 文件開頭"""內容"""

2-5. 2.5 輸入輸出

2-5-1. 2.5.1 語法格式

差異對比 輸入 輸出
python2 raw_input("輸入") print "輸出"
python3 input("輸入") print("輸出")

注意:input()獲取的數據類型爲字符串

2-5-2. 2.5.2 格式化輸出

  • %s: 字符串佔位符

    # 字符串格式化存在的意義
    name = input('姓名:')
    do = input('在幹什麼:')
    template = "%s在教室,%s。" %(name,do,)    #最後加逗號
    print(template)
    # 直接作佔位符
    # template = "我是%s,年齡%s, 職業%s。" %("alex",73,'講雞湯',)
    # print(template)
  • %d: 整形站位符

    # template = "我是%s,年齡%d, 職業%s。" %("alex",73,'講雞湯',)
    # print(template)
  • %%: 輸出%

    # name = 'alex'
    # template = "%s如今手機的電量是100%%" %(name,)
    # print(template)
  • 練習

    name = input('請輸入姓名:')
    age = input('請輸入年齡:')
    job = input('請輸入職業:')
    hobby = input('請輸入愛好:')
    msg = ''' ------------ info of Alex Li ---------- Name : %s Age : %s job : %s Hobbie: %s ------------- end ----------------'''
    data = msg %(name,age,job,hobby,)
    print(data)
  • 特殊格式1

    msg = "我是%s,年齡%s" %('alex',19,)
    print(msg)
    
    msg = "我是%(n1)s,年齡%(n2)s" % {'n1': 'alex', 'n2': 123, }
    print(msg)
  • 特殊格式2

    # v1 = "我是{0},年齡{1}".format('alex',19)
    v1 = "我是{0},年齡{1}".format(*('alex',19,))
    print(v1)
    
    # v2 = "我是{name},年齡{age}".format(name='alex',age=18)
    v2 = "我是{name},年齡{age}".format(**{'name':'alex','age':18})
    print(v2)

2-5-3. 2.6 運算符

2-5-4. 2.6.1算數運算符

​ +、-、*、/、%、**、//

# 練習題: 1 ~ 100 之間全部的數相加。
# total = 0
# count = 1
# while count <=100:
# total = total + count
# count = count + 1
# print(total)
# 練習題:打印 1 ~ 100 之間的奇數。
count = 1
while count <= 100:
    val = count % 2
    if val == 1:
    print(count)
count = count + 1

2-5-5. 2.6.2 比較運算符

​ >/>=/</<=/==/!=

2-5-6. 2.6.3 賦值運算符

​ +=/-=

# count = 1
# while count <=100:
# print(count)
# count +=1 # count = count + 1

2-5-7. 2.6.4 邏輯運算符

​ and or not

  • 通常用於判斷
if 1 > 0 and 1 > 2:
print('666')
  • 二般用於取值(面試)

    • or
    """ 對於 or,若是有遇到 value= 1 or 9 第一個值若是是轉換成布爾值若是是真,則value=第一值。 第一個值若是是轉換成布爾值若是是假,則value=第二值。 若是有多個or條件,則從左到右依次進行上述流程。 示例: v1 = 0 or 1 v2 = 8 or 10 v3 = 0 or 9 or 8 """
    • and
    """對於and,若是遇到 value= 1 and 9 這種狀況 若是第一個值轉換成布爾值是True,則value=第二個值。 若是第一個值轉換成布爾值是False,則value=第一個值。 若是有多個and條件,則從左到右依次進行上述流程。 示例: v1 = 1 and 9 v2 = 1 and 0 v3 = 0 and 7 v4 = 0 and "" v5 = 1 and 0 and 9 """
    • 結合
    # 先看and再看or
    # v1 = 1 and 9 or 0 and 6
    # print(v1)
    • 優先級

      在沒有()的狀況下not 優先級高於 and,and優先級高於or,即優先級關係爲()>not>and>or,同一優先級從左往右計算。

2-5-8. 2.6.5 成員運算

​ in/ not in

2-5-9. 2.6.6 優先級

​ 算數>比較>賦值>邏輯(not>and>or)

2-5-10. 2.6.7 逗號運算符

  • a,b=b,a 交換兩個值
  • a,b=取值

2-6. 2.7 流程控制

2-6-1. 2.7.1 if語句

# 請實現一個功能:讓用戶輸入性別,若是是 男,則輸出:
再見;若是是 女:則輸出 來呀來呀;
gender = input("請輸入性別:")
""" 若是是男生:打印再見 不然:打印來呀來呀 """
if gender == "男":
print('再見')
else:
print('來呀來呀')

2-6-2. 2.7.2 elif 條件

# 請實現一個功能:讓用戶輸入性別,若是是 男,則輸出:
再見;若是是 女:則輸出 來呀來呀;若是是 人妖:找alex
去,他也是。不然:滾
gender = input("請輸入性別:")
""" 若是是男生:打印再見 不然:打印來呀來呀 """
if gender == "男":
print('再見')
elif gender == '女':
print('來來來')
elif gender == '人妖':
print('找alex去,他也是')
else:
print('滾')
print('end')
# 第一題:讓用戶輸入一個數字,猜:若是數字 > 50,則輸
出:大了; 若是數字 <= 50 ,則輸出:小了。
1
num = input('請輸入一個數字')
number = int(num)
if number > 50:
print('大了')
else:
print('小了')
# 第二題:用戶名密碼登錄
username = input('請輸入用戶名:')
password = input('請輸入密碼:')
if username == 'alex' and password ==
"oldboy" :
print('歡迎登錄')
else:
print('用戶名或密碼錯誤')

2-7. 2.8 循環語句

2-7-1. 2.8.1 格式

while 條件語句:
    執行語句
#打印1 2 3 4 5 6 8 9 10
""" count = 1 while count <= 10: if count != 7: print(count) count = count + 1"""
count = 1
while count <= 10:
    if count == 7:
        pass
    else:
        print(count)
    count = count + 1

2-7-2. 2.8.2 關鍵字break

做用:終止當前循環.

while True:
      print("你好")
      while True:
          print(666)
          break
      break

2-7-3. 2.8.2 關鍵字:continue

本次循環遇到continue,則再也不繼續往下走,返回條件語句繼續判斷.

count = 1
while count <=10:
print(count)
continue # 本次循環若是遇到continue,則不在繼續往下走,而是回到while條件位置。
count = count + 1
# 示例:1234568910
count = 1
while count <=10:
if count == 7:
count = count + 1
continue
print(count)
count = count + 1

2-7-4. 2.8.3 while else 結構

""" count = 1 while count < 10: print(count) count = count + 1 else: # 再也不知足while後的條件時,觸發。 或 條件=False print('ELSE代碼塊') print('結束') """
""" count = 1 while True: print(count) if count == 10: break count = count + 1 else: # 再也不知足while後的條件時,觸發。 或 條件=False print('ELSE代碼塊') print('結束') """

2-7-5. 2.9 三元運算(三目運算)

v =  前面  if 條件 else 後面 

if 條件:
    v = '前面'
else:
    v = '後面'
# 讓用戶輸入值,若是值是整數,則轉換成整數,不然賦值爲None

data = input('>>>')
value =  int(data) if data.isdecimal() else None

注意:先作出來,再思考如何簡化。

3. 第三章 數據類型

3-1. 3.1 整型(int)

from __future__ import division 
value = 3/2
print(value)
  • py2:有int和long,除法保留整數

  • py3只有int,結果保留全部

3-2. 3.2 布爾型(bool)

True
False
v1 = bool("hello")
v2 = bool("")
print(v1,v2)

轉布爾型False: None 0 "" [] {} () set{}

3-3. 3.3 字符串(str)

字符串是寫代碼中最多見的,python內存中的字符串是按照:unicode 編碼存儲。對於字符串是不可變。

  • 基本用法

  • 加法拼接

    a = '世界'
    b = '你好'
    print(a + b)
    # 結果:世界你好
  • 單引號雙引號三引號用法

    s = """yinhaiping簡寫爲'yhp'."""
    print(s)
    #運行結果:yinhaiping簡寫爲'yhp'.
  • 乘法屢次拼接鏈接

    a = '堅強'
    print(a * 8)
    結果:堅強堅強堅強堅強堅強堅強堅強堅強
  • 經常使用方法

  • .upper() / .lower(): 將字母轉換爲大/小寫

    n='yinhaiping'
    na=n.upper()
    name=na.lower()
    print(na,name)
    #運行結果:YINHAIPING yinhaiping
v = 'ALEX'
v1 = v.upper()
print(v1)
v2 = v.isupper() # 判斷是否所有是大寫
print(v2)
v = 'alex'
v1 = v.lower()
print(v1)
v2 = v.islower() # 判斷是否所有是小寫
print(v2)


############ 瞭解便可
v = 'ß'
# 將字符串變小寫(更牛逼)
v1 = v.casefold()
print(v1) # ss
v2 = v.lower()
print(v2)
  • .isdigit(): 判斷字符串是否是數字

    a='b'
    b="8"
    print(a.isdigit(),b.isdigit())
    #運行結果:False True
    v = 'alex'
    v1 = v.lower()
    print(v1)
    v2 = v.islower() # 判斷是否所有是小寫
    print(v2)
    
    
    ############ 瞭解便可
    v = 'ß'
    # 將字符串變小寫(更牛逼)
    v1 = v.casefold()
    print(v1) # ss
    v2 = v.lower()
    print(v2)
  • .strip() / .lstrip() / .rstrip():去除字符串兩端/左邊/右邊空格或換行

    a=" >>>>>>\n"
    a=a.strip()
    b="YHP"
    print(a,b)
    #運行結果:>>>>>> YHP
    v1 = "alex "
    print(v1.strip())
    
    v2 = "alex\t"
    print(v2.strip())
    
    v3 = "alex\n"
    print(v3.strip())
    
    v1 = "alexa"
    print(v1.strip('al'))
  • .split():將字符串按指定格式分割爲列表

    s="yinhaiping"
    b=s.split("i")
    print(b)
    運行結果:['y', 'nha', 'p', 'ng']
  • .replace("被替換的字符/子序列","要替換爲的內容",1):替換字符

    a="yinhaiping"
    b=a.replace(a[0:2],"YIN")
    c=a.replace("i","I",2)
    print(b,c)
    #運行結果:YINnhaiping yInhaIping
  • .startswith()/.endswith(): 判斷是否以指定字符開頭

    a="yinhaiping"
    print(a.startswith("yin"),a.endswith("gn"))
    #運行結果:True False
  • .jion():循環字符串每一個字符,按指定方式鏈接.例:"_".jion(str)

    a="yinhaiping"
    b="-".join(a)
    print(b)
    #運行結果:y-i-n-h-a-i-p-i-n-g
  • .format():格式化賦值例:"你好{}".format(s)

    a="你好{}".format("尹海平")
    print(a)
    #運行結果:你好尹海平
  • .encode():改變編碼格式保存

    a="尹海平"
    b=a.encode("gbk")
    c=b.decode("utf-8")
    print(a,b,c)
    #運行結果:尹海平 b'\xd2\xfc\xba\xa3\xc6\xbd' 尹海平

3-4. 3.4 列表(list)

  • 基本格式:["str",int,bool]

  • 特色:【有序,可變】

  • 經常使用方法

    • .append(): 在列表最後追加元素

      s=[1,2,3,"唱:","我愛北京"]
      s.append("天安門")
      print(s)
      #結果:[1, 2, 3, '唱:', '我愛北京', '天安門']
    • .insert(索引,"元素"): 在指定索引前加元素

      s=[1,2,3,"唱:","我愛北京天安門"]
      s.insert(3,"預備")
      print(s)
      #結果:[1, 2, 3, '預備', '唱:', '我愛北京天安門']
    • .remove("須要刪除的元素"): 直接刪除指定元素

      s=[1,2,3,"唱:","我愛北京天安門"]
      s.remove("唱:")
      print(s)
      #結果:[1, 2, 3, '我愛北京天安門']
    • .pop(索引): 刪除索引的元素 ,可返回所刪除元素值

      s=[1,2,3,"唱:","我愛北京天安門"]
      b=s.pop(3)
      print(s,b)
      #結果:[1, 2, 3, '我愛北京天安門'] 唱:
    • .clear(): 清空全部元素

      s=[1,2,3,"唱:","我愛北京天安門"]
      s.clear()
      print(s)
      #結果:[]
    • del:刪除帶索引的列表內容.例:del name[0]

      s=[1,2,3,"唱:","我愛北京天安門"]
      del s[4]
      print(s)
      #結果:[1, 2, 3, '唱:']
    • .reverse():把列表反轉

      s=[1,2,3,4,5]
      s.reverse()
      print(s)
      #結果:[5, 4, 3, 2, 1]
    • .sort(): 排序,默認升序.降序:sort(reverse=True)

      a=[5,8,6,99,81,]
      b=[5,8,6,99,81,]
      a.sort()
      b.sort(reverse=True)
      print(a,b)
      #結果:[5, 6, 8, 81, 99] [99, 81, 8, 6, 5]
    • .extend():批量追加另外一個序列(str,list,tuple,dict(鍵),set)每一個元素

      s = "qwert"
       li = ["alex", "WuSir", "ritian", "barry", "wenzhou"]
       li.extend(s)
       print(li) # 輸出:['alex', 'WuSir', 'ritian', 'barry', 'wenzhou', 'q', 'w', 'e', 'r', 't']

3-5. 3.5 元組(tuple)

  • 基本格式:("str",int,bool)

  • 特色:【有序,不可變】

  • 自有方法【無】

    注意:元素不可修改,嵌套的可變類型內元素可修改

3-6. 3.6 字典(dict)

  • 基本格式:{鍵:值,鍵,值...}

  • 特色:【鍵索引,可變】

  • 經常使用方法

    • .keys(): 獲取全部鍵

      info = { "name":"尹海平","age":"保密","address":"北京","work":"碼農" }
      info_keys = message.keys()
      for i in info_keys:
          print(i)
      #運行結果:
      name
      age
      address
      work
    • .values(): 獲取全部值

      info = { "name":"尹海平","age":"保密","address":"北京","work":"碼農" }
      info_values = info.values()
      for i in info_values:
          print(i)
      #運行結果:
      尹海平
      保密
      北京
      碼農
    • .items(): 獲取全部鍵值對

      info = { "name":"尹海平","age":"保密","address":"北京","work":"碼農" }
      info_items = info.items()
      for i in info_items:
          print(i)
      #運行結果:
      ('name', '尹海平')
      ('age', '保密')
      ('address', '北京')
      ('work', '碼農')
    • .get(鍵,返回值): 獲取鍵對應的值,默認返回None

      infos = { "name":"尹海平","age":"保密","address":"北京","work":"碼農" }
      info = infos.get("name")
      info1=infos.get("addrss","不存在")
      print(info,info1)
      #運行結果:
      尹海平 不存在
    • .pop(): 刪除指定鍵值對

      infos = { "name":"尹海平","age":"保密","address":"北京","work":"碼農" }
      name=infos.pop("name")
      print(infos)
      #運行結果:{'age': '保密', 'address': '北京', 'work': '碼農'}
    • .update(): 批量更新鍵值

      infos = { "name":"尹海平","age":"保密","address":"北京","work":"碼農" }
      info_new={"gender":"男","愛好":"女"}
      infos.update(info_new)
      print(infos)
      #運行結果:{'name': '尹海平', 'age': '保密', 'address': '北京', 'work': '碼農', 'gender': '男', '愛好': '女'}

注意:字典中鍵是無序的,必須是可哈希數據類型(list/dict/set不能作鍵)

有序字典

from collections import OrderedDict

info = OrderedDict()
info['k1'] = 123
info['k2'] = 456

print(info.keys())
print(info.values())
print(info.items())

3-7. 3.7 集合(set)

  • 基本格式:{str,int,bool,list...}空集合=set()

  • 特色:【無序,可變,不重複】

  • 經常使用方法

    • .add(): 添加元素

      heros={"金克斯","蓋倫","艾希"}
      heros.add("提莫")
      print(heros)
      #運行結果:{'提莫', '艾希', '蓋倫', '金克斯'}
    • .update(): 批量添加

      heros={"金克斯","蓋倫","艾希"}
      new_heros={"塔姆","艾克","劍聖"}
      heros.update(new_heros)
      print(heros)
      #運行結果:{'艾希', '蓋倫', '金克斯', '劍聖', '塔姆', '艾克'}
    • .discard(): 刪除指定元素

      heros={"金克斯","蓋倫","艾希"}
      heros.discard("蓋倫")
      print(heros)
      #運行結果:{'艾希', '金克斯'}
    • .intersection(): 取交集

      heros={"金克斯","蓋倫","艾希"}
      new_heros={"蓋倫","劍聖","艾希"}
      nb_heros=heros.intersection(new_heros)
      print(nb_heros)
      #運行結果:{'艾希', '蓋倫'}
    • .union(): 取並集

      heros={"金克斯","蓋倫","艾希"}
      new_heros={"蓋倫","劍聖","艾希"}
      all_heros=heros.union(new_heros)
      print(all_heros)
      #運行結果:{'艾希', '劍聖', '金克斯', '蓋倫'}
    • .difference(): 取差集

      heros={"金克斯","蓋倫","艾希"}
      new_heros={"蓋倫","劍聖","艾希"}
      dft_heros=heros.difference(new_heros)
      dft1_heros=new_heros.difference(heros)
      print(dft_heros,dft1_heros)
      #運行結果:{'金克斯'} {'劍聖'}
    • .symmetric_difference():取對等差分集合,返回兩個集合中不重複的元素集合

      heros={"金克斯","蓋倫","艾希"}
      new_heros={"蓋倫","劍聖","艾希"}
      sym_heros=heros.difference(new_heros)
      print(sym_heros)
      #運行結果:{'金克斯'}

3-8. 3.8 公共方法

  • len(): 返回元素個數

    可應用的數據類型有:str 字符串、list 列表、dict 字典、tuple 元組、set 集合

    heros={"金克斯","蓋倫","艾希"}
    num=len(heros)
    print(num)
    #y=運行結果:3
  • 索引[num]: 左閉右開,左→右從0開始,從右→左從-1開始

    可應用的數據類型有:str 字符串、list 列表、dict 字典、tuple 元組

    heros=["金克斯","蓋倫","艾希"]
    name=heros[1]
    name1=heros[-3]
    print(name,name1)
    #運行結果:蓋倫 金克斯
  • 切片[start:stop]: 左閉右開,反向加"-"

    可應用的數據類型有:str 字符串、list 列表、tuple 元組

    heros=["金克斯","蓋倫","艾希","提莫","趙信"]
    name=heros[-4:-1]
    print(name)
    #運行結果:['蓋倫', '艾希', '提莫']
  • 步長[start:stop:step]: 默認爲1,逆向取加"-"

    可應用的數據類型有:str 字符串、list 列表、tuple 元組

    heros=["金克斯","蓋倫","艾希","提莫","趙信"]
    name=heros[-1:-4:-2]
    print(name)
    #運行結果:['趙信', '艾希']
  • del: 刪除

    可應用的數據類型有:list 列表、dict 字典

    heros=["金克斯","蓋倫","艾希","提莫","趙信"]
    del heros[3]
    print(heros)
    #運行結果:['金克斯', '蓋倫', '艾希', '趙信']
  • .update(): 批量增長

    可應用的數據類型有:list 列表、dict 字典、set集合

    heros={"金克斯","蓋倫","艾希"}
    new_heros={"塔姆","艾克","劍聖"}
    heros.update(new_heros)
    print(heros)
    #運行結果:{'艾希', '蓋倫', '金克斯', '劍聖', '塔姆', '艾克'}

4. 第四章 文件操做

4-1. 4.1 文件基本操做

obj = open('路徑',mode='模式',encoding='編碼')
obj.write()
obj.read()
obj.close()

4-2. 4.2 打開模式

  • r / w / a
  • r+ / w+ / a+
  • rb / wb / ab
  • r+b / w+b / a+b

4-3. 4.3 操做

  • read() , 所有讀到內存

  • read(1)

    • 1表示一個字符

      obj = open('a.txt',mode='r',encoding='utf-8')
      data = obj.read(1) # 1個字符
      obj.close()
      print(data)
    • 1表示一個字節

      obj = open('a.txt',mode='rb')
      data = obj.read(3) # 1個字節
      obj.close()
  • write(字符串)

    obj = open('a.txt',mode='w',encoding='utf-8')
    obj.write('中午你')
    obj.close()
  • write(二進制)

    obj = open('a.txt',mode='wb')
    
    # obj.write('中午你'.encode('utf-8'))
    v = '中午你'.encode('utf-8')
    obj.write(v)
    
    obj.close()
  • seek(光標字節位置),不管模式是否帶b,都是按照字節進行處理。

    obj = open('a.txt',mode='r',encoding='utf-8')
    obj.seek(3) # 跳轉到指定字節位置
    data = obj.read()
    obj.close()
    
    print(data)
    
    obj = open('a.txt',mode='rb')
    obj.seek(3) # 跳轉到指定字節位置
    data = obj.read()
    obj.close()
    
    print(data)
  • tell(), 獲取光標當前所在的字節位置

    obj = open('a.txt',mode='rb')
    # obj.seek(3) # 跳轉到指定字節位置
    obj.read()
    data = obj.tell()
    print(data)
    obj.close()
  • flush,強制將內存中的數據寫入到硬盤

    v = open('a.txt',mode='a',encoding='utf-8')
    while True:
        val = input('請輸入:')
        v.write(val)
        v.flush()
    
    v.close()

4-4. 4.4 關閉文件

文藝青年

v = open('a.txt',mode='a',encoding='utf-8')

v.close()

二逼

with open('a.txt',mode='a',encoding='utf-8') as v:
    data = v.read()
    # 縮進中的代碼執行完畢後,自動關閉文件

4-5. 4.5 文件內容的修改

with open('a.txt',mode='r',encoding='utf-8') as f1:
    data = f1.read()
new_data = data.replace('飛灑','666')

with open('a.txt',mode='w',encoding='utf-8') as f1:
    data = f1.write(new_data)

大文件修改

f1 = open('a.txt',mode='r',encoding='utf-8')
f2 = open('b.txt',mode='w',encoding='utf-8')

for line in f1:
    new_line = line.replace('阿斯','死啊')
    f2.write(new_line)
f1.close()
f2.close()
with open('a.txt',mode='r',encoding='utf-8') as f1, open('c.txt',mode='w',encoding='utf-8') as f2:
    for line in f1:
        new_line = line.replace('阿斯', '死啊')
        f2.write(new_line)

5.

6. 第五章 函數

截至目前:面向過程編程。 【可讀性差/可重用性差】。

寫代碼的方式:面向過程 --> 函數式編程(多) --> 面向對象編程。

對於函數編程:

  • 本質:將N行代碼拿到別處並給他起個名字,之後經過名字就能夠找到這段代碼並執行。
  • 場景:
    • 代碼重複執行。
    • 代碼量特別多超過一屏,能夠選擇經過函數進行代碼的分割。

6-1. 5.1函數的基本結構

# 函數的定義
def 函數名():
    # 函數內容
    pass

# 函數的執行
函數名()
def get_list_first_data():
    v = [11,22,33,44]
    print(v[0])


get_list_first_data()

# 注意:函數若是不被調用,則內部代碼永遠不會被執行。
# 假如:管理員/業務員/老闆用的是同一個郵箱。
def send_email():
    print('發送郵件成功,假設有10含代碼')


user_input = input('請輸入角色:')

if user_input == '管理員':
    send_email()
elif user_input == '業務員':
    send_email()
elif user_input == '老闆':
    send_email()

6-2. 5.2 參數

6-2-1. 5.2.1參數格式與種類

  1. 函數能夠傳遞任意數據類型,任意個數的參數
def func(a1,a2,a3):# a1,a2,a3叫形式參數(形參)
    print(a1,a2,a3)
    
func(1,"asdf",True)#調用時傳遞的參數叫實際參數(實參)
  1. 位置傳參(調用函數語句)
def func(a1,a2):
    print(a1,a2)

    func(1,3)
  1. 關鍵字傳參(調用函數語句)
def func(a1, a2):
    print(a1, a2)

func(a2=99,a1=2)

# 關鍵字傳參數和位置傳參能夠混合使用,位置傳入的參數在前,關鍵字參數在後 
def func1(a1, a2, a3):
    print(a1, a2, a3)

# func(1, 2, a3=9)
# func(1, a2=2, a3=9)
# func(a1=1, a2=2, a3=9)
# func(a1=1, 2,3) # 錯誤
  1. 參數默認值

    編寫函數時,可給每一個形參指定默認值。在調用函數中給形參提供了實參時,Python將使用指定的實參值;不然,將使用形參的默認值。所以,給形參指定默認值後,可在函數調用中省略相應的實參。使用默認值可簡化函數調用,還可清楚地指出函數的典型用法。

    def func(a1,a2,a3=9,a4=10):
        print(a1,a2,a3,a4)
    
    func(11,22)
    func(11,22,10)
    func(11,22,10,100)
    func(11,22,10,a4=100)
    func(11,22,a3=10,a4=100)
    func(11,a2=22,a3=10,a4=100)
    func(a1=11,a2=22,a3=10,a4=100)

    函數的默認值慎用可變類型

    # 若是要想給value設置默認是空列表
    
    # 不推薦(坑)
    def func(data,value=[]): 
        pass 
    
    # 推薦
    def func(data,value=None):
        if not value:
            value = []
    def func(data,value=[]): 
        value.append(data)
        return value 
    
    v1 = func(1) # [1,]
    v2 = func(1,[11,22,33]) # [11,22,33,1]

    面試題:

    • def func(a,b=[]) 有什麼陷阱?

    • 看代碼寫結果

      def func(a,b=[]):
          b.append(a)
          return b
      
      l1 = func(1)
      l2 = func(2,[11,22])
      l3 = func(3)
      
      # [1,3] [11,22,2] [1,3]
      print(l1,l2,l3)
      def func(a,b=[]):
          b.append(a)
          print(b)
          
      func(1)
      func(2,[11,22,33])
      func(3)
      
      # [1] [11,22,33,2] [1,3]
  2. 萬能參數(打散)

    • *args

      • 能夠接受任意個數的位置參數,並將參數轉換成元組。

        • 調用函數無 *
        def func(*args):
            print(args)
        
        func(1,2,3,4)
        • 調用函數有 *

          循環列表的每一個元素傳入函數

        def func(*args):
            print(args)
        
        func(*(1,2,3,4))
        func(*[1,2,3,4])
    • 只能用位置傳參

      def func(*args):
          print(args)
      
      # func(1)
      # func(1,2)
      func(1,2) # args=(1, 2)
      func((11,22,33,44,55)) # args=((11,22,33,44,55),)
      func(*(11,22,33,44,55)) # args=(11,22,33,44,55)
    • **kwargs

      • 能夠接受任意個數的關鍵字參數,並將參數轉換成字典。

        • 調用函數無 **

          def func(**kwargs):
              print(kwargs)
          
          
          func(k1=1,k2="alex")
        • 調用函數有**

          循環字典的每一個鍵值對傳入函數

          def func(**kwargs):
              print(kwargs)
          func(**{'k1':'v2','k2':'v2'}) # kwargs={'k1':'v2','k2':'v2'}
      • 只能用關鍵字傳參

      • 綜合應用:無敵 + 無敵 => 真無敵

        def func(*args,**kwargs):
            print(args,kwargs)
        
        # func(1,2,3,4,5,k1=2,k5=9,k19=999)
        func(*[1,2,3],k1=2,k5=9,k19=999)
        func(*[1,2,3],**{'k1':1,'k2':3})
        func(111,222,*[1,2,3],k11='alex',**{'k1':1,'k2':3})

    參數相關重點:

    1. 定義函數
    def func1(a1,a2):
        pass 
    
    def func2(a1,a2=None):
        pass 
    
    def func3(*args,**kwargs):
        pass
    1. 調用函數
      位置參數 > 關鍵字參數

6-2-2. 5.2.2 做用域

python中:

  • py文件:全局做用域
  • 函數:局部做用域
a = 1
def s1():   #注意:在調用以前選擇參數值究竟是多少. 
    x1 = 666
    print(x1)
    print(a)
    print(b)
b = 2
print(a) #1
s1()	#666\n 1\n2
a = 88888
def s2():
    print(a,b) 
    s1()		
s2()	 #88888 2 #666\n 88888\n2

總結:

  • 一個函數是一個做用域

    def func():
        x = 9
        print(x)
    func()
    print(x)
  • 做用域中查找數據規則:優先在本身的做用域找數據,本身沒有就去 "父級" -> "父級" -> 直到全局,所有麼有就報錯。注意:父級做用域中的值究竟是什麼?

    x = 10
    def func():
        x = 9
        print(x)
    
    func()

    注意:函數參數取決於調用時的參數值而不是定義時的值

  • 子做用域中只能 找到父級中的值 ,默認沒法從新爲父級的變量進行賦值。(global/nonlocal能夠強制作)

    # #####################
    name = 'oldboy'
    def func():
        name = 'alex' # 在本身做用域再建立一個這樣的值。
        print(name)
    func()
    print(name)
    
    
    
    # #####################
    name = [1,2,43]
    def func():
        name.append(999)
        print(name)
    func()
    print(name)
    
    # ###################### 若是非要對全局的變量進行賦值
    # 示例一
    name = ["老男孩",'alex']
    def func():
        global name
        name = '我'
    func()
    print(name)
    # 示例一
    name = "老男孩"
    def func():
        name = 'alex'
        def inner():
            global name
            name = 999
        inner()
        print(name)
    func()
    print(name)
    
    
    name = "老男孩"
    def func():
        name = 'alex'
        def inner():
            global name
            name = 999
        inner()
        print(name)
    func()
    print(name)
    
    # ############################## nonlocal
    name = "老男孩"
    def func():
        name = 'alex'
        def inner():
            nonlocal name # 找到上一級的name
            name = 999
        inner()
        print(name)
    func()
    print(name)

練習題

# 1. 請寫一個函數,函數計算列表 info = [11,22,33,44,55] 中全部元素的和。

def get_sum():
    info = [11,22,33,44,55]
    data = 0
    for item in info:
        data += item
    print(data)

get_sum()

# 2. 請寫一個函數,函數計算列表中全部元素的和。

def get_list_sum(a1):
   	data = 0
    for item in a1:
        data += item
   	print(data)
    
get_list_sum([11,22,33])
get_list_sum([99,77,66])
v1 = [8712,123,123]
get_list_sum(v1)

# 3. 請寫一個函數,函數將兩個列表拼接起來。
def join_list(a1,a2):
    result = []
    result.extend(a1)
    result.extend(a2)
    print(result)
    
join_list([11,22,33],[55,66,77]

# 4. 計算一個列表的長度
def my_len(arg):
    count = 0
    for item in arg:
          count += 1
    print(count)

v = [11,22,33]
my_len(v)
len(v)

# 5. 發郵件的示例
          
def send_email(role,to):
    template = "要給%s%s發送郵件" %(role,to,)
    print(template)
 

user_input = input('請輸入角色:')

if user_input == '管理員':
    send_email('管理員','xxxx@qq.com')
elif user_input == '業務員':
    send_email('業務員','xxxxo@qq.com')
elif user_input == '老闆':
    send_email('老闆','xoxox@qq.com')

6-3. 5.3 返回值

def func(arg):
    # ....
    return 9 # 返回值爲9 默認:return None

val = func('adsfadsf')
# 1. 讓用戶輸入一段字符串,計算字符串中有多少A字符的個數。有多少個就在文件a.txt中寫多少個「李邵奇」。

def get_char_count(data):
    sum_counter = 0
    for i in data:
        if i == 'A':
            sum_counter += 1
            
    return sum_counter

def write_file(line):
    if len(line) == 0:
        return False  # 函數執行過程當中,一旦遇到return,則中止函數的執行。
    with open('a.txt',mode='w',encoding='utf-8') as f:
        f.write(line)
    return True 


content = input('請輸入:')
counter = get_char_count(content)
write_data = "李邵奇" * counter 
status = write_file(write_data)
if status:
    print('寫入成功')
else:
    print('寫入失敗')

6-4. 5.4 上述總結

# 狀況1
def f1():
    pass 
f1()

# 狀況2
def f2(a1):
    pass 
f2(123)

# 狀況3
def f3():
    return 1 
v1 = f3()

# 狀況4
def f4(a1,a2):
    # ... 
    return 999
v2 = f4(1,7)

6-5. 5.5 練習題

# 1. 寫函數,計算一個列表中有多少個數字,打印: 列表中有%s個數字。
# 提示:type('x') == int 判斷是不是數字。
""" # 方式一: def get_list_counter1(data_list): count = 0 for item in data_list: if type(item) == int: count += 1 msg = "列表中有%s個數字" %(count,) print(msg) get_list_counter1([1,22,3,'alex',8]) # 方式二: def get_list_counter2(data_list): count = 0 for item in data_list: if type(item) == int: count += 1 return count v = get_list_counter1([1,22,3,'alex',8]) msg = "列表中有%s個數字" %(v,) print(msg) """

# 2. 寫函數,計算一個列表中偶數索引位置的數據構形成另一個列表,並返回。
""" # 方式一: def get_data_list1(arg): v = arg[::2] return v data = get_data_list1([11,22,33,44,55,66]) # 方式二: def get_data_list2(arg): v = [] for i in range(0,len(arg)): if i % 2 == 0: v.append(arg[i]) return v data = get_data_list2([11,22,33,44,55,66]) """

# 3. 讀取文件,將文件的內容構形成指定格式的數據,並返回。
""" a.log文件 alex|123|18 eric|uiuf|19 ... 目標結構: a. ["alex|123|18","eric|uiuf|19"] 並返回。 b. [['alex','123','18'],['eric','uiuf','19']] c. [ {'name':'alex','pwd':'123','age':'18'}, {'name':'eric','pwd':'uiuf','age':'19'}, ] """
def lst(f):
    a = []
    for line in f:
        new_line = line.strip()
        a.append(new_line)
    return a


def list_lst(f):
    b = []
    f.seek(0)
    for line in f:
        new_line = line.strip()
        li = new_line.split("|")
        b.append(li)
    return b


def dit(f):
    c = []
    f.seek(0)
    for line in f:
        dic = {}
        new_line = line.strip()
        li = new_line.split("|")
        dic["name"] = li[0]
        dic["pwd"] = li[1]
        dic["age"] = li[2]
        c.append(dic)
    return c


with open('a.txt', mode='r', encoding='utf-8') as f:
    a = lst(f)
    b = list_lst(f)
    c = dit(f)
    print(a, "\n", b, "\n", c)

6-6. 5.6 函數變量

函數自己也是一種數據類型,函數名對應程序入口地址

6-6-1. 5.6.1 函數名看成變量來使用

def func():
    print(123) 
v1 = func #函數名能夠賦值給其餘變量,來指向函數
func()
v1()     #函數加()纔會執行
#123 
#123
def func():
    print(123)
    
func_list = [func, func, func]
for item in func_list:
    v = item()
    print(v)

6-6-2. 5.6.2 函數能夠看成參數進行傳遞

def func(arg):
    v1 = arg()
    print(v1)

def show():
    print(666)

func(show)
#666
#None
def func(arg):
    v1 = arg()
    print(v1)
    
def show():
    print(666)
    
result = func(show)
print(result)
# 面試題

def func():
    print('花費查詢')


def bar():
    print('語音溝通')


def base():
    print('xxx')


def show():
    print('xxx')


def test():
    print('xxx')

info = {
    'f1': func,
    'f2': bar,
    'f3':base,
    'f4':show,
    'f5':test
}
choice = input('請選擇要選擇功能:')
function_name = info.get(choice)
if function_name:
    function_name()
else:
    print('輸入錯誤')

6-6-3. 5.6.3 函數能夠作返回值

函數被調用,開闢一塊內存空間執行,同時被調用開闢不一樣的內存空間,之間不會混亂,執行完畢後釋放內存.

def func():
    print(123)
def bar():
    return func
v = bar()
v()
name = 'oldboy'
def func():
    print(name)  
def bar():
    return func
v = bar()
v()
name = 'oldboy'
def bar(name):
    def inner():
        print(name)
    return inner
v1 = bar('alex') # { name=alex, inner } # 閉包,爲函數建立一塊區域(內部變量供本身使用),爲他之後執行提供數據。
v2 = bar('eric') # { name=eric, inner }
v1()
v2()

6-6-4. 5.6.4 閉包

閉包概念:爲函數建立一塊區域併爲其維護本身數據,之後執行時方便調用。【應用場景:裝飾器 / SQLAlchemy源碼】

def func(name):
    def inner():
        print(name)
    return inner 

v1 = func('alex')
v1()
v2 = func('eric')
v2()
info = []

def func(i):
    def inner():
        print(i)
    return inner

for item in range(10):
    info.append(func(item))

info[0]()
info[1]()
info[4]()
def x(func):
    def inner(a1,a2):
        return func()
    return inner 

@x
def index():
    pass
# func = 原來的index函數u
# index = inner
index(1,2)
  • 關於返回值
def x1(func):
    def inner(*args,**kwargs):
        data = func(*args,**kwargs)
        return data
    return inner 

@x1
def f1():
    print(123)
    return 666
v1 = f1()
print(v1)
def x1(func):
    def inner(*args,**kwargs):
        data = func(*args,**kwargs)
    return inner 

@x1
def f1():
    print(123)
    return 666

v1 = f1()
print(v1)
  • 關於先後

    def x1(func):
        def inner(*args,**kwargs):
            print('調用原函數以前')
            data = func(*args,**kwargs) # 執行原函數並獲取返回值
            print('調用員函數以後')
            return data
        return inner 
    
    @x1
    def index():
        print(123)
        
    index()
  • 帶參數的裝飾器(flask框架 + django緩存 + 寫裝飾器實現被裝飾的函數要執行N次)

    # 第一步:執行 ret = xxx(index)
    # 第二步:將返回值賦值給 index = ret 
    @xxx
    def index():
        pass
    
    # 第一步:執行 v1 = uuu(9)
    # 第二步:ret = v1(index)
    # 第三步:index = ret 
    @uuu(9)
    def index():
        pass
    # 寫一個帶參數的裝飾器,實現:參數是多少,被裝飾的函數就要執行多少次,把每次結果添加到列表中,最終返回列表。
    def xxx(counter):
        print('x函數')
        def wrapper(func):
            print('wrapper函數')
            def inner(*args,**kwargs):
                v = []
                for i in range(counter):
                    data = func(*args,**kwargs) # 執行原函數並獲取返回值
                    v.append(data)
                return v
            return inner
        return wrapper
    
    @xxx(5)
    def index():
        return 8
    
    v = index()
    print(v)

6-7. 5.7 lambda表達式

用於表示簡單的函數,也稱做匿名函數。

# 三元運算,爲了解決簡單的if else的狀況,如:
if 1 == 1:
    a = 123
else:
    a = 456

a =  123  if 1 == 1 else 456

# lambda表達式,爲了解決簡單函數的狀況,如:
def func(a1,a2):
    return a1 + 100 

func = lambda a1,a2: a1+100
func1 = lambda : 100 

func2 = lambda x1: x1 * 10

func3 = lambda *args,**kwargs: len(args) + len(kwargs)

總結:列表全部方法基本上都是返回None;字符串的全部方法基本上都是返回新值

6-8. 5.8 內置函數

  • 輸入輸出

    • print
    • input
  • 強制轉換

    • int()
    • bool()
    • list()
    • str()
    • tuple()
    • dict()
    • set()
  • 數學相關

    • abs() 絕對值

    • float() 轉換成浮點數

    • max() 找到最大值

    • min() 找到最小值

    • sum() 求和

    • pow() 乘方

      v = pow(2,3)
      print(v)# 2的3次方
    • round

      v = round(1.127,2)
      print(v)  #四捨五入保留幾位小數
    • divmod() 兩數相除的商和餘數

      a,b = divmod(1001,5)
      print(a,b)
      # 練習題 請經過分頁對數據進行展現
      """ 要求: 每頁顯示10條數據 讓用戶輸入要查看的頁面:頁碼 """
      
      USER_LIST = []
      for i in range(1,836):
          temp = {'name':'你少妻-%s' %i,'email':'123%s@qq.com' %i }
          USER_LIST.append(temp)
      
      # 數據總條數
      total_count = len(USER_LIST)
      
      # 每頁顯示10條
      per_page_count= 10
      
      # 總頁碼數
      max_page_num,a = divmod(total_count,per_page_count)
      if a>0:
          max_page_num += 1
      
      while True:
          pager = int(input('要查看第幾頁:'))
          if pager < 1 or pager > max_page_num:
              print('頁碼不合法,必須是 1 ~ %s' %max_page_num )
          else:
              """ # 第1頁:USER_LIST[0:10] -> 0123456789 # 第2頁:USER_LIST[10:20] # 第3頁:USER_LIST[20:30] ... """
              start = (pager-1) * per_page_count
              end = pager * per_page_count
              data = USER_LIST[start:end]
              for item in data:
                  print(item)
  • 進制轉換相關

    • bin,將十進制轉化成二進制

      num = 13
      v1 = bin(num)
      print(v1)
    • oct,將十進制轉換成八進制

      num = 8
      v1 = oct(num)
      print(v1)
    • int,將其餘進制轉化成十進制

      # 二進制轉化成十進制
      v1 = '0b1101'
      result = int(v1,base=2)
      print(result)
      
      # 八進制轉化成十進制
      v1 = '0o1101'
      result = int(v1,base=8)
      print(result)
      
      # 十六進制轉化成十進制
      v1 = '0x1101'
      result = int(v1,base=16)
      print(result)
    • hex,將十進制轉換成十六進制

      num = 16
      v1 = hex(num)
      print(v1)
    • 面試題

      # 1字節等於8位
      # IP: 192.168.12.79 -> 001010010 . 001010010 . 001010010 . 001010010
      
      # 1. 請將 ip = "192.168.12.79" 中的每一個十進制數轉換成二進制並經過,鏈接起來生成一個新的字符串。
      ip = "192.168.12.79"
      ip_list = ip.split('.') # ['192','168','12','79']
      result = []
      for item in ip_list:
          result.append(bin(int(item)))
      print(','.join(result))
      
      
      # 2. 請將 ip = "192.168.12.79" 中的每一個十進制數轉換成二進制: 
      # 0010100100001010010001010010001010010 -> 十進制的值。
      
      # 3232238671
      ip='192.168.12.79'
      bit_str=''
      ip_list=ip.split(".")
      for i in ip_list:
          bit=bin(int(i))[2:]
          long=len(bit)
          if long<8:
              bit=(8-long)*"0"+bit
          bit_str+=''.join(bit)
      num=int(bit_str,base=2)
      print(num)
  • 編碼相關

    • chr,將十進制數字轉換成 unicode 編碼中的對應字符串。

      v = chr(99)
      print(v)
    • ord,根據字符在unicode編碼中找到其對應的十進制。

      num = ord('中')
    • 應用:random模塊

      import random
      
      def get_random_code(length=6):
          data = []
          for i in range(length):
              v = random.randint(65,90)
              data.append(chr(v))
      
          return  ''.join(data)
      
      
      code = get_random_code()
      print(code)
      import random # 導入一個模塊 
      
      v = random.randint(起始,終止) # 獲得一個隨機數
  • 高級一點的內置函數

    • map,循環每一個元素(第二個參數),而後讓每一個元素執行函數(第一個參數),將每一個函數執行的結果保存到新的列表中,並返回。map(批量操做函數,序列)

      v1 = [11,22,33,44]
      result = map(lambda x:x+100,v1)
      print(list(result)) # 特殊
    • filter filter(判斷條件,序列)

      v1 = [11,22,33,'asd',44,'xf']
      
      def func(x):
          if type(x) == int:
              return True
          return False
      result = filter(func,v1) # [11,]
      print(list(result))
      
      
      result = filter(lambda x: True if type(x) == int else False ,v1)
      print(list(result))
      
      result = filter(lambda x: type(x) == int ,v1)
      print(list(result))
    • reduce

      import functools
      v1 = ['wo','hao','e']
      
      def func(x,y):
          return x+y
      result = functools.reduce(func,v1) 
      print(result)
      
      result = functools.reduce(lambda x,y:x+y,v1)
      print(result)

6-9. 5.10 裝飾器

裝飾器:在不改變原函數內部代碼的基礎上,在函數執行以前和以後自動執行某個功能。

def func(arg):
    def inner():
        v = arg()
        return v 
    return inner 

# 第一步:執行func函數並將下面的函數參數傳遞,至關於:func(index)
# 第二步:將func的返回值從新賦值給下面的函數名。 index = func(index)
@func 
def index():
    print(123)
    return 666

print(index)
# ################## 普通裝飾器 #####################
def wrapper(func):
    def inner(*args,**kwargs):
        print('調用原函數以前')
        data = func(*args,**kwargs) # 執行原函數並獲取返回值
        print('調用員函數以後')
        return data
    return inner 

@wrapper
def index():
    pass

# ################## 帶參數裝飾器 #####################
def x(counter):
    def wrapper(func):
        def inner(*args,**kwargs):
            data = func(*args,**kwargs) # 執行原函數並獲取返回值
            return data
        return inner 
    return wrapper 

@x(9)
def index():
    pass

編寫裝飾器 和應用

# 裝飾器的編寫
def x(func):
    def y():
        # 前
        ret = func()
        # 後
        return ret 
   	return y 

# 裝飾器的應用
@x
def index():
    return 10

@x
def manage():
    pass

# 執行函數,自動觸發裝飾器了
v = index()
print(v)
  • 應用場景:想要爲函數擴展功能時,能夠選擇用裝飾器。

  • 記住:

    • 裝飾器建議編寫格式

      def 外層函數(參數): 
          def 內層函數(*args,**kwargs):
              return 參數(*args,**kwargs)
          return 內層函數
    • 裝飾器應用格式

      @外層函數
      def index():
          pass
      
      index()
    • 問題:爲何要加 *args, **kwargs

6-10. 5.11 迭代器

本身不會寫迭代器,只用。

任務:請展現列表中全部的數據。

  • while + 索引 + 計數器

  • 迭代器,對 某種對象(str/list/tuple/dict/set類建立的對象)-可迭代對象 中的元素進行逐一獲取,表象:具備__next__方法且每次調用都獲取可迭代對象中的元素(從前到後一個一個獲取)。

    • 列表轉換成迭代器:

      • v1 = iter([11,22,33,44])
      • v1 = [11,22,33,44].__iter__()
    • 迭代器想要獲取每一個值:反覆調用 val = v1.__next__()

      v1 = [11,22,33,44]
      
      # 列表轉換成迭代器
      v2 = iter(v1)
      result1 = v2.__next__()
      print(result1)
      result2 = v2.__next__()
      print(result2)
      result3 = v2.__next__()
      print(result3)
      result4 = v2.__next__()
      print(result4)
      result5 = v2.__next__()
      print(result5)
      """
      # v1 = "alex"
      # v2 = iter(v1)
      # while True:
      #     try:
      #         val = v2.__next__()
      #         print(val)
      #     except Exception as e:
      #         break
    • 直到報錯:StopIteration錯誤,表示已經迭代完畢。

    • 如何判別一個對象是不是迭代器:內部是否有__next__方法

  • for循環

    v1 = [11,22,33,44]
    
    # 1.內部會將v1轉換成迭代器
    # 2.內部反覆執行 迭代器.__next__()
    # 3.取完不報錯
    for item in v1:
        print(item)
  • 可迭代對象

    • 內部具備 __iter__() 方法且返回一個迭代器。(*)
    v1 = [11,22,33,44]
    result = v1.__iter__()
    • 能夠被for循環

6-11. 5.12 生成器(函數的變異)

# 函數
def func():
    return 123
func()
# 生成器函數(內部是否包含yield)
def func():
    print('F1')
    yield 1
    print('F2')
    yield 2
    print('F3')
    yield 100
    print('F4')
# 函數內部代碼不會執行,返回一個 生成器對象 。
v1 = func()
# 生成器是能夠被for循環,一旦開始循環那麼函數內部代碼就會開始執行。
for item in v1:
    print(item)
def func():
    count = 1
    while True:
        yield count
        count += 1
        
val = func()

for item in val:
    print(item)

總結:函數中若是存在yield,那麼該函數就是一個生成器函數,調用生成器函數會返回一個生成器,生成器只有被for循環時,生成器函數內部的代碼纔會執行,每次循環都會獲取yield返回的值。

def func():
    count = 1
    while True:
        yield count
        count += 1
        if count == 100:
            return

val = func()
for item in val:
    print(item)

示例:讀文件

def func():
    """
    分批去讀取文件中的內容,將文件的內容返回給調用者。
    :return:
    """
    cursor = 0
    while True:
        f = open('db', 'r', encoding='utf-8')# 經過網絡鏈接上redis
        # 代指   redis[0:10]
        f.seek(cursor)
        data_list =[]
        for i in range(10):
            line = f.readline()
            if not line:
                return
            data_list.append(line)
        cursor = f.tell()
        f.close()  # 關閉與redis的鏈接


        for row in data_list:
            yield row


for item in func():
    print(item)

其餘知識:

  • yeild from關鍵字【欠】
  • 生成器推導式【欠】

6-12. 5.13 推導式

  • 列表推導式

    """ 目的:方便的生成一個列表。 格式: v1 = [i for i in 可迭代對象 ] v2 = [i for i in 可迭代對象 if 條件 ] # 條件爲true才進行append """
    v1 = [ i for i in 'alex' ]  
    v2 = [i+100 for i in range(10)]
    v3 = [99 if i>5 else 66  for i in range(10)]
    
    def func():
        return 100
    v4 = [func for i in range(10)]
    
    v5 = [lambda : 100 for i in range(10)]
    result = v5[9]()
    
    def func():
        return i
    v6 = [func for i in range(10)]
    result = v6[5]()
    
    v7 = [lambda :i for i in range(10)]
    result = v7[5]()
    
    
    v8 = [lambda x:x*i for i in range(10)] # 新浪微博面試題
    # 1.請問 v8 是什麼?
    # 2.請問 v8[0](2) 的結果是什麼?
    
    # 面試題
    def num():
        return [lambda x:i*x for i in range(4)]
    # num() -> [函數,函數,函數,函數]
    print([ m(2) for m in num() ]) # [6,6,6,6]
    
    # ##################### 篩選 #########################
    v9 = [i for i in range(10) if i > 5]
  • 集合推導式

    v1 = { i for i in 'alex' }

    注意:重複值會被覆蓋

  • 字典推導式

    v1 = { 'k'+str(i):i for i in range(10) }

    注意:鍵值重複會被覆蓋

6-13. 5.14 遞歸

函數本身調用本身。(效率低)

def func():
    print(1)
    func()
    
func()
def func(a,b): 
    print(b) 
    func(b,a+b)
    
func(0,1) #1 1 2 3 5
def func(a):
    if a == 5:
        return 100000		# 注意遞歸的返回值
    result = func(a+1) + 10
    return result 

v = func(1) #100040

7. 第六章 模塊(類庫)

模塊分類

  1. 內置模塊-----python內部提供的功能

  2. 第三方模塊-----下載/安裝/使用

    # 把pip.exe 所在的目錄添加到環境變量中。
    
    pip install 要安裝的模塊名稱  # pip install xlrd
    #報錯更新
    python36  -m pip install --upgrade pip
  3. 自定義模塊

7-1. 6.1 內置模塊

7-1-1. 6.1.1 sys

python解釋器相關的數據。

  • sys.getrefcount , 獲取一個值的引用計數

    a = [11,22,33]
    b = a
    print(sys.getrefcount(a))
  • sys.getrecursionlimit , python默認支持的遞歸數量

  • sys.stdout.write --> print

    import time
    for i in range(1,101):
        msg = "%s%%\r" %i
        print(msg,end='')
        time.sleep(0.05)
    import os
    
    # 1. 讀取文件大小(字節)
    file_size = os.stat('20190409_192149.mp4').st_size
    
    # 2.一點一點的讀取文件
    read_size = 0
    with open('20190409_192149.mp4',mode='rb') as f1,open('a.mp4',mode='wb') as f2:
        while read_size < file_size:
            chunk = f1.read(1024) # 每次最多去讀取1024字節
            f2.write(chunk)
            read_size += len(chunk)
            val = int(read_size / file_size * 100)
            print('%s%%\r' %val ,end='')
  • sys.argv(經常使用)

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    """
    讓用戶執行腳本傳入要刪除的文件路徑,在內部幫助將目錄刪除。
    C:\Python36\python36.exe D:/code/s21day14/7.模塊傳參.py D:/test
    C:\Python36\python36.exe D:/code/s21day14/7.模塊傳參.py
    
    """
    import sys
    
    # 獲取用戶執行腳本時,傳入的參數。
    # C:\Python36\python36.exe D:/code/s21day14/7.模塊傳參.py D:/test
    # sys.argv = [D:/code/s21day14/7.模塊傳參.py, D:/test]
    path = sys.argv[1]
    
    # 刪除目錄
    import shutil
    shutil.rmtree(path)
  • sys.path ---默認Python去導入模塊時,會按照sys.path中的路徑挨個查找。

    # import sys
    # sys.path.append('D:\\')
    # import oldboy
  • sys.exit(0)退出程序

7-1-2. 6.1.2 os

和操做系統相關的數據。

  • os.path.exists(path) , 若是path存在,返回True;若是path不存在,返回False

  • os.stat('20190409_192149.mp4').st_size , 獲取文件大小

  • os.path.abspath() , 獲取一個文件的絕對路徑

    path = '20190409_192149.mp4' # D:\code\s21day14\20190409_192149.mp4
    
    import os
    v1 = os.path.abspath(path)
    print(v1)
  • os.path.dirname ,獲取路徑的上級目錄

    import os
    v = r"D:\code\s21day14\20190409_192149.mp4"
    
    print(os.path.dirname(v))
  • os.path.join ,路徑的拼接

    import os
    path = "D:\code\s21day14" # user/index/inx/fasd/
    v = 'n.txt'
    
    result = os.path.join(path,v)
    print(result)
    result = os.path.join(path,'n1','n2','n3')
    print(result)
  • os.listdir , 查看一個目錄下全部的文件【第一層】

    import os
    
    result = os.listdir(r'D:\code\s21day14')
    for path in result:
        print(path)
  • os.walk , 查看一個目錄下全部的文件【全部層】

    import os
    
    result = os.walk(r'D:\code\s21day14')
    for a,b,c in result:
        # a,正在查看的目錄 b,此目錄下的文件夾  c,此目錄下的文件
        for item in c:
            path = os.path.join(a,item)
            print(path)
  • os.makedirs,建立目錄和子目錄

    import os
    file_path = r'db\xx\xo\xxxxx.txt'
    
    file_folder = os.path.dirname(file_path)
    if not os.path.exists(file_folder):
        os.makedirs(file_folder)
    
    with open(file_path,mode='w',encoding='utf-8') as f:
        f.write('asdf')
  • os.rename,重命名

    import os
    os.rename('db','sb')
  • 補充:

    • 轉義

      v1 = r"D:\code\s21day14\n1.mp4"  (推薦)
      print(v1)
      
      v2 = "D:\\code\\s21day14\\n1.mp4"
      print(v2)

7-1-3. 6.1.3 shutil

import shutil

# 刪除目錄
# shutil.rmtree('test')

# 重命名
# shutil.move('test','ttt')

# 壓縮文件
# shutil.make_archive('zzh','zip','D:\code\s21day16\lizhong')

# 解壓文件
# shutil.unpack_archive('zzh.zip',extract_dir=r'D:\code\xxxxxx\xxxx',format='zip')

實例

import os
import shutil
from datetime import datetime
ctime = datetime.now().strftime('%Y-%m-%d-%H-%M-%S')

# 1.壓縮lizhongwei文件夾 zip
# 2.放到到 code 目錄(默認不存在)
# 3.將文件解壓到D:\x1目錄中。

if not os.path.exists('code'):
    os.makedirs('code')
shutil.make_archive(os.path.join('code',ctime),'zip','D:\code\s21day16\lizhongwei')

file_path = os.path.join('code',ctime) + '.zip'
shutil.unpack_archive(file_path,r'D:\x1','zip')

7-1-4. 6.1.4 json★

json是一個特殊的字符串。 【長的像列表/字典/字符串/數字/真假】

  • dumps序列化 & load反序列化
import json
# 序列化,將python的值轉換爲json格式的字符串。
# v = [12,3,4,{'k1':'v1'},True,'asdf']
# v1 = json.dumps(v)
# print(v1)

# 反序列化,將json格式的字符串轉換成python的數據類型
# v2 = '["alex",123]'
# print(type(v2))
# v3 = json.loads(v2)
# print(v3,type(v3))
  • json.dumps 序列化時對中文默認使用的ascii編碼.想輸出真正的中文須要指定ensure_ascii=False:

    v = {'k1':'alex','k2':'李傑'}
    
    import json
    val = json.dumps(v,ensure_ascii=False)
    print(val)
  • dump序列化並寫入文件

    import json
    
    v = {'k1':'alex','k2':'李傑'}
    
    f = open('x.txt',mode='w',encoding='utf-8')
    val = json.dump(v,f)
    print(val)
    f.close()
  • load從文件讀取並反序列化

    import json
    
    v = {'k1':'alex','k2':'李傑'}
    
    f = open('x.txt',mode='r',encoding='utf-8')
    
    data = json.load(f)
    f.close()
    
    print(data,type(data)
Python JSON
dict object
list, tuple array
str string
int, float number
True true
False false
None null

7-1-5. 6.1.5 pickle

  • json,優勢:全部語言通用;缺點:只能序列化基本的數據類型 list/dict/int...

  • pickle,優勢:python中全部的東西都能被他序列化(socket對象);缺點:序列化的內容只有python認識。

    import pickle
    
    # #################### dumps/loads ######################
    """ v = {1,2,3,4} val = pickle.dumps(v) print(val) data = pickle.loads(val) print(data,type(data)) """
    
    """ def f1(): print('f1') v1 = pickle.dumps(f1) print(v1) v2 = pickle.loads(v1) v2() """
    
    # #################### dump/load ######################
    # v = {1,2,3,4}
    # f = open('x.txt',mode='wb')
    # val = pickle.dump(v,f)
    # f.close()
    
    # f = open('x.txt',mode='rb')
    # data = pickle.load(f)
    # f.close()
    # print(data)

7-1-6. 6.1.6 time&datetime

UTC/GMT:世界時間

本地時間:本地時區的時間。

  • time模塊

    • time.time() ,時間戳:1970-1-1 00:00
    • time.sleep(10),等待秒數。
    • time.timezone
  • datetime模塊

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import time
    from datetime import datetime,timezone,timedelta
    
    # ######################## 獲取datetime格式時間 ##############################
    """ v1 = datetime.now() # 當前本地時間 print(v1) tz = timezone(timedelta(hours=7)) # 當前東7區時間 v2 = datetime.now(tz) print(v2) v3 = datetime.utcnow() # 當前UTC時間 print(v3) """
    
    # ######################## 把datetime格式轉換成字符串 ##############################
    # v1 = datetime.now()
    # print(v1,type(v1))
    # val = v1.strftime("%Y-%m-%d %H:%M:%S")
    # print(val)
    
    # ######################## 字符串轉成datetime ##############################
    # v1 = datetime.strptime('2011-11-11','%Y-%m-%d')
    # print(v1,type(v1))
    
    # ######################## datetime時間的加減 ##############################
    # v1 = datetime.strptime('2011-11-11','%Y-%m-%d')
    # v2 = v1 - timedelta(days=140)
    # date = v2.strftime('%Y-%m-%d')
    # print(date)
    
    # ######################## 時間戳和datetime關係 ##############################
    # ctime = time.time()
    # print(ctime)
    # v1 = datetime.fromtimestamp(ctime)
    # print(v1)
    
    # v1 = datetime.now()
    # val = v1.timestamp()
    # print(val)

7-1-7. 6.1.7 hashlib

  • 將指定的 「字符串」 進行加密。
import hashlib

def get_md5(data):
    obj = hashlib.md5()
    obj.update(data.encode('utf-8'))
    result = obj.hexdigest()
    return result

val = get_md5('123')
print(val)

​ 加嚴

import hashlib

def get_md5(data):
    obj = hashlib.md5("sidrsicxwersdfsaersdfsdfresdy54436jgfdsjdxff123ad".encode('utf-8'))
    obj.update(data.encode('utf-8'))
    result = obj.hexdigest()
    return result

val = get_md5('123')
print(val)

應用:

import hashlib
USER_LIST = []
def get_md5(data):
    obj = hashlib.md5("12:;idrsicxwersdfsaersdfsdfresdy54436jgfdsjdxff123ad".encode('utf-8'))
    obj.update(data.encode('utf-8'))
    result = obj.hexdigest()
    return result


def register():
    print('**************用戶註冊**************')
    while True:
        user = input('請輸入用戶名:')
        if user == 'N':
            return
        pwd = input('請輸入密碼:')
        temp = {'username':user,'password':get_md5(pwd)}
        USER_LIST.append(temp)

def login():
    print('**************用戶登錄**************')
    user = input('請輸入用戶名:')
    pwd = input('請輸入密碼:')

    for item in USER_LIST:
        if item['username'] == user and item['password'] == get_md5(pwd):
            return True


register()
result = login()
if result:
    print('登錄成功')
else:
    print('登錄失敗')

7-1-8. 6.1.8 getpass

import getpass
#密碼不顯示(只能在終端運行)
pwd = getpass.getpass('請輸入密碼:')
if pwd == '123':
    print('輸入正確')

7-1-9. 6.1.9 random

import random # 導入一個模塊 

v = random.randint(起始,終止) # 獲得一個隨機數

7-1-10. 6.1.10 functools

-functools.reduce(func,v1)

7-2. 6.2 自定義模塊

定義模塊時能夠把一個py文件或一個文件夾(包)看成一個模塊,以方便於之後其餘py文件的調用。

對於包的定義:

  • py2:文件見中必須有 _ _init _ _.py 。
  • py3:不須要 _ init _.py .

推薦你們之後寫代碼時,都要加上此文件。

導入模塊方法:

  • import 模塊 模塊.函數()
  • from 模塊 import 函數 函數() 【as起別名 / *表示所有】
  • from 模塊 import 函數 as 別名 別名()
- 模塊和要執行的py文件在同一目錄 且 須要 模塊中的不少功能時,推薦用: import 模塊	模塊.函數()
- 其餘推薦:from 模塊 import 模塊       模塊.函數()
- 其餘推薦:from 模塊.模塊 import 函數   函數()

1555575703809

1553910245673

7-3. 6.3 第三方模塊

  • requests
  • xlrd

7-4. 6.4 異常處理

try:
    val = input('請輸入數字:')
    num = int(val)
except Exception as e:
    print('操做異常')
# import requests
#
# try:
# ret = requests.get('http://www.google.com')
# print(ret.text)
# except Exception as e:
# print('請求異常')
def func(a):
    try:
        return a.strip()
    except Exception as e:
        pass
    return False

v = func('alex')
if not v:
    print('函數執行失敗')
else:
    print('結果是',v)
# 1. 寫函數,函數接受一個列表,請將列表中的元素每一個都 +100
def func(arg):
    result = []
    for item in arg:
        if item.isdecimal():
            result.append(int(item) + 100)
    return result 

# 2. 寫函數去,接受一個列表。列表中都是url,請訪問每一個地址並獲取結果。
import requests 
def func(url_list):
    result = []
    try:
        for url in url_list:
            response = requests.get(url)
            result.append(response.text)
    except Exception as e:
        pass
    return result 

def func2(url_list):
    result = []
    for url in url_list:
        try:
            response = requests.get(url)
            result.append(response.text)
        except Exception as e:
            pass
    return result 

func(['http://www.baidu.com','http://www.google.com','http://www.bing.com'])

7-5. 6.5 正則表達式

到底什麼是正則表達式(regex)?

在編寫處理字符串的程序或網頁時,常常有查找符合某些複雜規則的字符串的須要。正則表達式就是用於描述這些規則的工具。換句話說,正則表達式就是記錄文本規則的代碼。

在線工具

7-5-1. 6.5.1 經常使用元字符

\d	表示全部的數字
\w	字母/數字/下劃線
\s	空白(空格/換行符/製表符)
\t	匹配製表符 Tab
\n	匹配換行符
.	表示除了換行符以外的任意內容
\D	表示全部的非數字
\W	表示除 數字字母下劃線以外的全部字符
\S	表示非空白
[]	  	字符組 :只要在中括號內的全部字符都是符合規則的字符
[^xyz]	非字符組 :只要在中括號內的全部字符都是不符合規則的字符
^	表示一個字符的開始
$	表示一個字符的結束
|	表示或,注意,若是兩個規則有重疊部分,老是長的在前面,短的在後面
()	表示分組,給一部分正則規定爲一組,|這個符號的做用域就能夠縮小了

[\d\D] [\W\w] [\S\s] 匹配全部一切字符

7-5-2. 6.5.2 經常使用限定符(量詞)

代碼/語法 說明
* 重複零次或更屢次
+ 重複一次或更屢次
? 重複零次或一次
{n} 重複n次
{n,} 重複n次或更屢次
{n,m} 重複n到m次
> 匹配一個整數或者小數 \d+.\d+ \d+ \d+.?\d* \d+(.\d+)?
# 以a開頭,由至少一個字母組成的字符串
# ^a[a-zA-Z]+
# ^a[a-zA-Z]*

# 以1開頭,中間3-5個數字,若是中間位置超過5個數字,則整個字符串不匹配
# ^1\d{3,5}$

7-5-3. 6.5.3 貪婪匹配

默認採用回溯算法,貪婪匹配,老是會在符合量詞條件的範圍內儘可能多匹配.

adljdkjsljdlj

<.+> 會匹配到整個字符串,而不是

惰性匹配

老是匹配符合條件範圍內儘可能小的字符串

格式: 元字符 量詞 ? x

表示按照元字符規則在量詞範圍內匹配,一旦遇到x就中止

# 身份證號
# 15位  全數字 首位不爲0
# 18位  前17位全數字 首位不爲0  最後一位多是x和數字
# [1-9](\d{14}|\d{16}(\d|x))
# [1-9](\d{16}[\dx]|\d{14})
# [1-9]\d{14}(\d{2}[\dx])?

7-5-4. 6.5.4 表達式中轉義符

正則表達式中的轉義符在python的字符串中也恰好有轉義的做用,可是正則表達式中的轉義符和字符串中的轉義符並不要緊,且還容易有衝突,爲了不這種衝突,咱們全部的正則都以在工具中的測試結果爲結果,而後只須要在正則和待匹配的字符串外面都加r便可.

  • \d \s \w \t \n→python字符串中
  • 匹配()[]{}\d等,須要加\轉義

7-5-5. 6.5.5 ret正則模塊

  • ret.findall('正則表達式',字符串)
    匹配字符串中全部符合規則的項,並返回一個列表,若是未匹配到返回空列表

  • ret.search('正則表達式',字符串)

    匹配字符串中知足條件的第一項,返回一個對象,用group方法取值;若是不能匹配上返回None,group方法會報錯.

if ret:
    print(ret.group()) # 若是是對象,那麼這個對象內部實現了group,因此能夠取值
                       # 若是是None,那麼這個對象不可能實現了group方法,因此報錯
  • ret.match('正則表達式',字符串)

    會從頭匹配字符串中取出從第一個字符開始是否符合規則,若是符合,就返回對象,用group取值,若是不符合,就返回None

    match = search + ^正則

  • re.finditer('正則表達式',字符串)

    返回一個迭代器,迭代出來的每一項都是一個對象,而後group取值

    在查詢的結果超過1個的狀況下,可以有效的節省內存,下降空間複雜度,從而也下降了時間複雜度

  • re.compile('正則表達式')

    正則表達式編譯成python語言,供屢次使用

    ret = re.compile('\d3')
    r1=ret.search("djasjd5a646")
  • re.split()

    re.split('\d\d','alex83wusir74taibai')	  #不保存被分割的內容 [,1]第幾個分割
    re.split('\d(\d)','alex83wusir74taibai')  # 默認自動保留分組中的內容
  • re.sub('正則表達式',替換內容,字符串,[序號])
    返回字符串

  • re.subn('正則表達式',替換內容,字符串,[序號])
    返回元組(替換後字符串,替換個數)

7-5-6. 6.5.6 分組

  • 分組命名
    (?P<組名>正則)

  • 引用分組
    (?P=組命)

  • findall和分組

    • 優先顯示分組中的內容,其餘內容內容返回空字符串""
    • (?:)取消這個分組的優先⭐ ,量詞爲了約定多個字符加括號,會產生此狀況.
    import re
    ret = re.findall('\d+(\.\d+)?','21.234+2')
    print(ret)
    #運行結果:['.234', '']
    import re
    ret = re.findall('\d+(?:\.\d+)?','21.234+2')
    print(ret)
    #運行結果:['21.234', '2']

小技巧:有的時候咱們想匹配的內容包含在不相匹配的內容當中,這個時候只須要把不想匹配的先匹配出來,再經過手段去掉.

import re
ret=re.findall(r"\d+\.\d+|(\d+)","1-2*(60+(-40.35/5)-(-4*3))")
print(ret)
ret.remove('')
print(ret)
#運行結果:
#['1', '2', '60', '', '5', '4', '3']
#['1', '2', '60', '5', '4', '3']
  • split和分組
    會保留分組中原本應該被切割掉的內容
  • search和分組
    經過索引取 obj.group(1)
    經過組名取 obj.group('組名')
# 1.找出<h1>123fh</h1><h2>hado</h2>中全部標籤內的字符串 爬蟲
import re
ret = re.findall('<.*?>(.*?)<.*?>','<h1>123fh</h1><h2>hado</h2>')
print(ret)

# 2.找出四則運算表達式中的第一個乘除法
# \d*\d|\d/\d
# \d+(\.\d+)?[*/]\d(\.\d+)?
# \d+(\.\d+)?[*/]-?\d(\.\d+)?
import re
ret = re.search('\d+(\.\d+)?[*/]-?\d(\.\d+)?', '2-3*-5/6')
print(ret.group())

# 3.檢測用戶輸入的內容是不是一個合法的身份證號 網頁的合法輸入(手機號碼 qq號碼 銀行卡號 郵箱地址)
# '^[1-9]\d{14}(\d{2}[\dx])?$'
import re
inp = input('>>>').strip()
re.match('[1-9]\d{14}(\d{2}[\dx])?$', inp)  # 首選
re.search('^[1-9]\d{14}(\d{2}[\dx])?$', inp)
re.findall('^[1-9]\d{14}(\d{2}[\dx])?$', inp)
ret=re.findall(pattern,info,re.S) #容許.匹配下一行

8. 第七章 面向對象

8-1. 7.1 面向對象基本格式

# ###### 定義類 ######

class 類名:
    def 方法名(self,name):
        print(name)
        return 123

# ###### 調用類中的方法 ###### 
# 1.建立該類的對象
obj = 類名()
# 2.經過對象調用方法
result = obj.方法名('alex')
print(result)
# 若是在python2中這樣定義,則稱其爲:經典類
class Foo:
    pass 
# 若是在python2中這樣定義,則稱其爲:新式類
class Foo(object):
    pass 
# 在python3中這倆的寫法是同樣,由於全部的類默認都會繼承object類,所有都是新式類。
class Base(object):
    pass
class Bar(Base):
    pass

8-2. 7.2 面向對象的特性

封裝,繼承,多態.

8-2-1. 7.2.1封裝

  • 表現一:函數封裝到類
class File:
    def read(self):
        pass
    def write(self):
        pass
  • 表現二:數據封裝到對象 *
class Person:
    def __init__(sef,name,age):
        self.name = name
        self.age = age
p = Person('alex',19)

對象的做用:存儲一些值,方便之後調用.

class Person:
    def __init__(self,n,a,g): # 初始化方法(構造方法),給對象的內部作初始化。
        self.name = n
        self.age = a
        self.gender = g

    def show(self):
        temp = "我是%s,年齡:%s,性別:%s " % (self.name, self.age, self.gender,)
        print(temp)

# 類() 實例化對象,自動執行此類中的 __init__方法。
p1 = Person('李兆琪',19,'男')
p1.show()

p2 = Person('利奇航',19,'男')
p2.show()

若是寫代碼時,函數比較多比較亂。

  1. 能夠將函數歸類並放到同一個類中。
  2. 函數若是有一個反覆使用的公共值,則能夠放到對象中。
class Person:
    def __init__(self,user,pwd,email):
        self.username = user
        self.password = pwd
        self.email = email
        


    def info(self):
        return "個人名字:%s,密碼:%s,郵箱%s" %(self.username,self.password,self.email,)

USER_LIST = []#對象(用戶/密碼/郵箱),對象(用戶/密碼/郵箱),對象(用戶/密碼/郵箱)
while True:
    user = input('請輸入用戶名:')
    pwd = input('請輸入密碼:')
    email = input('請輸入郵箱:')
    p = Person(user,pwd,email)
    USER_LIST.append(p)

for item in USER_LIST:
    msg = item.info()
    print(msg)

8-2-2. 7.2.2 繼承

# 父類(基類)
class Base:
    def f1(self):
        pass
# 子類(派生類)
class Foo(Base):
    def f2(self):
        pass

# 建立了一個字類的對象
obj = Foo()
# 執行對象.方法時,優先在本身的類中找,若是沒有就是父類中找。
obj.f2()
obj.f1()

# 建立了一個父類的對象
obj = Base()
obj.f1()

何時才能用到繼承?多個類中若是有公共的方法,能夠放到基類中避免重複編寫。

class Base:
    def f1(self):
        self.f2()
        print('base.f1')
    def f2(self):
        print('base.f2')
class Foo(Base):
    def f2(self):
        print('foo.f2')
obj = Foo()
obj.f1()        
#foo.f2
#base.f1 注意self是誰

注意事項:

  • self 究竟是誰?
  • self 是哪一個類建立的,就今後類開始找,本身沒有就找父類。

8-2-3. 7.2.3 多態-鴨子模型

# Python
def func(arg):
    v = arg[-1] # arg.append(9)
    print(v)

# java
def func(str arg):
    v = arg[-1]
    print(v)

什麼是鴨子模型?

對於一個函數而言,Python對於參數的類型不會限制,那麼傳入參數時就能夠是各類類型,在函數中若是有例如:arg.send方法,那麼就是對於傳入類型的一個限制(類型必須有send方法)。
這就是鴨子模型,相似於上述的函數咱們認爲只要能呱呱叫的就是鴨子(只有有send方法,就是咱們要想的類型)

8-3. 7.3 成員

    • 類變量
    • 方法
      • 綁定方法
      • 類方法
      • 靜態方法
    • 屬性
  • 實例(對象)
    • 實例變量

8-3-1. 7.3.1 實例變量

實例本身封裝的變量

class Foo:
    def __init__(self,name):
        self.name=name
        
     def info(self):
        pass
 obj1 = Foo("alex")
 obj2 = Foo('eric')

8-3-2. 7.3.2 類變量

  • 定義:寫在類的下一級和方法同一級。

  • 訪問:

    類.類變量名稱 (推薦)
    對象.類變量名稱
  • 面試題

    class Base:
        x = 1
        
    obj = Base()
    
    
    print(obj.x) # 先去對象中找,沒有再去類中找。
    obj.y = 123  # 在對象中添加了一個y=123的變量。
    print(obj.y)
    obj.x = 123
    print(obj.x)
    print(Base.x)

    總結:找變量優先找本身,本身沒有找 類 或 基類;修改或賦值只能在本身的內部設置。

8-3-3. 7.3.3 綁定方法/普通方法

  • 定義:至少有一個self參數
  • 執行:先建立對象,由對象.方法()。
class Foo:
    def func(self,a,b):
        print(a,b)
        
obj = Foo()
obj.func(1,2)
# ###########################
class Foo:
    def __init__(self):
        self.name = 123

    def func(self, a, b):
        print(self.name, a, b)

obj = Foo()
obj.func(1, 2)

8-3-4. 7.3.4 靜態方法

  • 定義:
    • @staticmethod裝飾器
    • 參數無限制
  • 執行:
    • 類.靜態方法名 ()
    • 對象.靜態方法() (不推薦)
class Foo:
    def __init__(self):
        self.name = 123

    def func(self, a, b):
        print(self.name, a, b)

 @staticmethod
    def f1():
        print(123)

obj = Foo()
obj.func(1, 2)

Foo.f1()
obj.f1() # 不推薦

8-3-5. 7.3.5 類方法

  • 定義:
    • @classmethod裝飾器
    • 至少有cls參數,當前類。
  • 執行:
    • 類.類方法()
    • 對象.類方法() (不推薦)
class Foo:
    def __init__(self):
        self.name = 123

    def func(self, a, b):
        print(self.name, a, b)

 @staticmethod
    def f1():
        print(123)

 @classmethod
    def f2(cls,a,b):
        print('cls是當前類',cls)
        print(a,b)

obj = Foo()
obj.func(1, 2)

Foo.f1()
Foo.f2(1,2)
# 問題: @classmethod和@staticmethod的區別?
"""
一個是類方法一個靜態方法。 
定義:
	類方法:用@classmethod作裝飾器且至少有一個cls參數。
	靜態方法:用staticmethod作裝飾器且參數無限制。
調用:
	類.方法直接調用。
	對象.方法也能夠調用。 
"""

8-3-6. 7.3.6 屬性

  • 定義:
    • @property裝飾器
    • 只有一個self參數
  • 執行:
    • 對象.方法 不用加括號。
class Foo:

 @property
    def func(self):
        print(123)
        return 666

obj = Foo()
result = obj.func
print(result)
# 屬性的應用

class Page:
    def __init__(self, total_count, current_page, per_page_count=10):
        self.total_count = total_count
        self.per_page_count = per_page_count
        self.current_page = current_page
 @property
    def start_index(self):
        return (self.current_page - 1) * self.per_page_count
 @property
    def end_index(self):
        return self.current_page * self.per_page_count


USER_LIST = []
for i in range(321):
    USER_LIST.append('alex-%s' % (i,))

# 請實現分頁展現:
current_page = int(input('請輸入要查看的頁碼:'))
p = Page(321, current_page)
data_list = USER_LIST[p.start_index:p.end_index]
for item in data_list:
    print(item)

8-4. 7.4 成員修飾符

  • 公有,全部地方都能訪問到。
  • 私有,只有本身能夠訪問到。
class Foo:
    def __init__(self, name):
        self.__name = name

    def func(self):
        print(self.__name)


obj = Foo('alex')
# print(obj.__name)
obj.func()
class Foo:
    __x = 1

 @staticmethod
    def func():
        print(Foo.__x)


# print(Foo.__x)
Foo.func()
class Foo:

    def __fun(self):
        print('msg')

    def show(self):
        self.__fun()

obj = Foo()
# obj.__fun()
obj.show()
# 強制訪問私有成員

class Foo:
    def __init__(self,name):
        self.__x = name


obj = Foo('alex')

print(obj._Foo__x) # 強制訪問私有實例變量

8-5. 7.4 嵌套

嵌套表現形式:

  • 函數: 參數能夠是任意類型
  • 字典: 對象和類均可以作字典的key和value
  • 繼承的查找關係
class StarkConfig(object):
    pass

class AdminSite(object):
    def __init__(self):
        self.data_list = []
        
    def register(self,arg):
        self.data_list.append(arg)
        
site = AdminSite()

obj = StarkConfig()
site.register(obj)	#將對象嵌入另外一類的對象的列表中
class StarkConfig(object):
    def __init__(self,name,age):
        self.name = name
        self.age = age

class AdminSite(object):
    def __init__(self):
        self.data_list = []
        self.sk = None

    def set_sk(self,arg):
        self.sk = arg
        
        
site = AdminSite() # data_list = [] sk = StarkConfig
site.set_sk(StarkConfig)
site.sk('alex',19)	#StarkConfig('alex',19)

8-6. 7.5 特殊成員

8-6-1. 7.5.1 __init__

class Foo:
    """ 類是幹啥的。。。。 """
    def __init__(self,a1):
        """ 初始化方法 :param a1: """
        self.a1 = a1
        
obj = Foo('alex')

8-6-2. 7.5.2__new__

class Foo(object):
    def __init__(self):
        """ 用於給對象中賦值,初始化方法 """
        self.x = 123
    def __new__(cls, *args, **kwargs):
        """ 用於建立空對象,構造方法 :param args: :param kwargs: :return: """
        return object.__new__(cls)

obj = Foo()

8-6-3. 7.5.3 __call__

class Foo(object):
    def __call__(self, *args, **kwargs):
        print('執行call方法')

# obj = Foo()
# obj()
Foo()()
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from wsgiref.simple_server import make_server

def func(environ,start_response):
    start_response("200 OK", [('Content-Type', 'text/plain; charset=utf-8')])
    return ['你好'.encode("utf-8")  ]

class Foo(object):

    def __call__(self, environ,start_response):
        start_response("200 OK", [('Content-Type', 'text/html; charset=utf-8')])
        return ['你<h1 style="color:red;">很差</h1>'.encode("utf-8")]


# 做用:寫一個網站,用戶只要來方法,就自動找到第三個參數並執行。
server = make_server('127.0.0.1', 8000, Foo())
server.serve_forever()

8-6-4. 7.5.4 __getitem__

class Foo(object):

    def __setitem__(self, key, value):
        pass

    def __getitem__(self, item):
        return item + 'uuu'

    def __delitem__(self, key):
        pass


obj1 = Foo()
obj1['k1'] = 123  # 內部會自動調用 __setitem__方法
val = obj1['xxx']  # 內部會自動調用 __getitem__方法
print(val)
del obj1['ttt']  # 內部會自動調用 __delitem__ 方法

8-6-5. 7.4.5 __str__

class Foo(object):

    def __setitem__(self, key, value):
        pass

    def __getitem__(self, item):
        return item + 'uuu'

    def __delitem__(self, key):
        pass


obj1 = Foo()
obj1['k1'] = 123  # 內部會自動調用 __setitem__方法
val = obj1['xxx']  # 內部會自動調用 __getitem__方法
print(val)
del obj1['ttt']  # 內部會自動調用 __delitem__ 方法
class User(object):
    def __init__(self,name,email):
        self.name = name
        self.email = email
    def __str__(self):
        return "%s %s" %(self.name,self.email,)
user_list = [User('二狗','2g@qq.com'),User('二蛋','2d@qq.com'),User('狗蛋','xx@qq.com')]
for item in user_list:
    print(item)

8-6-6. 7.4.6__dict__

class Foo(object):
    def __init__(self,name,age,email):
        self.name = name
        self.age = age
        self.email = email

obj = Foo('alex',19,'xxxx@qq.com')
print(obj)
print(obj.name)
print(obj.age)
print(obj.email)
val = obj.__dict__ # 去對象中找到全部變量並將其轉換爲字典
print(val)

8-6-7. 7.4.7 上下文管理

class Foo(object):
    def __enter__(self):
        self.x = open('a.txt',mode='a',encoding='utf-8')
        return self.x
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.x.close()

with Foo() as ff:
    ff.write('alex')
    ff.write('alex')
    ff.write('alex')
    ff.write('alex')
# class Context:
# def __enter__(self):
# print('進入')
# return self
#
# def __exit__(self, exc_type, exc_val, exc_tb):
# print('推出')
#
# def do_something(self):
# print('內部執行')
#
# with Context() as ctx:
# print('內部執行')
# ctx.do_something()


class Foo(object):
    def do_something(self):
        print('內部執行')

class Context:
    def __enter__(self):
        print('進入')
        return Foo()

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('推出')

with Context() as ctx:
    print('內部執行')
    ctx.do_something()
val = 5 + 8
print(val)

val = "alex" + "sb"
print(val)

class Foo(object):
    def __add__(self, other):
        return 123
    
obj1 = Foo()
obj2 = Foo()
val  = obj1 + obj2
print(val)

8-6-8. 7.4.8 對象相加

val = 5 + 8
print(val)

val = "alex" + "sb"
print(val)

class Foo(object):
    def __add__(self, other):
        return 123
    
obj1 = Foo()
obj2 = Foo()
val  = obj1 + obj2
print(val)

8-7. 7.5 內置函數(補充)

8-7-1. 7.5.1 type,查看類型

class Foo:
    pass

obj = Foo()

if type(obj) == Foo:
    print('obj是Foo類的對象')

8-7-2. 7.5.2 issubclass

class Base:
    pass

class Base1(Base):
    pass

class Foo(Base1):
    pass

class Bar:
    pass

print(issubclass(Bar,Base))
print(issubclass(Foo,Base))

8-7-3. 7.5.3 isinstance

class Base(object):
    pass

class Foo(Base):
    pass

obj = Foo()

print(isinstance(obj,Foo))  # 判斷obj是不是Foo類或其基類的實例(對象)
print(isinstance(obj,Base)) # 判斷obj是不是Foo類或其基類的實例(對象)

8-8. 7.6 super

class Base(object):
    def func(self):
        print('base.func')
        return 123


class Foo(Base):
    def func(self):
        v1 = super().func()
        print('foo.func',v1)

obj = Foo()
obj.func()
# super().func() 去父類中找func方法並執行
class Bar(object):
    def func(self):
        print('bar.func')
        return 123

class Base(Bar):
    pass

class Foo(Base):
    def func(self):
        v1 = super().func()
        print('foo.func',v1)

obj = Foo()
obj.func()
# super().func() 根據類的繼承關係,按照順序挨個找func方法並執行(找到第一個就不在找了)
class Base(object): # Base -> object
    def func(self):
        super().func()
        print('base.func')

class Bar(object):
    def func(self):
        print('bar.func')

class Foo(Base,Bar): # Foo -> Base -> Bar
    pass

obj = Foo()
obj.func()

# super().func() 根據self對象所屬類的繼承關係,按照順序挨個找func方法並執行(找到第一個就不在找了)

8-9. 7.7 異常處理

8-9-1. 7.7.1 基本格式

try:
    pass
except Exception as e:
    pass
try:
    v = []
    v[11111] # IndexError
except ValueError as e:
    pass
except IndexError as e:
    pass
except Exception as e:
    print(e) # e是Exception類的對象,中有一個錯誤信息。
try:
    int('asdf')
except Exception as e:
    print(e) # e是Exception類的對象,中有一個錯誤信息。
finally:
    print('最後不管對錯都會執行')
    
# #################### 特殊狀況 #########################
def func():
    try:
        # v = 1
        # return 123
        int('asdf')
    except Exception as e:
        print(e) # e是Exception類的對象,中有一個錯誤信息。
        return 123
    finally:
        print('最後')

func()

8-9-2. 7.7.2 主動觸發異常

try:
    int('123')
    raise Exception('阿薩大大是阿斯蒂') # 代碼中主動拋出異常
except Exception as e:
    print(e)
def func():
    result = True
    try:
        with open('x.log',mode='r',encoding='utf-8') as f:
            data = f.read()
        if 'alex' not in data:
            raise Exception()
    except Exception as e:
        result = False
    return result

8-9-3. 7.7.3 自定義異常

class MyException(Exception):
    pass

try:
    raise MyException('asdf')
except MyException as e:
    print(e)
class MyException(Exception):
    def __init__(self,message):
        super().__init__()
        self.message = message

try:
    raise MyException('asdf')
except MyException as e:
    print(e.message)

8-10. 7.8 可迭代對象

表象:能夠被for循環對象就能夠稱爲是可迭代對象:字符串,列表,字典...

  • 如何讓一個對象變成可迭代對象?

在類中實現__iter__方法且返回一個迭代器(生成器)

class Foo:
    def __iter__(self):
        return iter([1,2,3,4])

obj = Foo()


class Foo:
    def __iter__(self):
        yield 1
        yield 2
        yield 3

obj = Foo()

記住:只要能被for循環就是去看他內部的iter方法。

8-11. 7.9 約束

# 約束字類中必須寫send方法,若是不寫,則調用時候就報拋出 NotImplementedError 
class Interface(object):
    def send(self):
        raise NotImplementedError()
        
class Message(Interface):
    def send(self):
        print('發送短信')
        
class Email(Interface):
    def send(self):
        print('發送郵件')

8-12. 7.10反射

根據字符串的形式去某個對象中 操做 他的成員。

  • getattr(對象,"字符串") 根據字符串的形式去某個對象中 獲取 對象的成員.

    class Foo(object):
        def __init__(self,name):
            self.name = name
    obj = Foo('alex')
    
    # 獲取變量
    v1 = getattr(obj,'name')
    # 獲取方法
    method_name = getattr(obj,'login')
    method_name()
  • hasattr(對象,'字符串') 根據字符串的形式去某個對象中判斷是否有該成員。

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from wsgiref.simple_server import make_server
    
    class View(object):
        def login(self):
            return '登錄'
    
        def logout(self):
            return '等出'
    
        def index(self):
            return '首頁'
    
    
    def func(environ,start_response):
        start_response("200 OK", [('Content-Type', 'text/plain; charset=utf-8')])
        #
        obj = View()
        # 獲取用戶輸入的URL
        method_name = environ.get('PATH_INFO').strip('/')
        if not hasattr(obj,method_name):
            return ["sdf".encode("utf-8"),]
        response = getattr(obj,method_name)()
        return [response.encode("utf-8")  ]
    
    # 做用:寫一個網站,用戶只要來方法,就自動找到第三個參數並執行。
    server = make_server('192.168.12.87', 8000, func)
    server.serve_forever()
  • setattr(對象,'變量','值') 根據字符串的形式去某個對象中設置成員。

    class Foo:
        pass
    
    
    obj = Foo()
    obj.k1 = 999
    setattr(obj,'k1',123) # obj.k1 = 123
    
    print(obj.k1)
  • delattr(對象,'變量') 根據字符串的形式去某個對象中刪除成員。

    class Foo:
        pass
    
    obj = Foo()
    obj.k1 = 999
    delattr(obj,'k1')
    print(obj.k1)

python一切皆對象

  • py文件
  • 對象

python一切皆對象,因此之後想要經過字符串的形式操做其內部成員均可以經過反射的機制實現。

8-13. 7.11.單例模式

不管實例化多少次,永遠用的都是第一次實例化出的對象。

class Foo:
    pass

# 多例,每實例化一次就建立一個新的對象。
obj1 = Foo() # 實例,對象
obj2 = Foo() # 實例,對象
# 單例,不管實例化多少次,都用第一次建立的那個對象。
obj1 = Foo()
obj2 = Foo()

單例模式標準

class Singleton(object):
    instance = None
    def __new__(cls, *args, **kwargs):
        if not cls.instance:
            cls.instance = object.__new__(cls)
        return cls.instance

obj1 = Singleton()
obj2 = Singleton()

# 不是最終,加鎖。

文件的鏈接池

class FileHelper(object):
    instance = None
    def __init__(self, path):
        self.file_object = open(path,mode='r',encoding='utf-8')

    def __new__(cls, *args, **kwargs):
        if not cls.instance:
            cls.instance = object.__new__(cls)
        return cls.instance

obj1 = FileHelper('x')
obj2 = FileHelper('x')
  • 模塊屢次導入從新加載
import jd # 第一次加載:會加載一遍jd中全部的內容。
import jd # 由已經加載過,就不在加載。
print(456)
import importlib
import jd
importlib.reload(jd)
print(456)

經過模塊導入的特性也能夠實現單例模式:

# jd.py
class Foo(object):
    pass

obj = Foo()
# app.py
import jd # 加載jd.py,加載最後會實例化一個Foo對象並賦值給obj
print(jd.obj)

8-14. 7.12日誌

  • logging基本應用

  • 日誌處理本質:Logger/FileHandler/Formatter

  • 推薦處理日誌方式

    import logging
    
    file_handler = logging.FileHandler(filename='x1.log', mode='a', encoding='utf-8',)
    logging.basicConfig(
        format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S %p',
        handlers=[file_handler,],
        level=logging.ERROR
    )
    
    logging.error('你好')
  • 推薦處理日誌方式 + 日誌分割

    import time
    import logging
    from logging import handlers
    # file_handler = logging.FileHandler(filename='x1.log', mode='a', encoding='utf-8',)
    file_handler = handlers.TimedRotatingFileHandler(filename='x3.log', when='s', interval=5, encoding='utf-8')
    logging.basicConfig(
        format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S %p',
        handlers=[file_handler,],
        level=logging.ERROR
    )
    
    for i in range(1,100000):
        time.sleep(1)
        logging.error(str(i))

    注意事項:

    # 在應用日誌時,若是想要保留異常的堆棧信息。
    import logging
    import requests
    
    logging.basicConfig(
        filename='wf.log',
        format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S %p',
        level=logging.ERROR
    )
    
    try:
        requests.get('http://www.xxx.com')
    except Exception as e:
        msg = str(e) # 調用e.__str__方法
        logging.error(msg,exc_info=True)

8-15. 7.13項目結構目錄

1556459318540

1556459350241

1556459398316

9. 第八章 網絡編程

10. 第九章 併發編程

11. 第十章 數據庫

12. 第十一章 前端開發

13. 第十二章 Django框架

14. 附錄 常見錯誤和單詞

14-1. py2&py3區別

  • py2:
    xrange,不會在內存中當即建立,而是在循環時。邊循環邊建立。
    range ,在內存當即把全部的值都建立。
    py3:
    range ,不會在內存中當即建立,而是在循環時。邊循環邊建立。
    list(range(10))

14-2. 單詞

upper 大寫 ...

14-3. 錯誤記錄

14-3-1.

14-4. 面試題

  • 線上操做系統:centos

  • py2和py3的區別?

  • 每種數據類型,列舉你瞭解的方法。

  • 3 or 9 and 8

  • 字符串的反轉

  • is 和 == 的區別?

  • v1 = (1) / v2 = 1

  • 深淺拷貝

  • 文件操做,大文件如何讀取內容 [ 50G的日誌文件 ]

    v = open(....)
    
    for line in v:
        print(line)
        
    v.close()
  • 一行寫出:9*9乘法表【不會】

  • git流程【不會】

  • global和nonlocal區別

  • 需求分析

  • 誠實

  • 知識邊界分析,對比

相關文章
相關標籤/搜索