類的繼承案例解析,python相關知識延伸
作者:白寧超
2016年10月10日22:36:57
摘要:繼<快速上手學python>一文之后,筆者又將python官方文檔認真學習下。官方給出的pythondoc入門資料包含了基本要點。本文是對文檔常用核心要點進行梳理,簡單冗余知識不再介紹,作者假使你用c/java/c#/c++任一種語言基礎。本系列文章屬于入門內容,老鳥可以略看也可以略過,新鳥可以從篇一<快速上手學python>先接觸下python怎樣安裝與運行,以及pycharm編輯器的使用和配置;篇二<數據結構看python>介紹python語言中控制語句、列表、字典、元組、循環等基本操作;篇三<函數修行知python>細解python語言函數的范疇與內容;篇四<模塊異常談python>采用登錄的案例詳解模塊來龍去脈;篇五<‘類’過依然繼續前行,直至ending再出發>介紹類的基本操作,擴展虛擬環境、標準類庫和下個系列預告。(本文原創,轉載注明出處:類的繼承案例解析,python相關知識延伸)
目錄:
【Python五篇慢慢彈(1)】快速上手學python
【Python五篇慢慢彈(2)】數據結構看python
【Python五篇慢慢彈(3)】函數修行知python
【Python五篇慢慢彈(4)】模塊異常談python
【Python五篇慢慢彈(5)】‘類’過依然繼續前行,直至ending再出發
1 類的相關介紹
【小記】本文中所有代碼經過測試均可正常運行,python有個問題就是復制后會破壞原有格式。所以讀者復制運行時報如下錯誤:SyntaxError: expected an indented block,是因為空格問題,可以預留4個空格,或者采用tab鍵空格,本篇也是系列文章的結束,除了類的相關介紹,后面擴展一些獨立的知識點,下一個系列將是python自然語言處理系列文章,敬請期待......
命名空間 :從命名到對象的映射。當前命名空間主要是通過 Python 字典實現的.Python 中任何一個“.”之后的命名可以理解為屬性 --例如,表達式 z.real 中的 real 是對象 z 的一個屬性。如:
表達式 modname.funcname 中,modname 是一個模塊對象,funcname 是它的一個屬性
因此,模塊的屬性和模塊中的全局命名有直接的映射關系:它們共享同一命名空間,作用域 是一個 Python 程序可以直接訪問命名空間的正文區域。至少有三個命名空間可以直接訪問的作用域嵌套在一起,包含局部命名的使用域在最里面,首先被搜索;其次搜索的是中層的作用域,這里包含了同級的函數;最后搜索最外面的作用域,它包含內置命名。global 語句用以指明某個特定的變量為全局作用域,并重新綁定它。nonlocal 語句用以指明某個特定的變量為封閉作用域,并重新綁定它。
作用域和命名空間示例
def scope_test():def do_local():spam = "local spam"def do_nonlocal():nonlocal spamspam = "nonlocal spam"def do_global():global spamspam = "global spam"spam = "test spam"do_local()print("After local assignment:", spam)do_nonlocal()print("After nonlocal assignment:", spam)do_global()print("After global assignment:", spam)scope_test()
print("In global scope:", spam)
運行結果:
解析:
local 賦值語句是無法改變 scope_test 的 spam 綁定。nonlocal 賦值語句改變了 scope_test 的 spam 綁定,并且 global 賦值語句從模塊級改變了 spam 綁定。
類的正確設計應該使用一個實例變量
class Dog:def __init__(self, name):self.name = nameself.tricks = [] # creates a new empty list for each dogdef add_trick(self, trick):self.tricks.append(trick)
d = Dog('Fido')
d.add_trick('roll over')
print(d.tricks)
R運行結果:
E:\Python\python.exe E:/sourceCode/pydata/AddPro/MothedDome.py
['roll over']
Process finished with exit code 0
命名空間:
①大寫方法名稱的首字母,使用一個唯一的小字符串(也許只是一個下劃線)作為數據屬性名稱的前綴,或者方法使用動詞而數據屬性使用名詞。
②類不能用來實現③數據類型。
③一般,方法的第一個參數被命名為 self。這僅僅是一個約定:對 Python 而言,名稱 self 絕對沒有任何特殊含義。
④函數定義代碼不一定非得定義在類中:也可以將一個函數對象賦值給類中的一個局部變量。例如:
通過 self 參數的方法屬性,方法可以調用其它的方法:
class Bag:def __init__(self):self.data = []def add(self, x):self.data.append(x)def addtwice(self, x):self.add(x)self.add(x)
2、類繼承實例解析
?
實例分析:在python中類繼承案例,要求如下:
① 創建一個BaseSubDome.py文件,編寫類繼承文件
② 父類是動物類,有初始化函數,且有動物講話的方法
③ 子類是一個狗類,繼承父類所有屬性,并擴展自己方法
④ 調用子類講話方法,并直接調用父類講話方法
類繼承實例:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
__title__ = ''
__author__ = 'cuitbnc'
__mtime__ = '2016/10/9'
# 歡迎進入我的主頁:http://www.cnblogs.com/baiboy/.
"""
class BaseAnimal:def __init__(self,name,age):self.name=nameself.age=ageprint("this is 【 %s 】 and is BaseClass." %(self.name))def speak(self):print("my name is【 %s 】,age is 【 %d 】" %(self.name,self.age))class SubDog(BaseAnimal):def __init__(self,name,age,say):BaseAnimal.__init__(self,name,age)self.say=sayprint("this SubClass is 【 %s 】."%(self.name))print('_'*20+'調用子函數方法'+'_'*20)def talk(self):BaseAnimal.speak(self)print("my name is 【 %s 】,today I 【 %d 】 years,I want say 【 %s 】" %(self.name,self.age,self.say))ani=SubDog('dog',12,'汪汪...')
print(ani.talk())
print('_'*20+'直接調用父函數方法'+'_'*20)
BaseAnimal('tom',13).speak()
運行結果:
?
解析:
__init__方法(雙下劃線):__init__方法在類的一個對象被建立時,馬上運行。這個方法可以用來對你的對象初始化 。注意,這個名稱的開始和結尾都是雙下劃線。
我們把__init__方法定義為取一個參數name(以及普通的參數self)。在__init__方法里,我們只是創建一個新的域,也稱為name。注意它們是兩個不同的變量,盡管它們有相同的名字。點號使我們能夠區分它們。最重要的是,在創建一個類的新實例的時候,把參數包括在圓括號內跟在類名后面,從而傳遞給__init__方法。這是這種方法的重要之處。現在,我們能夠在我們的方法中使用self.name域。給C++/Java/C#程序員的注釋__init__方法類似于C++、C#和Java中的constructor 。
3、python相關技術知識點擴展
?
python里面的私有變量與眾不同
在c/c#/Java中設置私有變量均為 private 標示。而python里面以一個下劃線開頭的命名(例如 _spam )會被處理為 API 的非公開部分(無論它是一個函數、方法或數據成員)。
它會被視為一個實現細節,無需公開。
迭代器工作原理
還記得這個for循環語句?
例如:
>>> for element in ['bnc','Tom','jack']:
print(element)bnc
Tom
jack
工作原理解析:采用迭代器機制。在后臺,for 語句在容器對象中調用 iter() 。返回一個定義了 __next__() 方法的迭代器對象,它在容器中逐一訪問元素。沒有后續的元素時,__next__() 拋出一個 StopIteration 異常通知 for 語句循環結束。以下是其工作原理的示例:
>>> elements=['bnc','Tom','jack']
>>> it=iter(elements)
>>> it
<list_iterator object at 0x03C06E90>
>>> next(it)
'bnc'
>>> next(it)
'Tom'
>>> next(it)
'jack'
>>> next(it)
Traceback (most recent call last):
File "<pyshell#11>", line 1, in <module>
next(it)
StopIteration
>>>
生成器工作原理
Generator 是創建迭代器的簡單而強大的工具。它們寫起來就像是正規的函數,需要返回數據的時候使用 yield 語句。
def reverse(data):
for index in range(len(data)-1, -1, -1):
yield data[index]
>>> for char in reverse('golf'):
... print(char)
...
f
l
o
g
前一節中描述了基于類的迭代器,它能作的每一件事生成器也能作到。因為自動創建了 __iter__() 和 __next__() 方法,生成器顯得如此簡潔。另一個關鍵的功能在于兩次執行之間,局部變量和執行狀態都自動的保存下來。這使函數很容易寫,而且比使用 self.index 和 self.data 之類的方式更清晰。除了創建和保存程序狀態的自動方法,當發生器終結時,還會自動拋出 StopIteration 異常。綜上所述,這些功能使得編寫一個正規函數成為創建迭代器的最簡單方法。
虛擬環境和包
Python 應用程序經常會使用一些不屬于標準庫的包和模塊。應用程序有時候需要某個特定版本的庫,意味著可能無法安裝一個 Python 來滿足每個應用程序的要求。如果應用程序 A 需要一個特定模塊的 1.0 版本,但是應用程序 B 需要該模塊的 2.0 版本,這兩個應用程序的要求是沖突的,安裝版本 1.0 或者版本 2.0 將會導致其中一個應用程序不能運行。這個問題的解決方案就是創建一個 虛擬環境 (通常簡稱為 “virtualenv”),包含一個特定版本的 Python,以及一些附加的包的獨立的目錄樹。不同的應用程序可以使用不同的虛擬環境。為了解決前面例子中的沖突,應用程序 A 可以有自己的虛擬環境,其中安裝了特定模塊的 1.0 版本。而應用程序 B 擁有另外一個安裝了特定模塊 2.0 版本的虛擬環境。如果應用程序 B 需求一個庫升級到 3.0 的話,這也不會影響到應用程序 A 的環境。
創建虛擬環境
用于創建和管理虛擬環境的腳本叫做 pyvenv。要創建一個 virtualenv,首先決定一個你想要存放的目錄接著運行 pyvenv 后面攜帶著目錄名:
pyvenv tutorial-env
如果目錄不存在的話,這將會創建一個 tutorial-env 目錄,并且也在目錄里面創建一個包含 Python 解釋器,標準庫,以及各種配套文件的 Python “副本”。一旦你已經創建了一個虛擬環境,你必須激活它。
在 Windows 上,運行:
tutorial-env/Scripts/activate
在 Unix 或者 MacOS 上,運行:
source tutorial-env/bin/activate
激活了虛擬環境會改變你的 shell 提示符,顯示你正在使用的虛擬環境,并且修改了環境以致運行 python 將會讓你得到了特定的 Python 版本。例如:
-> source ~/envs/tutorial-env/bin/activate
(tutorial-env) -> python
Python 3.5.2+ (3.4:c7b9645a6f35+, May 22 2015, 09:31:25)
...
>>> import sys
>>> sys.path
['', '/usr/local/lib/python35.zip', ...,
'~/envs/tutorial-env/lib/python3.5/site-packages']
>>>
?使用 pip 管理包
一旦你激活了一個虛擬環境,可以使用一個叫做 pip 程序來安裝,升級以及刪除包。默認情況下 pip 將會從 Python Package Index,<https://pypi.python.org/pypi>, 中安裝包。
你可以通過 web 瀏覽器瀏覽它們,或者你也能使用 pip 有限的搜索功能:
(tutorial-env) -> pip search astronomy
skyfield - Elegant astronomy for Python
gary - Galactic astronomy and gravitational dynamics.
novas - The United States Naval Observatory NOVAS astronomy library
astroobs - Provides astronomy ephemeris to plan telescope observations
PyAstronomy - A collection of astronomy related tools for Python.
pip 有許多子命令:“搜索”,“安裝”,“卸載”,“freeze”(譯者注:這個詞語暫時沒有合適的詞語來翻譯),等等。(請參考 installing-index 指南獲取 pip 更多完整的文檔。)
交互模式:
①錯誤處理
當錯誤發生時,解釋器打印一個錯誤信息和堆棧跟蹤。在交互模式下,它返回主提示符;當輸入來自文件的時候,在打印堆棧跟蹤后以非零退出(a nonzero exit)狀態退出。有些錯誤是非常致命的會導致一個非零狀態的退出;這也適用于內部錯誤以及某些情況的內存耗盡。所有的錯誤信息都寫入到標準錯誤流;來自執行的命令的普通輸出寫入到標準輸出。輸入中斷符(通常是 Control-C 或者 DEL)到主或者從提示符中會取消輸入并且返回到主提示。 當命令執行中輸入中斷符會引起 KeyboardInterrupt 異常,這個異常能夠被一個 try 聲明處理。
②可執行 Python 腳本
在 BSD’ish Unix 系統上,Python 腳本可直接執行,像 shell 腳本一樣,只需要把下面內容加入到#!/usr/bin/env python3.5(假設 python 解釋器在用戶的 PATH 中)腳本的開頭,并給予該文件的可執行模式。#! 必須是文件的頭兩個字符。在一些系統上,第一行必須以 Unix-style 的行結束符('\n')結束,不能以 Windows 的行結束符('\r\n')。 注意 '#' 在 Python 中是用于注釋的。使用 chmod 命令能夠給予腳本執行模式或者權限。
$ chmod +x myscript.py在 Windows 系統上,沒有一個 “可執行模式” 的概念。Python 安裝器會自動地把 .py 文件和 python.exe 關聯起來,因此雙擊 Python 將會把它當成一個腳本運行。文件擴展名也可以是 .pyw,在這種情況下,運行時不會出現控制臺窗口。
③交互式啟動文件
當你使用交互式 Python 的時候,它常常很方便地執行一些命令在每次解釋器啟動時。你可以這樣做:設置一個名為 PYTHONSTARTUP 的環境變量為包含你的啟動命令的文件名。這跟 Unix shells 的 .profile 特點有些類似。這個文件在交互式會話中是只讀的,在當 Python 從腳本中讀取命令,以及在當 /dev/tty 被作為明確的命令源的時候不只是可讀的。該文件在交互式命令被執行的時候在相同的命名空間中能夠被執行,因此在交互式會話中定義或者導入的對象能夠無需授權就能使用。你也能在文件中更改提示 sys.ps1 和 sys.ps2。如果你想要從當前目錄中讀取一個附加的啟動文件,你可以在全局啟動文件中編寫代碼像這樣:if os.path.isfile('.pythonrc.py'): exec(open('.pythonrc.py').read())。如果你想要在腳本中使用啟動文件的話,你必須在腳本中明確要這么做:
import os
filename = os.environ.get('PYTHONSTARTUP')
if filename and os.path.isfile(filename):with open(filename) as fobj:startup_file = fobj.read()exec(startup_file)
定制模塊
Python 提供兩個鉤子為了讓你們定制 sitecustomize 和 usercustomize。為了看看它的工作機制的話,你必須首先找到你的用戶 site-packages 目錄的位置。
啟動 Python 并且運行這段代碼:
>>> import site
>>> site.getusersitepackages()
'/home/user/.local/lib/python3.4/site-packages'
現在你可以創建一個名為 usercustomize.py 的文件在你的用戶 site-packages 目錄,并且在里面放置你想要的任何內容。它會影響 Python 的每一次調用,
除非它以 -s (禁用自動導入)選項啟動。sitecustomize 以同樣地方式工作,但是通常由是機器的管理員創建在全局的 site-packages 目錄中,并且是在 usercustomize 之前導入。請參閱 site 模塊獲取更多信息。
4、Python 標準庫概覽
?
操作系統接口
os 模塊提供了很多與操作系統交互的函數,我們先看幾個,然后help(os),等到哪天需要使用os開發再去深入研究方法的作用。os.getcwd() 查看當前工作路徑:
>>> import os
>>> os.getcwd()
'E:\\Python'
針對日常的文件和目錄管理任務,shutil 模塊,需要import shutil
help(os)查看下
文件通配符
glob 模塊提供了一個函數用于從目錄通配符搜索中生成文件列表:
>>> import glob
>>> glob.glob('*.py')
['primes.py', 'random.py', 'quote.py']
命令行參數
通用工具腳本經常調用命令行參數。這些命令行參數以鏈表形式存儲于 sys 模塊的 argv 變量。例如在命令行中執行 python demo.py one two three 后可以得到以下輸出結果:
>>> import sys
>>> print(sys.argv)
['demo.py', 'one', 'two', 'three']
?錯誤輸出重定向和程序終止
sys 還有 stdin, stdout 和 stderr 屬性,即使在 stdout 被重定向時,后者也可以用于顯示警告和錯誤信息:
>>> sys.stderr.write('Warning, log file not found starting a new one\n')
Warning, log file not found starting a new one
大多腳本的定向終止都使用 sys.exit()。
字符串正則匹配
re 模塊為高級字符串處理提供了正則表達式工具。對于復雜的匹配和處理,正則表達式提供了簡潔、優化的解決方案:
>>> import re
>>> re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest')
['foot', 'fell', 'fastest']
>>> re.sub(r'(\b[a-z]+) \1', r'\1', 'cat in the the hat')
'cat in the hat'
只需簡單的操作時,字符串方法最好用,因為它們易讀,又容易調試:
>>> 'tea for too'.replace('too', 'two')
'tea for two'
數學
math 模塊為浮點運算提供了對底層C函數庫的訪問:
>>> import math
>>> math.cos(math.pi / 4.0)
0.70710678118654757
>>> math.log(1024, 2)
10.0
random 提供了生成隨機數的工具:
>>> import random
>>> random.choice(['apple', 'pear', 'banana'])
'apple'
>>> random.sample(range(100), 10) # sampling without replacement
[30, 83, 16, 4, 8, 81, 41, 50, 18, 33]
>>> random.random() # random float
0.17970987693706186
>>> random.randrange(6) # random integer chosen from range(6)
4
SciPy <http://scipy.org> 項目提供了許多數值計算的模塊。
互聯網訪問
有幾個模塊用于訪問互聯網以及處理網絡通信協議。其中最簡單的兩個是用于處理從 urls 接收的數據的 urllib.request 以及用于發送電子郵件的 smtplib:
>>> from urllib.request import urlopen
>>> for line in urlopen('http://tycho.usno.navy.mil/cgi-bin/timer.pl'):
... line = line.decode('utf-8') # Decoding the binary data to text.
... if 'EST' in line or 'EDT' in line: # look for Eastern Time
... print(line)<BR>Nov. 25, 09:43:32 PM EST>>> import smtplib
>>> server = smtplib.SMTP('localhost')
>>> server.sendmail('soothsayer@example.org', 'jcaesar@example.org',
... """To: jcaesar@example.org
... From: soothsayer@example.org
...
... Beware the Ides of March.
?日期和時間
datetime 支持日期和時間算法的同時,實現的重點放在更有效的處理和格式化輸出。該模塊還支持時區處理。
>>> # dates are easily constructed and formatted
>>> from datetime import date
>>> now = date.today()
>>> now
datetime.date(2003, 12, 2)
>>> now.strftime("%m-%d-%y. %d %b %Y is a %A on the %d day of %B.")
'12-02-03. 02 Dec 2003 is a Tuesday on the 02 day of December.'>>> # dates support calendar arithmetic
>>> birthday = date(1964, 7, 31)
>>> age = now - birthday
>>> age.days
14368
?數據壓縮
以下模塊直接支持通用的數據打包和壓縮格式:zlib, gzip, bz2, lzma, zipfile 以及 tarfile。
>>> import zlib
>>> s = b'witch which has which witches wrist watch'
>>> len(s)
41
>>> t = zlib.compress(s)
>>> len(t)
37
>>> zlib.decompress(t)
b'witch which has which witches wrist watch'
>>> zlib.crc32(s)
226805979
?性能度量
解決同一問題的不同方法之間的性能差異。Python 提供了一個度量工具,為這些問題提供了直接答案。例如,使用元組封裝和拆封來交換元素看起來要比使用傳統的方法要誘人的多。timeit 證明了后者更快一些:
>>> from timeit import Timer
>>> Timer('t=a; a=b; b=t', 'a=1; b=2').timeit()
0.056634688316198646
>>> Timer('a,b = b,a', 'a=1; b=2').timeit()
0.029404588209626326
相對于 timeit 的細粒度,profile 和 pstats 模塊提供了針對更大代碼塊的時間度量工具。
瑞士軍刀
Python 展現了“瑞士軍刀”的哲學。這可以通過它更大的包的高級和健壯的功能來得到最好的展現。列如:
①xmlrpc.client 和 xmlrpc.server 模塊讓遠程過程調用變得輕而易舉。盡管模塊有這樣的名字,用戶無需擁有 XML 的知識或處理 XML。
②email 包是一個管理郵件信息的庫,包括MIME和其它基于 RFC2822 的信息文檔。
不同于實際發送和接收信息的 smtplib 和 poplib 模塊,email 包包含一個構造或解析復雜消息結構(包括附件)及實現互聯網編碼和頭協議的完整工具集。
③xml.dom 和 xml.sax 包為流行的信息交換格式提供了強大的支持。同樣, csv 模塊支持在通用數據庫格式中直接讀寫。綜合起來,這些模塊和包大大簡化了 Python 應用程序和其它工具之間的數據交換。
④國際化由 gettext, locale 和 codecs 包支持。
線程
線程是一個分離無順序依賴關系任務的技術。在某些任務運行于后臺的時候應用程序會變得遲緩,線程可以提升其速度。一個有關的用途是在 I/O 的同時其它線程可以并行計算。下面的代碼顯示了高級模塊 threading 如何在主程序運行的同時運行任務:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
__title__ = ''
__author__ = 'cuitbnc'
__mtime__ = '2016/10/9'
# 歡迎進入我的主頁:http://www.cnblogs.com/baiboy/.
"""
import threading, zipfileclass AsyncZip(threading.Thread):def __init__(self, infile, outfile):threading.Thread.__init__(self)self.infile = infileself.outfile = outfiledef run(self):f = zipfile.ZipFile(self.outfile, 'w', zipfile.ZIP_DEFLATED)f.write(self.infile)f.close()print('Finished background zip of:', self.infile)background = AsyncZip(r'C:\Users\cuitbnc\Desktop\testfile.txt', 'myarchive.zip')
background.start()
print('The main program continues to run in foreground.')background.join() # Wait for the background task to finish
print('Main program waited until background was done.')
運行結果:
?
?
?
6、參考文獻和推薦資料
- ?Python 官方網站 :包含代碼、文檔和 Web 上與 Python 有關的頁面鏈接該網站鏡像于全世界的幾處其它問題,類似歐洲、日本和澳大利亞。鏡像可能會比主站快,這取決于你的地理位置
- 快速訪問 Python 的文檔
- Python 包索引 :索引了可供下載的,用戶創建的 Python 模塊。如果你發布了代碼,可以注冊到這里,這樣別人可以找到它
- The Scientific Python : 項目包括數組快速計算和處理模塊,和大量線性代數、傅里葉變換、非線性solvers、隨機數分布,統計分析以及類似的包
- 官方python學習文檔
- 簡明Python教程
- 廖雪峰:python教程
- Python官網文檔
- 【51cto學院,入門課程】Python零基礎入門學習視頻教程
- 【個人博客:案例】GitHub數據提取與分析
- 【csdn】python知識庫
- 【社區】python中文學習大本營
- 【個人博客】老王python
- 【51cto學院】如何用python開發跨平臺的記事本視頻課程
- 【51cto學院,網站開發】臺灣輔仁大學:Python Django基礎視頻課程
- 【51cto學院,網站開發】用Python Django快速做出高大上的BBS論壇網站
?