1. 程式人生 > >簡明 Python3 教程 | 學習筆記

簡明 Python3 教程 | 學習筆記

《A Byte of Python》是一本由 Swaroop C H 編寫,旨在於介紹如何使用 Python 語言進行程式設計的自由圖書。它以教材與指南的形式為入門者介紹 Python 語言。如果你對電腦知識的瞭解僅限於如何儲存文字檔案的話,那這本書就是為你準備的。
2005 年,沈潔元將本書的 1.20 版引進中國,並完成了全本翻譯,將本書的譯名定為《簡明 Python 教程》。2017年,漠倫基於原書 4.0 版重新翻譯,製作了本版全新譯本,並沿用同樣的譯名。
本版譯本定義為 4.08c 版。最後修訂於 2018 年 2 月 4 日。

本人僅在該教程上,提煉自身薄弱的知識點,以及需注意的重點。該筆記不具有參考意義,有需要的讀者可看原 GitBook 電子書。—-ZJ

格式化方法: format()

有時候我們會想要從其他資訊中構建字串。這正是 format() 方法大有用武之地的地方。

age = 20
name = 'Swaroop'

print('{0} was {1} years old when he wrote this book'.format(name, age))
print('Why is {0} playing with that python?'.format(name))
Swaroop was 20 years old when he wrote this book
Why is Swaroop playing with that python?
name  + ' is '+ str(age) + ' years old'
'Swaroop is 20 years old'
# 對於浮點數 '0.333' 保留小數點(.)後三位
print('{0:.3f}'.format(1.0/3))
# 使用下劃線填充文字,並保持文字處於中間位置
# 使用 (^) 定義 '___hello___'字串長度為 11
print('{0:_^11}'.format('hello'))
# 基於關鍵詞輸出 'Swaroop wrote A Byte of Python'
print('{name} wrote {book}'.format(name='Swaroop'
,book='A byte of Python'))
0.333
___hello___
Swaroop wrote A byte of Python

由於我們正在討論格式問題,就要注意 print 總是會以一個不可見的“新一行”字元( \n )
結尾,因此重複呼叫 print 將會在相互獨立的一行中分別列印。為防止列印過程中出現這一
換行符,你可以通過 end 指定其應以空白結尾:

print('wow')
print('a',end='')
print('b',end='')
print()
print('c', end=' ')
print('d', end=' ')
wow
ab
c d 

轉義序列(Escape Sequence)

  • 通過 \ 來指定單引號:要注意它可是反斜槓。
  • 雙引號,必須使用轉義序列 \ 來指定反斜槓本身。
  • \n 來表示新一行的開始
print('what\'s your name?')
print("what's your name?")
print('This is the first line.\nThis is the second line.')
what's your name?
what's your name?
This is the first line.
This is the second line.

原始字串

如果你需要指定一些未經過特殊處理的字串,比如轉義序列,那麼你需要在字串前增加 r 或 R 來指定一個 原始(Raw) 字串 。

針對正則表示式使用者的提示
在處理正則表示式時應全程使用原始字串。否則,將會有大量 Backwhacking 需要處理。舉例說明的話,反向引用可以通過 ‘\1’ 或 r’\1’ 來實現。

print(r"Newlines are indicated by \n")
Newlines are indicated by \n
i = 5
print(i)
i = i + 1
print(i)

s = '''This is a multi-line string.
This is the second line'''
print(s)
5
6
This is a multi-line string.
This is the second line
'''
強烈建議你對於每一行物理行最多隻寫入一行邏輯行。這個觀點就是說你不應該使
用分號。實際上,我從未在 Python 程式中使用、甚至是見過一個分號。

在一類情況下這一方法會頗為有用:如果你有一行非常長的程式碼,你可以通過使用反斜槓將
其拆分成多個物理行。這被稱作顯式行連線(Explicit Line Joining)

注意: \ 後面不要有空格

'''

s = 'This is a string. \
This continues the string.'
print(s)
This is a string. This continues the string.
i = \
5
print(i)
5

運算子

  • // (整除)
    • x 除以 y 並對結果向下取整至最接近的整數。
    • 13 // 3 輸出 4 。
    • -13 // 3 輸出 -5 。
  • % (取模)

    • 返回除法運算後的餘數。
    • 13 % 3 輸出 1 。 -25.5 % 2.25 輸出 1.5 。
    • 對於整型數a,b來說,取模運算或者求餘運算的方法都是:

      • 1.求 整數商: c = a/b;
      • 2.計算模或者餘數: r = a - c*b.
    • 歸納:

      • 當a和b符號一致時,求模運算和求餘運算所得的c的值一致,因此結果一致。
      • 當符號不一致時,結果不一樣。求模運算結果的符號和b一致,求餘運算結果的符號和a一致。
  • << (左移)

    • 將數字的位向左移動指定的位數。(每個數字在記憶體中以二進位制數表示,即 0 和1)
    • 2 << 2 輸出 8 。 2 用二進位制數表示為 10 。
    • 向左移 2 位會得到 1000 這一結果,表示十進位制中的 8 。
  • >> (右移)
    • 將數字的位向右移動指定的位數。
    • 11 >> 1 輸出 5 。
    • 11 在二進位制中表示為 1011 ,右移一位後輸出 101 這一結果,表示十進位制中的 5 。
13//3
4
-13//3 # 向下取整 -4.多 向下取整是 -5
-5
13%3
1
'''
c = a/b; -25.5/2.25 = -12 (向下取整)
r = a - c*b. r = -25.5 - (-12 * 2.25) = 1.5
'''
-25.5%2.25
1.5
'''
2  ----- 10 
左移兩位

8  ----- 1000 

(2**3, 2**2, 2**1, 2**0)

'''
2<<2
8
'''
11 ---- 1011 (8+2+1)
右移 1 位
5  ----- 101 (4+1) 

'''

11>>1
5
  • & (按位與)
    • 對數字進行按位與操作。
    • 5 & 3 輸出 1 。
  • | (按位或)
    • 對數字進行按位或操作。運算規則:0 ^ 0 = 0;0 ^ 1 = 1;1 ^ 0 = 1;1 ^ 1 = 0;
    • 5 | 3 輸出 7 。
  • ^ (按位異或)
    • 對數字進行按位異或操作。
    • 5 ^ 3 輸出 6 。
  • < (小於)
    • 返回 x 是否小於 y。所有的比較運算子返回的結果均為 True 或 False 。請注意這些名稱之中的大寫字母。
    • 5 < 3 輸出 False , 3 < 6 輸出 True 。
print(5 < 3)
print(~5)
a = 2
a *= 3
print(a)
False
-6
6
number = 23
guess = int(input('Enter an integer :'))

if guess == number:
    print('Congratulations, you guessed it.')
    print('(but you do not win any prizes!)')
# 新塊在這裡結束
elif guess < number:
# 另一程式碼塊
    print('No, it is a little higher than that')
# 你可以在此做任何你希望在該程式碼塊內進行的事情
else:
    print('No, it is a little lower than that')
# 你必須通過猜測一個大於(>)設定數的數字來到達這裡。
print('Done')
Enter an integer :89
No, it is a little lower than that
Done
number = 23
running = True

while running:
    guess = int(input('Enter an integer:'))

    if guess == number:
        print('Congratulations, you guessed it.')
        # 這將導致 while 迴圈中止
        running = False
    elif guess < number:
        print('No, it is a little higher than that.')
    else:
        print('No, it is a little lower than that.')
else:
    print('The while loop is over.')
# 在這裡你可以做你想做的任何事
print('Done')
Enter an integer:90
No, it is a little lower than that.
Enter an integer:11
No, it is a little higher than that.
Enter an integer:23
Congratulations, you guessed it.
The while loop is over.
Done
for i in range(1,5):
    print(i)
else:
    print('The for loop is over')
1
2
3
4
The for loop is over
while True:
    s = input('Enter something:')
    if s == 'quit':
        break
    print('Length of the string is', len(s))
print('Done')    
Enter something:what?
Length of the string is 5
Enter something:quit
Done
# 用 continue 語句跳過程式碼塊中的其餘語句。
while True:
    s = input('Enter something:')
    if s == 'quit':
        break
    if len(s) < 3:
        print('Too small')
        continue
    print('Input is of sufficient length')    
Enter something:hello
Input is of sufficient length
Enter something:o
Too small
Enter something:quit
def say(message, times=1):
    print(message * times)

say('Hello ')    
say('World ', 5)
Hello 
World World World World World 
'''
關鍵字引數(Keyword Arguments)
'''
def func(a, b=5, c=10):
    print('a is',a, 'and b is', b, 'and c is', c)

func(3,7)    
func(35, c= 30)
func(c=80,b=9,a=888)
a is 3 and b is 7 and c is 10
a is 35 and b is 5 and c is 30
a is 888 and b is 9 and c is 80
'''
可變引數
'''
def total(a=5, *numbers, **phonebook):
    print('a', a)

    for single_item in numbers:
        print('single_item', single_item)

    for first_part,second_part in phonebook.items():
        print(first_part,second_part)

print(total(10,1,2,3,Jack=101010,John=22323,Inge=1889))
a 10
single_item 1
single_item 2
single_item 3
Jack 101010
John 22323
Inge 1889
None
'''
文件字串(Documentation Strings)

該文件字串所約定的是一串多行字串,其中第一行以某一大寫字母開始,以句號結束。
第二行為空行,後跟的第三行開始是任何詳細的解釋說明。 在此強烈建議你在你所有重要功
能的所有文件字串中都遵循這一約定。

'''


def print_max(x, y):
    '''列印兩個數值中的最大數。

    這兩個數都應該是整數'''
    # 如果可能,將其轉換至整數型別
    x = int(x)
    y = int(y)
    if x > y:
        print(x, 'is maximum')
    else:
        print(y, 'is maximum')

print_max(3, 5)
print(print_max.__doc__)
5 is maximum
列印兩個數值中的最大數。

    這兩個數都應該是整數
help(print_max)
Help on function print_max in module __main__:

print_max(x, y)
    列印兩個數值中的最大數。

    這兩個數都應該是整數
import sys

print('The command line arguments are:')
for i in sys.argv:
    print(i)

print('\n\n The PYTHONPATH is',sys.path,'\n') 
>python module_using_sys.py we are arguments
The command line arguments are:
module_using_sys.py
we
are
arguments


 The Python Path is ['D:\\github\\python\\Deep-Learning\\python', 'D:\\Program Files\\Python36\\python36.zip', 'D:\\Program Files\\Python36\\DLLs', 'D:\\Program Files\\Python36\\lib', 'D:\\Program Files\\Python36', 'C:\\Users\\qhtf\\AppData\\Roaming\\Python\\Python36\\site-packages', 'D:\\Program Files\\Python36\\lib\\site-packages']
import os

print(os.getcwd())
D:\github\python\Deep-Learning\python
from sys import argv
from math import sqrt

help(sqrt)
print('Square root of 16 is', sqrt(16))
Help on built-in function sqrt in module math:

sqrt(...)
    sqrt(x)

    Return the square root of x.

Square root of 16 is 4.0
import mymodule

mymodule.say_hi()
print('Version', mymodule.__version__)
Hi, this is mymodule speaking.
Version 0.1
from mymodule import say_hi,__version__

say_hi()
print('Version',__version__)
Hi, this is mymodule speaking.
Version 0.1
import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
import sys

# 給出 sys 模組中的屬性名稱
dir(sys)

# 給出當前模組的屬性名稱
dir()

包(Packages)

包是指一個包含模組與一個特殊的 init.py 檔案的資料夾,後者向 Python 表明這一資料夾是特別的,因為其包含了 Python 模組。
讓我們這樣設想:你想建立一個名為“world”的包,其中還包含著“asia”、“africa”等其它子包,同時這些子包都包含了諸如“india”、 “madagascar”等模組。

資料結構

資料結構(Data Structures)基本上人如其名——它們只是一種結構,能夠將一些資料聚合在一起。換句話說,它們是用來儲存一系列相關資料的集合。

Python 中有四種內建的資料結構——列表(List)、元組(Tuple)、字典(Dictionary)和集合(Set)。我們將瞭解如何使用它們,並利用它們將我們的程式設計之路變得更加簡單。

列表是可變的(Mutable)而字串是不可變的(Immutable)。

'''
list 列表
'''
shoplist = ['apple', 'mango', 'carrot','banana']

print('I have', len(shoplist), 'items to purchase')
print('I have %d items to purchase'% len(shoplist))

print('These items are:', end=' ')
for item in shoplist:
    print(item, end=' ')

print('\n I also have to buy rice.')    
shoplist.append('rice')
print('My shopping list is now', shoplist)

print('I will sort my list now')
shoplist.sort()
print('Sorted shopping list is now', shoplist)

print('The first item I will buy is', shoplist[0])
olditem = shoplist[0]

del shoplist[0]

print('I bought the',olditem)

print('My shopping list is now',shoplist)
I have 4 items to purchase
I have 4 items to purchase
These items are: apple mango carrot banana 
 I also have to buy rice.
My shopping list is now ['apple', 'mango', 'carrot', 'banana', 'rice']
I will sort my list now
Sorted shopping list is now ['apple', 'banana', 'carrot', 'mango', 'rice']
The first item I will buy is apple
I bought the apple
My shopping list is now ['banana', 'carrot', 'mango', 'rice']

元組(Tuple)

元組(Tuple)用於將多個物件儲存到一起。你可以將它們近似地看作列表,但是元組不能提供列表類能夠提供給你的廣泛的功能。元組的一大特徵類似於字串,它們是不可變的,也就是說,你不能編輯或更改元組。

zoo = ('python','elephant','penguin')
print('Number od animals in the zoo is',len(zoo))

new_zoo = 'monkey','camel',zoo

print('Number of cages in the new zoo is', len(new_zoo))
print('All animals in the zoo are',new_zoo)
print('Animals brought from old zoo are', new_zoo[2])

print('Last animal brought from old zoo is',new_zoo[2][2])
print('Number of animals in the new zoo is',len(new_zoo)-1 + len(new_zoo[2]))
Number od animals in the zoo is 3
Number of cages in the new zoo is 3
All animals in the zoo are ('monkey', 'camel', ('python', 'elephant', 'penguin'))
Animals brought from old zoo are ('python', 'elephant', 'penguin')
Last animal brought from old zoo is penguin
Number of animals in the new zoo is 5
'''
Dictionary 字典

'''
ab = {
    'Swaroop': '[email protected]',
    'Larry': '[email protected]',
    'Matsumoto': '[email protected]',
    'Spammer': '[email protected]'
}

print("Swaroop's address is", ab['Swaroop'])

del ab['Spammer']

print('\nThere are {} contacts in the address-book\n'.format(len(ab)))
print('There are %d contacts in the address-book\n'%len(ab))

for name, address in ab.items():
    print('Contact {} at {}'.format(name, address))

ab['Guido'] = '[email protected]'

if 'Guido' in ab:
    print("\nGuido's address is",ab['Guido'])
Swaroop's address is [email protected]

There are 3 contacts in the address-book

There are 3 contacts in the address-book

Contact Swaroop at [email protected]
Contact Larry at [email protected]
Contact Matsumoto at [email protected]

Guido's address is [email protected]
shoplist = ['apple', 'mango', 'carrot', 'banana']
name = 'swaroop'

# Indexing or 'Subscription' operation #
# 索引或“下標(Subscription)”操作符 #
print('Item 0 is', shoplist[0])
print('Item 1 is', shoplist[1])
print('Item 2 is', shoplist[2])
print('Item 3 is', shoplist[3])
print('Item -1 is', shoplist[-1])
print('Item -2 is', shoplist[-2])
print('Character 0 is', name[0])
Item 0 is apple
Item 1 is mango
Item 2 is carrot
Item 3 is banana
Item -1 is banana
Item -2 is carrot
Character 0 is s
# Slicing on a list shoplist = ['apple', 'mango', 'carrot', 'banana']#
print('Item 1 to 3 is', shoplist[1:3]) # 索引 1 開始 到 3 不包括3 
print('Item 2 to end is', shoplist[2:])
print('Item 1 to -1 is', shoplist[1:-1])
print('Item start to end is', shoplist[:])
Item 1 to 3 is ['mango', 'carrot']
Item 2 to end is ['carrot', 'banana']
Item 1 to -1 is ['mango', 'carrot']
Item start to end is ['apple', 'mango', 'carrot', 'banana']
# 從某一字串中切片 name = 'swaroop'#
print('characters 1 to 3 is', name[1:3])
print('characters 2 to end is', name[2:])
print('characters 1 to -1 is', name[1:-1])
print('characters start to end is', name[:])
characters 1 to 3 is wa
characters 2 to end is aroop
characters 1 to -1 is waroo
characters start to end is swaroop

你同樣可以在切片操作中提供第三個引數,這一引數將被視為切片的步長(Step)(在預設情況下,步長大小為 1):

ablist = ['a','b','c','d','e','f']

print(ablist[::1])
print(ablist[::2])
print(ablist[::3])
print(ablist[::-1])
print(ablist[::-2])
['a', 'b', 'c', 'd', 'e', 'f']
['a', 'c', 'e']
['a', 'd']
['f', 'e', 'd', 'c', 'b', 'a']
['f', 'd', 'b']
bri = set(['brazil', 'russia', 'india'])
'india' in bri
True
bric = bri.copy()
bric.add('china')
bric.issuperset(bri)
True
bri.add('russia')
bri.remove('russia')
print(bri & bric)
print(bri.intersection(bric))
{'india', 'brazil'}
{'india', 'brazil'}

引用

當你建立了一個物件並將其分配給某個變數時,變數只會查閱(Refer)某個物件,並且它也不會代表物件本身。也就是說,變數名只是指向你計算機記憶體中儲存了相應物件的那一部分。這叫作將名稱繫結(Binding)給那一個物件。

print('Simple Assignment')
shoplist = ['apple', 'mango', 'carrot', 'banana']
# mylist 只是指向同一物件的另一種名稱
mylist = shoplist

del shoplist[0]

print('shoplist is', shoplist)
print('mylist is', mylist)

# 注意到 shoplist 和 mylist 二者都
# 打印出了其中都沒有 apple 的同樣的列表,以此我們確認
# 它們指向的是同一個物件
Simple Assignment
shoplist is ['mango', 'carrot', 'banana']
mylist is ['mango', 'carrot', 'banana']
print('Copy by making a full slice')

# 通過生成一份完整的切片製作一份列表的副本
shoplist = ['apple', 'mango', 'carrot', 'banana']

mylist = shoplist[:]
del mylist[0]

print('shoplist is', shoplist)
print('mylist is', mylist)

# 注意到現在兩份列表已出現不同
Copy by making a full slice
shoplist is ['apple', 'mango', 'carrot', 'banana']
mylist is ['mango', 'carrot', 'banana']

有關字串的更多內容

  • startswith 方法用於查詢字串是否以給定的字串內容開頭。
  • in 運算子用以檢查給定的字串是否是查詢的字串中的一部分。
  • find 方法用於定位字串中給定的子字串的位置。如果找不到相應的子字串, find會返回 -1。
  • str 類同樣還擁有一個簡潔的方法用以 聯結(Join) 序列中的專案,其中字串將會作為每一專案之間的分隔符,並以此生成並返回一串更大的字串。
'''
有關字串的更多內容

'''
# 這是一個字串物件
name = 'Swaroop'

if name.startswith('Swa'):
    print('Yes, the string starts with "Swa"')

if  'a' in name:
    print('Yes, it contains the string "a"')

if name.find('war') != -1:    
    print('Yes, it contains the string "war"')

delimiter = '_*_'    
mylist = ['Brazil', 'Russia', 'India', 'China']
print(delimiter.join(mylist))

Yes, the string starts with "Swa"
Yes, it contains the string "a"
Yes, it contains the string "war"
Brazil_*_Russia_*_India_*_China

問題

我們希望解決的問題如下:

我想要一款程式來備份我所有的重要檔案。

分析(Analysis)— 例如,我們應該如何指定哪些檔案是我們需要備份
的?它們應該如何進行備份?儲存到哪裡?

設計(Design)

  • 需要備份的檔案與目錄應在一份列表中予以指定。
  • 備份必須儲存在一個主備份目錄中。
  • 備份檔案將打包壓縮成 zip 檔案。
  • zip 壓縮檔案的檔名由當前日期與時間構成。
  • 我們使用在任何 GNU/Linux 或 Unix 發行版中都會預設提供的標準 zip 命令進行打包。
  • 在這裡你需要了解到只要有命令列介面,你就可以使用任何需要用到的壓縮或歸檔命令。
'''
第一版


'''

import os
import time

# 1. 需要備份的檔案與目錄將被
# 指定在一個列表中。
# 例如在 Windows 下:
# source = ['"C:\\My Documents"', 'C:\\Code']
# 又例如在 Mac OS X 與 Linux 下: source = ['/Users/swa/notes']

source = ["D:\\github\\python\\Deep-Learning\\python\\source"]

# 在這裡要注意到我們必須在字串中使用雙引號
# 用以括起其中包含空格的名稱。

#2. 備份檔案必須儲存在一個
#主備份目錄中
#例如在 Windows 下:
# target_dir = 'E:\\Backup'
# 又例如在 Mac OS X 和 Linux 下:target_dir = '/Users/swa/backup'
target_dir = 'E:\\qqfile\\backup'

# 要記得將這裡的目錄地址修改至你將使用的路徑

# 3. 備份檔案將打包壓縮成 zip 檔案。
# 4. zip 壓縮檔案的檔名由當前日期與時間構成。
target = target_dir + os.sep + time.strftime('%Y%m%d%H%M%S') + 'zip'

# 如果目標目錄還不存在,則進行建立

if not os.path.exists(target_dir):
    os.mkdir(target_dir) # 建立目錄

# 5. 我們使用 zip 命令將檔案打包成 zip 格式
zip_command = 'zip -r {0} {1}'.format(target,' '.join(source))

# 執行備份   
print('Zip command is:')
print(zip_command)
print('Running:')
if os.system(zip_command) == 0:
    print('Successful backup to', target)
else:
    print('Backup Failed')

Zip command is:
zip -r E:\qqfile\backup\20180313152803zip D:\github\python\Deep-Learning\python\source
Running:
Successful backup to E:\qqfile\backup\20180313152803zip

os.sep 變數的使用方式——它將根據你的作業系統給出相應的分隔符,在
GNU/Linux 與 Unix 中它會是 ‘/’ ,在 Windows 中它會是 ‘\’ ,在 Mac OS 中它會是’:’ 。

第二版

我們的第一版指令碼已經能夠工作了。然而,我們還可以對它作出一些改進,從而使它能夠更好地在每一天都可以正常工作。我們將這一階段稱之為軟體的維護(Maintenance)階段。

我認為有一種頗為有用的改進是起用一種更好的檔案命名機制——使用時間作為檔名,儲存在以當前日期為名字的資料夾中,這一資料夾則照常儲存在主備份目錄下。
- 這種機制的第一個優點在於你的備份會以分層的形式予以儲存,從而使得它們能更易於管理。
- 第二個優點是檔名能夠更短。
- 第三個優點在於由於只有當天進行了備份才會建立相應的目錄,獨立的目錄能夠幫助你快速地檢查每天是否都進行了備份。

'''
第2版

'''

import os
import time

# 1. 需要備份的檔案與目錄將被
# 指定在一個列表中。
# 例如在 Windows 下:
# source = ['"C:\\My Documents"', 'C:\\Code']
# 又例如在 Mac OS X 與 Linux 下: source = ['/Users/swa/notes']

source = ["D:\\github\\python\\Deep-Learning\\python\\source"]

# 在這裡要注意到我們必須在字串中使用雙引號
# 用以括起其中包含空格的名稱。

#2. 備份檔案必須儲存在一個
#主備份目錄中
#例如在 Windows 下:
# target_dir = 'E:\\Backup'
# 又例如在 Mac OS X 和 Linux 下:target_dir = '/Users/swa/backup'
target_dir = 'E:\\qqfile\\backup'

# 要記得將這裡的目錄地址修改至你將使用的路徑

if not os.path.exists(target_dir):
    os.mkdir(target_dir) # 建立目錄

# 3. 備份檔案將打包壓縮成 zip 檔案。
# 4. 將當前日期作為主備份目錄下的子目錄名稱
today = target_dir + os.sep + time.strftime('%Y%m%d')
# 將當前時間作為 zip 檔案的檔名
now = time.strftime('%H%M%S')
# 如果目標目錄還不存在,則進行建立

# zip 檔名稱格式
target = today + os.sep + now +'.zip'

if not os.path.exists(today):
    os.mkdir(today) # 建立目錄
    print('Successfully created directory', today)

# 5. 我們使用 zip 命令將檔案打包成 zip 格式
zip_command = 'zip -r {0} {1}'.format(target,' '.join(source))

# 執行備份   
print('Zip command is:')
print(zip_command)
print('Running:')
if os.system(zip_command) == 0:
    print('Successful backup to', target)
else:
    print('Backup Failed')

Successfully created directory E:\qqfile\backup\20180313
Zip command is:
zip -r E:\qqfile\backup\20180313\154421.zip D:\github\python\Deep-Learning\python\source
Running:
Successful backup to E:\qqfile\backup\20180313\154421.zip

第三版

第二版在我要製作多份備份時能夠正常工作,但當備份數量過於龐大時,我便很難找出備份之間有什麼區別了。例如,我可能對我的程式或者簡報做了重大修改,然後我想將這些修改與 zip 檔案的檔名產生關聯。這可以通過將使用者提供的註釋內容新增到檔名中來實現。

預先提醒:下面給出的程式將不會正常工作,所以不必驚慌,只需跟著案例去做因為你要在裡面學上一課。

'''
第3版

'''

import os
import time

# 1. 需要備份的檔案與目錄將被
# 指定在一個列表中。
# 例如在 Windows 下:
# source = ['"C:\\My Documents"', 'C:\\Code']
# 又例如在 Mac OS X 與 Linux 下: source = ['/Users/swa/notes']

source = ["D:\\github\\python\\Deep-Learning\\python\\source"]

# 在這裡要注意到我們必須在字串中使用雙引號
# 用以括起其中包含空格的名稱。

#2. 備份檔案必須儲存在一個
#主備份目錄中
#例如在 Windows 下:
# target_dir = 'E:\\Backup'
# 又例如在 Mac OS X 和 Linux 下:target_dir = '/Users/swa/backup'
target_dir = 'E:\\qqfile\\backup'

# 要記得將這裡的目錄地址修改至你將使用的路徑

if not os.path.exists(target_dir):
    os.mkdir(target_dir) # 建立目錄

# 3. 備份檔案將打包壓縮成 zip 檔案。
# 4. 將當前日期作為主備份目錄下的子目錄名稱
today = target_dir + os.sep + time.strftime('%Y%m%d')
# 將當前時間作為 zip 檔案的檔名
now = time.strftime('%H%M%S')
# 如果目標目錄還不存在,則進行建立

# 新增一條來自使用者的註釋以建立
# zip 檔案的檔名
comment = input('Enter a comment -->')
# 檢查是否有評論鍵入

if len(comment) == 0:
    target = today + os.sep + now + '_' + comment.replace(' ','_') + '.zip'
else:
    target = today + os.sep + now + '_' + 
    comment.replace(' ','_') + '.zip'


if not os.path.exists(today):
    os.mkdir(today) # 建立目錄
    print('Successfully created directory', today)

# 5. 我們使用 zip 命令將檔案打包成 zip 格式
zip_command = 'zip -r {0} {1}'.format(target,' '.join(source))

# 執行備份   
print('Zip command is:')
print(zip_command)
print('Running:')
if os.system(zip_command) == 0:
    print('Successful backup to', target)
else:
    print('Backup Failed')

  File "<ipython-input-2-a0cbe1ca32a2>", line 47
    target = today + os.sep + now + '_' +
                                          ^
SyntaxError: invalid syntax

它是如何(不)工作的

這個程式它跑不起來!Python 會說程式之中存在著語法錯誤,這意味著指令碼並未擁有 Python期望看見的結構。當我們觀察 Python 給出的錯誤時,會看見它同時也告訴我們它檢測到錯誤的地方。所以我們開始從那個地方開始對我們的程式進行 Debug 工作。仔細觀察,我們會發現有一獨立的邏輯行被分成了兩行物理行,但我們並未指定這兩行物理行應該是一起的。基本上,Python 已經發現了該邏輯行中的加法運算子( + )沒有任何運算元,因此它不知道接下來應當如何繼續。因此,我們在程式中作出修正。當我們發現程式中的錯誤並對其進行修正時,我們稱為“錯誤修復(Bug Fixing)”。

'''
第 4 版

'''

import os
import time

# 1. 需要備份的檔案與目錄將被
# 指定在一個列表中。
# 例如在 Windows 下:
# source = ['"C:\\My Documents"', 'C:\\Code']
# 又例如在 Mac OS X 與 Linux 下: source = ['/Users/swa/notes']

source = ["D:\\github\\python\\Deep-Learning\\python\\source"]

# 在這裡要注意到我們必須在字串中使用雙引號
# 用以括起其中包含空格的名稱。

#2. 備份檔案必須儲存在一個
#主備份目錄中
#例如在 Windows 下:
# target_dir = 'E:\\Backup'
# 又例如在 Mac OS X 和 Linux 下:target_dir = '/Users/swa/backup'
target_dir = 'E:\\qqfile\\backup'

# 要記得將這裡的目錄地址修改至你將使用的路徑

if not os.path.exists(target_dir):
    os.mkdir(target_dir) # 建立目錄

# 3. 備份檔案將打包壓縮成 zip 檔案。
# 4. 將當前日期作為主備份目錄下的子目錄名稱
today = target_dir + os.sep + time.strftime('%Y%m%d')
# 將當前時間作為 zip 檔案的檔名
now = time.strftime('%H%M%S')
# 如果目標目錄還不存在,則進行建立

# 新增一條來自使用者的註釋以建立
# zip 檔案的檔名
comment = input('Enter a comment -->')
# 檢查是否有評論鍵入

if len(comment) == 0:
    target = today + os.sep + now + '_' + comment.replace(' ','_') + '.zip'
else:
    target = today + os.sep + now + '_' +\
    comment.replace(' ','_') + '.zip'


if not os.path.exists(today):
    os.mkdir(today) # 建立目錄
    print('Successfully created directory', today)

# 5. 我們使用 zip 命令將檔案打包成 zip 格式
zip_command = 'zip -r -v {0} {1}'.format(target,' '.join(source))

# 執行備份   
print('Zip command is:')
print(zip_command)
print('Running:')
if os.system(zip_command) == 0:
    print('Successful backup to', target)
else:
    print('Backup Failed')

# 這裡沒有錯誤的,原書中給出的是 帶有錯誤的示例 for bug fixing
Enter a comment -->test
Zip command is:
zip -r -v E:\qqfile\backup\20180314\102221_test.zip D:\github\python\Deep-Learning\python\source
Running:
Successful backup to E:\qqfile\backup\20180314\102221_test.zip
'''
第 5 版

使用 zipfile 
'''

軟體開發流程

  1. What/做什麼(分析)
  2. How/怎麼做(設計)
  3. Do It/開始做(執行)
  4. Test/測試(測試與修復錯誤)
  5. Use/使用(操作或開發)
  6. Maintain/維護(改進)

面向物件程式設計

self

你一定會在想 Python 是如何給 self 賦值的,以及為什麼你不必給它一個值。一個例子或許會讓這些疑問得到解答。假設你有一個 MyClass 的類,這個類下有一個例項 myobject 。當你呼叫一個這個物件的方法,如myobject.method(arg1, arg2) 時,Python 將會自動將其轉換成 MyClass.method(myobject, arg1, arg2) ——這就是 self 的全部特殊之處所在。這同時意味著,如果你有一個沒有引數的方法,你依舊必須擁有一個引數—— self

class Person:
    pass

p = Person()
print(p)
<__main__.Person object at 0x000001C5D62DEE10>
class Person:
    def say_hi(self): # 這個引數 self 是必須有的
        print('Hello,how are you?')

p = Person()
p.say_hi()
Hello,how are you?

init_ 方法

__init__方法會在類的物件被例項化(Instantiated)時立即執行。這一方法可以對任何你想進行操作的目標物件進行初始化(Initialization)操作。這裡你要注意在 init 前後加上的雙下劃線。

class Person:
    def __init__(self, name):
        self.name = name

    def say_hi(self):
        print('Hello, my name is', self.name)

p = Person('Hinton')        
p.say_hi()

Person('Jack').say_hi()
Hello, my name is Hinton
Hello, my name is Jack

類變數與物件變數

我們已經討論過了類與物件的功能部分(即方法),現在讓我們來學習它們的資料部分。資料部分——也就是欄位——只不過是繫結(Bound)到類與物件的名稱空間(Namespace)的普通變數。這就代表著這些名稱僅在這些類與物件所存在的上下文中有效。這就是它們被稱作“名稱空間”的原因。

欄位(Field)有兩種型別——類變數與物件變數,它們根據究竟是類還是物件擁有這些變數來進行分類。
類變數(Class Variable)是共享的(Shared)——它們可以被屬於該類的所有例項訪問。

該類變數只擁有一個副本,當任何一個物件對類變數作出改變時,發生的變動將在其它所有例項中都會得到體現。

物件變數(Object variable)由類的每一個獨立的物件或例項所擁有。在這種情況下,每個物件都擁有屬於它自己的欄位的副本,也就是說,它們不會被共享,也不會以任何方式與其它不同例項中的相同名稱的欄位產生關聯。

# coding=UTF-8

class Robot:
    """表示有一個帶有名字的機器人。"""

    # 一個類變數,用來計數機器人的數量
    population = 0

    def __init__(self, name):
        """初始化資料"""
        # 物件變數          
        self.name = name
        print('(Initializing {})'.format(self.name))

        # 當有人被建立時,機器人
        # 將會增加人口數量
        Robot.population +=1

    def die(self):
        """我掛了。"""
        print('{} is being destroyed!'.format(self.name))

        Robot.population -= 1

        if Robot.population == 0:
            print('{} was the last one.'.format(self.name))
        else:
            print("There are still {:d} robots working.".format(Robot.population))


    def say_hi(self):
        """來自機器人的誠摯問候

        沒問題,你做得到。"""
        print("Greetings, my masters call me {}".format(self.name))


    @classmethod
    def how_many(cls):
        """打印出當前的人口數量"""
        print("we have {:d} robots.".format(cls.population))


droid1 = Robot("R2-D2")        
droid1.say_hi()
Robot.how_many()

droid2 = Robot('C-3PO')
droid2.say_hi()
Robot.how_many()


print("\nRobots can do some work here.\n")

print("Robots have finished their work. So let's destroy them.")

droid1.die()
droid2.die()

Robot.how_many()
(Initializing R2-D2)
Greetings, my masters call me R2-D2
we have 1 robots.
(Initializing C-3PO)
Greetings, my masters call me C-3PO
we have 2 robots.

Robots can do some work here.

Robots have finished their work. So let's destroy them.
R2-D2 is being destroyed!
There are still 1 robots working.
C-3PO is being destroyed!
C-3PO was the last one.
we have 0 robots.
print(Robot.__doc__)
Robot.say_hi.__doc__
表示有一個帶有名字的機器人。





'來自機器人的誠摯問候\n\n        沒問題,你做得到。'

繼承

面向物件程式設計的一大優點是對程式碼的重用(Reuse),重用的一種實現方法就是通過繼承(Inheritance)機制。繼承最好是想象成在類之間實現型別與子型別(Type and Subtype)關係的工具。

SchoolMember 類會被稱作基類(Base Class) 或是超類(Superclass)。 Teacher 和 Student 類會被稱作派生