practice
Python都是物件
,或說是把任何資料包裝成物件,以型別區分
python assign 決定claas 型態 // 重要概念
a = 1 # class int 型態
a = 1.1 # class float 型態
a = 'hello' # class str 型態
常用 type() 看物件型態 , id() 看記憶體位址 , repr??
Print a string as hex bytes
For Python 2.x:
':'.join(x.encode('hex') for x in 'Hello World!')
The code above will not work with Python 3.x, for 3.x, the code below will work:
':'.join(hex(ord(x))[2:] for x in '中文')
hex(ord('中')) # python3 str 預設是 unicode 編碼
In [25]: text = '中文' # python3 str 預設是 unicode 編碼
In [26]: b_str = text.encode('big5') # 轉成 bytes
In [27]: b_str
Out[27]: b'\xa4\xa4\xa4\xe5'
In [31]: unicode_str = b_str.decode('big5') # 從 big5 的 byts decode 回 str python3 str 預設是 unicode 編碼
In [32]: unicode_str
Out[33]: '中文'
In [34]: ':'.join(hex(ord(x))[2:] for x in unicode_str) # 查看 unicode bytes 格式
Out[34]: '4e2d:6587'
Python五種基本資料結構型態 list set dictionary tuple string
- 不可變(mutable) :建立之後,其值就不會改變。如「 3 + 5 」會建立新int物件
- 不可變: int、float、str、tuple
- 可變(immutable):建立後,其內容仍可改變 ex : 可變:list
Python中的元組(Tuple)類似於Java中的陣列,一旦新增了一個 tuple,就不能以任何方式改變它
。
string是一種不可變的數據 跟 tuple 一樣是不可變動
列表(list) 列表是Python中最具靈活性的有序集合物件類型
,與字串不同的是,列表可以包含任何種類的物件:數字,字串,甚至是其他列表.並且列表都是可變物件,它支持在原處修改的操作.也可以通過指定的索引和分片獲取元素.列表就可元組的可變版本.
TOOL OnlinePythonTutor
git clone https://github.com/pgbovine/OnlinePythonTutor
pip install bottle # make sure the bottle webserver (http://bottlepy.org/) is installed
cd OnlinePythonTutor/v5-unity/
python bottle_server.py
http://localhost:8003/live.html#mode=edit // 開啟
深拷貝
,完全拷貝了一個副本,容器內部元素地址都不一樣
談談python中的深拷貝和淺拷貝
https://zhuanlan.zhihu.com/p/25221086
python中的深拷貝和淺拷貝和java裡面的概念是一樣的,所謂淺拷貝就是對引用的拷貝
,
所謂深拷貝就是對對象的資源的拷貝
。
Python程式的基本執行單位是「模組」,簡單 地說就是Python程式檔案 // 重要
最小的執行單位是「述句」,述句可由分號「;」隔開,但非必要
([:]則是作淺層複製,只不過對字串這種不可變動的物件沒有實質意義)
[::-1]表示從索引0至結尾,以負偏移1方式取得字串,結果就是反轉字串。 // 技巧重要
常見錯誤訊息
TabError: inconsistent use of tabs and spaces in indentation // 格式沒對好
>>>type(None)
<class 'NoneType'>
表示該值是一個空對象,空值是Python裡一個特殊的值,用None表示。
None不能理解為0,因為0是有意義的,而None是一個特殊的空值。
>>>type('')
<class ''str'>
你可以將None賦值給任何變量,也可以將任何變量賦值給一個None值得對象
None、0、0.0、空字串「''」、空list或空tuple
(或空的容器),會被當做「False」(假) 其餘皆會被當做「True」(真)
成員關係運算子
成員關係運算子「in、not in」, 檢查某物件(元素)是否在容器裡
# 常用
同等關係運算子「is、is not」,檢查兩個名稱是否指向同一個物件
# 常用 id() 驗證是不是指向同個記憶體位址
not '0' 等於acsii 48 所以為真
'0'為真,反轉後為假
not 0 # True
not '' # True 空字串
not () # True
not [] # True
not {} # True
not set() # True
型別NoneType,唯一值None None用來代表:沒有、尚未定義、無效
x = 100; y = 50 bigger = x if x > y else y
找出三數字之最大的那一個
a, b, c = 3, 5, 7; x = None
(c if b < c else b) if a < b else (c if a < c else a)
上下等價
a, b, c = 3, 5, 7; x = None
if a < b:
if b < c:
x = c
else:
x = b
else:
if a < c:
x = c
else:
x = a
del述句:刪除名稱,連帶刪除與 物件之間的綁定關係
垃圾收集機制(garbage collection)
>>> a = 3
>>> del a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
for loop and while loop 等價只是應用點不同
i = 1
x = 0
while i <= 100:
x += i
i += 1
print(x)
x = 0
for i in range(1,101):
x += i
i += 1
print(x)
所謂「能提供一串東西的物件」,目前僅知是 list、tuple、str, dict
後續再詳細介紹
for 名稱 in `能提供一串東西的物件`:
述句
d = {'x': 1, 'y': 2, 'z': 3}
for key in d:
print key, 'corresponds to', d[key]
內建函式range
range(3)產生出"物件", 能提供0、1、2
break述句:
立即跳出迴圈(最近的那一層)
scores = (98, 87, 59, 64, 77)
# 預設All Pass
all_pass = True
for x in scores:
if x < 60:
all_pass = False
break
if all_pass:
print('passed')
else:
print('no all pass')
continue述句:
跳到下一輪
# 算大於60的平均
scores = (55, 73, 81, 65, 95, 34)
n = 0
high_total = 0
for x in scores:
if x < 60:
continue
n += 1
high_total += x
high_total /= n
print(high_total)
編碼 !!! 重要
這是因為 Python 3.x 中,python 直譯器預期的 .py 編碼,預設是 UTF-8
,而在 Ubuntu 15.10 中,預設採用的文字編碼也是 UTF-8,這時在 .py 檔案中撰寫中文,並不會有問題發生,然而,你知道在 Windows 中,使用記事本編輯文字檔案時,預設的文字編碼是什麼嗎?
關於Python腳本開頭兩行的
http://www.itread01.com/content/1501168823.html
有順序問題必須要下面這樣
#!/usr/bin/python
# -*- coding: utf-8 -*-
#!/usr/bin/python
是用來說明腳本語言是 python 的 是要用 /usr/bin下面的程序(工具)python,這個解釋器,來解釋 python 腳本,來運行 python 腳本的。
2、# -*- coding: utf-8 -*-
是用來指定文件編碼為 utf-8 的 ,
具體如何聲明python文件編碼?
對此格式的詳細解釋是:
如果沒有此文件編碼類型的聲明,則 python2 默認以ASCII編碼去處理
;如果你沒聲明編碼,但是文件中又包含非ASCII編碼的字符的話,python解析器去解析
的 python 文件
,自然就會報錯了。
必須放在python文件的第一行或第二行
開檔讀取寫入
Python使用open()打開檔案
f = open('檔案', '模式')
模式有
r - 讀取(檔案需存在)
w - 新建檔案寫入(檔案可不存在,若存在則清空)
a - 資料附加到舊檔案後面(遊標指在EOF)
r+ - 讀取舊資料並寫入(檔案需存在且遊標指在開頭)
w+ - 清空檔案內容,新寫入的東西可在讀出(檔案可不存在,會自行新增)
a+ - 資料附加到舊檔案後面(遊標指在EOF),可讀取資料
b - 二進位模式
Python 逐行讀取檔案內容
#!/usr/bin/python
## Open file
fp = open('filename.txt', "r")
line = fp.readline()
## 用 while 逐行讀取檔案內容,直至檔案結尾
while line:
print(line)
line = fp.readline()
fp.close()
使用 with as
#!/usr/bin/python
with open(filename.txt,'r') as fp:
all_lines = fp.readlines()
with之後的運算式傳回的物件,可以使用as指定給變數來參考,在上面的例子中,file所參考到的物件,最後會被自動關閉,即使在with as的區塊中發生了例外,最後一定會關閉file所參考的物件
。
Python 與中文處理 http://web.ntnu.edu.tw/~samtseng/present/Python_and_Chinese.pdf
測試檔案中文文字是Big5編碼
ubuntu內建的文字編輯器gedit存檔時選檔案->另存新檔->字元編碼->繁體中文(big5)
在 Python 程式中,讀入中文文字檔案時,也要事先知道該檔案的編碼方式,才能正確讀取。例如:
file_big5 = open('Big5File.txt', 'r', encoding='big5')
file1_big5 = open('Big5File1.txt', 'w', encoding='big5')
file_utf8 = open("UTF8File.txt", "w", encoding="utf-8")
for line in file_big5:
print(line) # line 是 str 型態python3預設 unicode
print(line.encode('utf-8'))
file_utf8.write(line)
file1_big5.write(line)
file_big5.close()
file1_big5.close()
file_utf8.close()
with open("Big5File.txt", 'r', encoding='big5') as fp:
for line in fp:
print(line)
物件導向三大特色
資料封裝(Encapsulation)
簡單講,資料封裝就是將資料分成私用(Private)、保護(Protected)、公用(Public)等,實踐 Information hiding 概念,
避免程式各個物件互相干擾
,降低程式的複雜度及維護上的困難度。繼承(Inheritance)
有繼承的關係後,父類別 (Super class) 中的資料 (Data) 或方法 (Method) 在次子類(Subclass)就可以繼承使用,次子類別的次子類別也可以繼承使用,最後即能達到資料重覆使用的目的。
多型(Polymorphism)
多型(Polymorphism) 代表能夠在執行階段,物件能夠依照不同情況變換資料型態,換句話說,多型是指一個物件參考可以在不同環境下,扮演不同角色的特性,指向不同的物件實體,可 透過實作多個繼承或介面來實現父類別,並使用Override或Overload來達成。
封裝、繼承、多型為物件導向三大基礎 。 此三者具有次序性 , 沒有封裝就不可能有繼承 、沒有繼承就不可能有多型
。
封裝 (encapsulation) 的目的是將 Class 裡的屬性用 private 隱藏,只能透過public的方法存取資料。
(隱藏程式細節,避免直接處理造成的困擾。使開發與維護更容易)
繼承 (Inheritance) 的目的,是要達到「程式碼再用」(Code Rause) 或「介面再用」。
透過繼承,可以適當的切割類別,並在衍生類別中重複使用、擴充和修改基底類別中定義的行為,又不破壞原先基底類別設計
。
多型 (Polymorphism) 指的是不同型態的物件,定義相同的操作介面,由於被呼叫者 (Callee) 有著相同的介面,呼叫者並不用指定特別型別,只需針對介面進行操作,實際執行的物件則在runtime決定,藉此增加程式碼的彈性。
何謂物件(Object)?
https://developer.mozilla.org/zh-TW/docs/Learn/Drafts/Python/Quickly_Learn_Object_Oriented_Programming 創建物件就像是創造你自己的變數型別(variable type)。
這個物件可以包含好幾個變數(稱為屬性,attributes/properties),裡面儲存不同型別的資料。這個物件也可以包含已經自己設定好的函式(稱為 methods),用於操作物件的屬性。
你可以用同一個型別去創建很多個物件(同一個類別),每個物件都有屬於自己的數值
。
類別( Class ),就是一個抽象的模板
,
實例(Instance)就是根據這個模板創造出來的資訊,像是王先生、蔡小姐等具體的對象,每個對象擁有相同的方法
,但是各自所擁有的資料能不同
。
class BankAccount:
""" Class for Bank Accounts"""
type = 'Normal Account' # variable shared by all objects of the class
# 這個特殊的方法 __init__() 會在物件被創見時自動執行。
def __init__(self, name):
# default variables unique to each object:
self.userName = name
self.balance = 0.0
# Object Methods:
def showBalance(self):
print(self.balance)
return
def withdrawMoney(self, amount):
self.balance -= amount
return
def depositMoney(self, amount):
self.balance += amount
return
if __name__ == '__main__':
object1 = BankAccount("Jason Yao") # create new instance of ClassName
object2 = BankAccount("Adan Yao") # create another instance
# access object properties
print(object1.userName) #'Im 1'
print(object2.userName) #'Me 2'
# access object methods
object1.depositMoney(100)
object2.depositMoney(200)
print(object1.balance) # 'Im 1'
print(object2.balance) # 'Me 2'
# same as:
object1.showBalance() # 100
object2.showBalance() # 200
print(object1.type) # 'Normal Account'
print(object2.type) # 'Normal Account'
python 物件導向「Class 」與「Instance」
物件導向第一個特性:封裝 物件導向的一個重要的特點就是封裝。在上面 Animal 的這個類別當中,每個實例就擁有自己的 Name 、 sound 、 age 這些資訊,我們可以通過一些函數來呼叫這些資訊,舉例來說,想要聽到這個動物的叫聲: print(Dog.sound)
# -*- coding: utf-8 -*-
class Animal(object):
"""
宣告一個抽象的類別 Animal
"""
# __init__是 python 當中的一個特殊方法,可以在一開始時,就將這個累所需要的屬性綁定,我們稱之為初始化
def __init__(self, age, sound, name):
"""
假設動物有三種屬性,年齡,叫聲,姓名,當然你也可以舉更多屬性
"""
self.age = age
self.sound = sound
self.__name = name
# 初始化屬性之後,動物可能會有一些動作,我們可以把它看成物件導向當中的方法( Method )
def run(self):
'''動物跑步的方法'''
pass
def Animal_sounds(self):
'''動物叫的方法'''
print("叫聲:" + self.sound)
if __name__ == '__main__':
# 這樣我們就創造了一隻 叫做 jj 的狗 ,年齡是 18 歲,叫的聲音是 wof
Dog = Animal('8', '汪', '拉西') # The Dog is instance
Dog.Animal_sounds()
Cat = Animal('5', '喵', '病貓')
Cat.Animal_sounds()
多型
class Demo:
def __init__(self, i):
self.i = i
def __str__(self):
return str(self.i)
def hello(self):
print("hello " + self.__str__())
class SubDemo1(Demo):
def __init__(self, i, j):
super().__init__(i)
self.j = j
def __str__(self):
return super().__str__() + str(self.j)
class SubDemo2(Demo):
def __init__(self, i, j):
super().__init__(i)
self.j = j
self.k = str(self.i) + str(self.j)
def __str__(self):
return self.k
a = SubDemo1(22, 33)
b = SubDemo2(44, "55")
a.hello()
b.hello()
SubDemo1 與 SubDemo2 繼承 (inherit) 自 Demo ,因此兩個子類別也都繼承了 hello() 方法 (method) ,雖然 SubDemo1 與 SubDemo2 所建立的物件各自是不同型態,然而由繼承關係兩種型態可通用 hello() 。
在如何確定一個物體的大小?
答案,"只使用 sys.getsizeof"不是完全完整的答案。 這對於直接的內置對象是有效的,但它並不解釋它們可能包含什麼,特別是數字和字元串之外的類型。
模組
Python 程式裡的 name 可以用來分辨程式是直接執行還是被 import 的
角色不同
原來如果一個 python script 是被別的 python script 當成 module 來 import 的話
,那麼這個被 import 的 python script 的 name 就會是那個 python script 的名稱。而如果這個 python script 是直接被執行的話,__name__ 就會是 __main__
。
if __name__ == '__main__':
doSomething()
Python 提供的 module(模組)與 package(套件)是建立架構的基本元件,但在module之間為了重複使用一些 function(函數)或 class(類別)而必須互相 import(匯入),使用上一個不注意就會掉入混亂的 import 陷阱。
sample_package/
├── __init__.py
├── sample_module.py
└── sample_module_import.py
from sample_module import sample_func
if __name__ == '__main__':
sample_func()
在 Python 中,import、import as 與 from import 是陳述句,可以出現在程式中陳述句可出現的任何位置,它們基本上用來在現有範疇(Scope)中匯入、設定名稱空間,舉例來說,如果先前程式範例是撰寫於 xmath.py 檔案中,那麼以下是一些 import、import as 與 from import 的使用實例,假設這些程式是撰寫在與 xmath.py 相同目錄的另一個 .py 檔案:
- xmath.py
def max(a, b):
return a if a > b else b
def min(a, b):
return a if a < b else b
def sum(*numbers): # numbers 接受可變長度引數
total = 0
for number in numbers:
total += number
return total
pi = 3.141592653589793
e = 2.718281828459045
import xmath
print '# import xmath'
print xmath.pi
print xmath.max(10, 5)
print xmath.sum(1, 2, 3, 4, 5)
print '# import xmath as math'
import xmath as math # 為 xmath 模組取別名為 math
print math.e
print '# from xmath import min'
from xmath import min # 將 min 複製至目前模組,不建議 from modu import *,易造成名稱衝突
print min(10, 5)