Python 程式設計入門 - 01

Pyladies Taiwan

Speaker : Mars

2017/09/17

Roadmap

  • Python 簡介
  • 第一支Python程式
  • 物件命名、型別轉換
  • 輸入與輸出
  • 布林型別、比較&邏輯運算
  • 判斷式
  • 更多數值型別
  • 知識補充
  • 進位與位元運算

Python 簡介

  • 簡潔易懂
  • 要求程式碼寫作風格
  • 可以做很多事情

應用

  • [網路爬蟲]:urllib、requests、lxml、beautiful_soup、scrapy、selenium
  • [資料庫串接]:sqlite3(sqlite)、MySQLdb(MySQL)、pymssql(MSSQL)、Psycopg(PostgreSQL)
  • [自然語言]:NLTK、jieba
  • [統計應用]:pandas、numpy、scipy、matplotlib
  • [機器學習]:scikit-learn、TensorFlow
  • [影像處理]:PIL、opencv
  • [網站架設]:Django、Flask
  • [網路分析]:scapy
  • [GUI設計]:tkinter、PyQt
  • [軟硬整合]:raspberry pi 樹莓派、Arduino
  • [遊戲開發]:pygame
  • [App開發]:kivy
  • [各種服務的API串接]:Bot

程式設計

幫我們自動化處理事情,減少重複或大量計算的動作

程式設計 Roadmap

  • [基礎學習]:物件、型別、命名、判斷式、迴圈、函式、類別、模組、檔案IO、例外處理
  • [進階技巧]:Effective Python
  • [各種應用]

接下來會用到的環境

[練習] 第一支Python程式

Hacker Rank

基礎數值型別

  • 整數 integer:int
  • 浮點數 float:float
  • 運算元+ - * / // % **
  • 在Python裡面整數interger可以儲存的位數,取決於電腦記憶體有多大
In [1]:
print(10+3)  # 加法
print(10-3)  # 減法
print(10*3)  # 乘法
print(10/3)  # 除法
print(10//3) # 除法(取整數,無條件捨去)
print(10%3)  # 取餘數
print(10**3) # 次方
13
7
30
3.3333333333333335
3
1
1000

現在的舉例是10跟3的各種運算, 那如果我想換成55跟5呢?

物件命名

In [2]:
a=10
b=3
print(a+b)  # 加法
print(a-b)  # 減法
print(a*b)  # 乘法
print(a/b)  # 除法
print(a//b) # 除法(取整數,無條件捨去)
print(a%b)  # 取餘數
print(a**b) # 次方
13
7
30
3.3333333333333335
3
1
1000
  • 在Python程式中「=」可以想像成是「貼標籤」的意思
  • 在右邊的「物件」(資料內容)存放位置貼上左邊「名稱」的標籤,亦即名稱指向物件。
  • 可以讓物件(資料內容)重複利用,程式碼可以更為簡潔
    • Python有垃圾收集(garbage collection)機制,沒有名稱指向的物件會被回收
a=10
url = "http://blog.marsw.tw"
  • a、url 都是自行命名的物件
  • 可以命名的字元:_、0~9、a~Z (中文也行,但不建議)

特別注意!!!

  • 不能以數字開頭
  • 不能與保留字相同
  • 好的命名方式會讓程式碼容易閱讀
    • xyz = "http://blog.marsw.tw" vs.
      url = "http://blog.marsw.tw"

保留字

andasassertbreakclass
continuedefdelelifelse
exceptfinallyforfromglobal
ifimportinislambda
nonlocalnotorpassraise
returntrywhilewithyield
NoneFalseTrueexecprint

In [3]:
a=3
b=a
print(id(a),id(b))
a=4
print(id(a),id(b))
10105888 10105888
10105920 10105888

物件型別

  • type(物件):印出此物件的型別
In [4]:
my_score = 96
pi = 3.14159
url = "http://blog.marsw.tw"

print(type(my_score))
print(type(pi))
print(type(url))
print(type(print))
<class 'int'>
<class 'float'>
<class 'str'>
<class 'builtin_function_or_method'>

在Python3中,所有東西都是物件!!!

Python 是一個動態性的語言

  • 同樣的物件可以隨時更動他的型別
In [5]:
my_score = 96
print(type(my_score))

my_score = 96.0
print(type(my_score))

my_score = "96"
print(type(my_score))
<class 'int'>
<class 'float'>
<class 'str'>

字串(string)

  • 可以直接給定詞句
  • 也可以給空白句
  • 可以相+、相*
In [6]:
my_string = "Hi"
my_string2 = ""
my_string2 = my_string2 + "Py" + 'Ladies'
my_string3 = "Hello"*4

print (my_string)
print (my_string2)
print (my_string3)
Hi
PyLadies
HelloHelloHelloHello

!注意

  • 用「成對的」雙引號"或是單引號',將字串包住

!注意

  • 字串與數值不可一同運算
In [7]:
my_string = "123"
my_int_number = 456
print (my_string+my_int_number)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-7-151fbba3d316> in <module>()
      1 my_string = "123"
      2 my_int_number = 456
----> 3 print (my_string+my_int_number)

TypeError: Can't convert 'int' object to str implicitly

型別轉換

  • int(物件):將物件轉成整數(integer)型別
  • float(物件):將物件轉成浮點數(float)型別
  • str(物件):將物件轉成字串(string)型別

!注意

  • 字串轉數字,需要符合整數、浮點數的格式
In [8]:
input1 = 123
input2 = "456"
input3 = "5566.123"
print (str(input1)+input2)
print (input1+int(input2))
print (float(input3)+input1)
print (int(input3))
123456
579
5689.123
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-8-347d8eaf9d2b> in <module>()
      5 print (input1+int(input2))
      6 print (float(input3)+input1)
----> 7 print (int(input3))

ValueError: invalid literal for int() with base 10: '5566.123'

內建函式-格式化輸出

  • round(數值,n):取小數點後n位,靠近偶數
In [9]:
print(round(1.5)) # 1.5 在1和2中間,最靠近的偶數是2
print(round(2.5)) # 2.5 在2和3中間,最靠近的偶數是2
2
2
In [10]:
pi = 3.14159
pi_2 = round(pi,2)
print (pi_2)
3.14

內建函式-數值運算

  • pow(x,y):x的y次方向
  • pow(x,y,z):x的y次方向除以z的餘數
  • divmod(被除數,除數):回傳商與餘數
  • abs(數值):取絕對值
In [11]:
print(pow(10,3))
print(pow(10,3,3))
print(divmod(10,3))
print(abs(10-15))
1000
1
(3, 1)
5

運算元的簡潔寫法

  • a+= ba = a+b
  • a-= ba = a-b
  • a*= ba = a*b
In [12]:
count = 0
count+= 1 
print (count)
count*= 3
print (count)
count-= 2
print (count)
1
3
1

計算機

想要計算一個數字的兩倍值、平方後的值,
可能會像這樣寫法

__ = __
print ("a*2=", ____ )
print ("a^2=", ____ )
In [13]:
a = 3
print ("a*2=",a*2)
print ("a^2=",a**2)
a*2= 6
a^2= 9

上面例子是計算3的兩倍值、平方值,
但如果我今天想要計算5的兩倍值、平方值呢?
我就要再把程式的第一行改掉

In [14]:
a = 5
print ("a*2=",a*2)
print ("a^2=",a**2)
a*2= 10
a^2= 25

這對已經會寫程式的你,這或許不是難事,
但假設你希望把你寫的好用程式也讓其他人能使用呢?

如果有個跟我們平常在用的計算機一樣,
可以有個介面輸入數字、想要運算的方式,
程式就能產生我想要的結果,好像很不錯~

輸入與輸出

  • input(提示字):從鍵盤輸入值
    • 輸入的值會儲存為字串型別
  • print(物件):輸出物件到螢幕上
    • 可以用,印出多個物件(印出後,會以空格分隔物件)
In [15]:
a = input("a=")    # "a=" 是提示字,讓我們知道電腦在等我們輸入
b = input("b=")
print ("a+b=",a+b) # input進來是字串
a=5
b=2
a+b= 52
In [16]:
a = input("a=")    # "a=" 是提示字,讓我們知道電腦在等我們輸入
b = input("b=")
print ("a+b=",a+b) # input進來是字串
a=Hello
b=PyLadies
a+b= HelloPyLadies

input()可以讓我們跟電腦互動
而不單單只是讓電腦print()東西出來而已

互動的計算機

In [17]:
a = input("a=") # "a=" 是提示字,讓我們知道電腦在等我們輸入
a = int(a)      # input進來是字串,要做數值運算要用int()轉換   
# 以上也可以簡寫為 a = int(input("a="))
print ("a*2=",a*2)
print ("a^2=",a**2)
a=5
a*2= 10
a^2= 25

問候機器人

In [18]:
a = input("請問你的名字是? ") 
print ("你好",a)      # 用,分隔會印出空格
# print("你好"+a)     # 可以用字串相加,就不會有空格
請問你的名字是? Mars
你好 Mars

[練習] 數值運算

Hacker Rank

注意

  • Hacker Rank 印出的格式要完全一樣
    • 所以不能有「提示字」,該換行的也要換行
  • Hacker Rank 的測試就像有人在對你的程式輸入不同的數字
    • 所以不能把程式寫死(直接印出範例的結果)
    • 假設希望你做出加法的功能:
      • 輸入3+5要得到8
      • 下一次可能會輸入6+7,結果應該是13
      • 正確的程式就是不管輸入什麼數字,都能執行出兩個數相加的結果

布林型別、比較&邏輯運算

布林型別

  • True
  • False

比較運算

  • 產生的結果為bool布林型別
  • <, <=, >, >=, ==, !=
In [19]:
print(10>3)
print(10==3) #<左邊的物件>「是否等於」<右邊的物件>  
print(10!=3) #不等於
print(10<=3)
print("Hi"=="hi")
True
False
True
False
False

邏輯運算

  • 產生的結果為bool布林型別
  • and:左右物件都為True=>True
  • or:左右物件其一為True=>True
  • not:反轉True/False
In [20]:
print(10>3 and 10==3)
print(10>3 or 10==3)
print(not 10==3)
False
True
True

內建函數-型別判定

  • isinstance(數值,型別):產生的結果為bool布林型別
In [21]:
print(isinstance(222,int))
print(isinstance(3.14,int))
print(isinstance(3.14,float))
print(isinstance('3.14',str))
True
False
True
True

布林型別轉換

可以用來判斷常見的型別是否有資料

  • 數值是否不等於0
  • 字串是否有值
  • ...
In [22]:
print(bool(""), bool(0))
print(bool(-1), bool(0.01), bool(1), bool("Hi"))
False False
True True True True

判斷式:if/elif/else

  • if是判斷式必備的
    • if:一種選項,滿足條件,才執行某動作
    • elif:有更多條件,滿足的話執行某動作,須伴隨if存在
    • else:當以上條件都不滿足,執行某動作,須伴隨if存在
if 布林型別:
    如果布林型別==True,就做這裡面的事情
In [23]:
# 基本的判斷式是由 if 構成
a = 61
if a>=60:
    print ("及格")
及格
In [24]:
# 不符合條件,因此什麼都沒有印出
a = 58
if a>=60:
    print ("及格")
In [25]:
# 如果希望處理判斷條件之外的狀況,可以用else
a = 58
if a>=60:
    print ("及格")
else:
    print ("不及格")
不及格

Python是靠「縮排」(四個空格),來斷定程式碼屬於那一個區塊。
if/else 後面記得要有:

In [26]:
a = 11
b = 8
if a>b:
    print ("a>b")
elif a<b:
    print ("a<b")
else:
    print ("a<=b")
print ("這是判斷式外的區塊")
a>b
這是判斷式外的區塊

如果有很多個條件,一個if不夠用,可以用elif

!注意

  • Python是靠「縮排」(四個空格),來斷定程式碼屬於那一個區塊
  • if/elif/else 後面記得要有:
In [27]:
a = 11
b = 8
# 第1組判斷式
if a%2==0:
    print ("a is even")
# 第2組判斷式
if a>b:
    print ("a>b")
elif a<b:
    print ("a<b")
else:
    print ("a==b")
a>b
  • 一個 if 就是一組判斷式
  • 兩組判斷式是不互相影響的
    • 如果 a = 11, b = 8
      第1組判斷式沒有符合任何條件就什麼事都不會做,
      第2組判斷式會印出a>b,不受到第1組判斷式沒有任何條件符合的影響
    • 如果 a = 6, b = 8
      第1組判斷式會印出a is even
      第2組判斷式會印出a<b

想想看

以下狀況是要用幾組判斷式呢?

  • 聊天機器人、Siri...
  • 商店打折可以共用優惠的...
In [28]:
keyword = "我想吃飯"

if keyword=="我想吃飯":
    print("建議你可以吃??")
    
elif keyword=="天氣如何":
    print("今天的天氣...")
    
elif keyword=="7-11":
    print("最近的7-11在oo")
    
else:
    print("我聽不懂你在說什麼")
建議你可以吃??

如果有很多個條件,一個if不夠用,可以用elif,
一個elif不夠用,可以繼續用很多個elif

應該沒有看過Siri回答你今天天氣之後,又說我聽不懂你在說什麼吧?

In [29]:
cost = 1000
gift = ""
# 第1組判斷式
if cost>=500:   # 滿500,送購物袋
    gift = gift+"購物袋"
# 第2組判斷式
if cost>=1000:  # 滿1000折100
    cost = cost-100
print(cost)
print(gift)
900
購物袋

[練習] 判斷式

Hacker Rank

更多數值型別

  • 浮點數float型別是用二進位表示,所以無法精確的表示
    • 比較的話要用誤差值
In [30]:
n= 0.1 + 0.2
print (n)
print (n==0.3, abs(n-0.3)<0.0001)
print(0.1+0.1+0.1-0.3)
0.30000000000000004
False True
5.551115123125783e-17

十進位數 Decimal

from decimal import *

  • 可以有最精確的數值表示
In [31]:
from decimal import *
d1 = Decimal(0.1)
d2 = Decimal('0.1')
print(d1)
print(d2)
0.1000000000000000055511151231257827021181583404541015625
0.1
In [32]:
f = 0.1+0.1+0.1-0.3
D = Decimal
d3 = D('0.1')+D('0.1')+D('0.1')-D('0.3')
print(f)
print(d3)
5.551115123125783e-17
0.0

如果想表示 1/3 呢?

分數 Fraction

from fractions import *

  • Fraction(分子,分母):分子分母需為非浮點數float的數值型別
  • Fraction(物件)
In [33]:
from fractions import *
fr1 = Fraction(1,3)
fr2 = Fraction('1/3')
print(fr1,fr2,fr1+fr1+fr1)
1/3 1/3 1
In [34]:
F = Fraction
print(F(16,10))       # 會自動約分
print(F(F(1,3),F(1,2)))
8/5
2/3

複數 complex

In [35]:
a = 5+7j
b = 5+7J
c = complex(5,7)
d = complex('5+7j')
print (a,type(a))
print (b,type(b))
print (c,d)
(5+7j) <class 'complex'>
(5+7j) <class 'complex'>
(5+7j) (5+7j)
In [36]:
print (complex('5 + 7j')) # 字串不能有空格
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-36-94f607a2ca5c> in <module>()
----> 1 print (complex('5 + 7j')) # 字串不能有空格

ValueError: complex() arg is a malformed string

複數運算

  • 和一般數值一樣可以加減乘除、次方、判斷是否相等
  • 不能比大小、取餘數、整除
In [37]:
a = 4+3j
b = 2+5j
print(a+b,a-b)
print(a*b,a/b)
print(a==b)
print(a>b)
(6+8j) (2-2j)
(-7+26j) (0.793103448275862-0.48275862068965514j)
False
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-37-eac484fb1260> in <module>()
      4 print(a*b,a/b)
      5 print(a==b)
----> 6 print(a>b)

TypeError: unorderable types: complex() > complex()

絕對值 abs()

In [38]:
a = 4+3j
print(abs(a))               # 絕對值,複數的模

# 直角三角形 a^2 + b^2 = c^2  
import math
print(math.sqrt(4**2+3**2)) # 取整數的平方根

import cmath
print(cmath.sqrt(a))        # 取複數的平方根
5.0
5.0
(2.1213203435596424+0.7071067811865476j)

計算弧度 cmath.phase()

In [39]:
import math
a = complex(1,math.sqrt(3))         # 1+3j

import cmath
print(cmath.phase(a))               # 弧度
print(cmath.phase(a)*180/math.pi)   # 角度
print(math.degrees(cmath.phase(a))) # 角度

# 角數 * pi /180 = 弧度   
# 60 * 3.14159 / 180 ≒ 1.0471967
1.0471975511965976
59.99999999999999
59.99999999999999

數值相關模組

記得要先import

  • math:pi, sqrt, gcd, log, floor, acos, ...
  • cmath:phase, ...

[練習] 計算絕對值與弧度

Hacker Rank

知識補充

運算優先順序

越上面越優先

[a,b,c] 字串轉換、串列、tuple、字典、集合
x[index], x[i1:i2], x(parameter), x.attr 索引、切片、函式呼叫、存取屬性項
** 次方
+x, -x, ~x 正數、負數、位元NOT運算
*, /, //, % 乘法、除法、餘數、字串格式化
+, - 加法、減法
>>, << 位元位移運算
& 位元AND運算
^ 位元XOR運算
| 位元OR運算
in, is, <, ==, > 比較運算
not x 布林NOT邏輯運算
and 布林AND邏輯運算
or 布林OR邏輯運算
if/else 條件運算式
lambda lambda運算式
In [40]:
print(3+5*4-8/2)
19.0
In [41]:
a=5
b=5
c=2
# (c==3) or (a==b and (not a==3)) or (b==4)
if c==3 or a==b and not a==3 or b==4: 
    print ("1")
else:
    print ("2")
1

!建議

可以用()來方便閱讀,也能確保自己的想法是正確的

  • (c==3) or (a==b and (not a==3)) or (b==4)
  • ((c==3) or (a==b)) and ((not a==3) or (b==4))

條件運算式

x if y else z:當y為True,運算的結果是x,否則是z

In [42]:
# 如果x是奇數,就保留原值,否則-1
x = 9
result = x if (x%2==1) else x-1  
print(result)
9
In [43]:
# 如果資料為空,設為預設值
x = ""
result = x if x else "Hi"
print(result)
Hi

小心無限大的數值

In [44]:
a = 3e400  # 浮點數 3*10^400
print(a)
print(a/999999, a*-2, 5/a)
print(a/(a/2), a/a)

import math
print(math.sqrt(a),math.sqrt(a/a))
inf
inf -inf 0.0
nan nan
inf nan
  • nan:代表不具意義的數學運算
  • inf:無限大

進位與位元運算

世界上只有10種人,懂二進位和不懂的

電腦會用二進位運算原因是因為穩定、實踐容易,運算速度較快,
而使用十六進位是方便表示太大的數字(eg. 色碼、記憶體位置),
但實務上,我們還是比較習慣用十進位。

可以把這章節當成額外讀物,了解電腦以及生活中進位的運作方式,
並不一定要熟悉裡面所有的語法~

計算機為何使用二進位

各種進位的轉換

  • bin(整數物件):轉換成2進位
  • oct(整數物件):轉換成8進位
  • hex(整數物件):轉換成16進位
  • int(整數物件):轉換成10進位
  • int(字串,以多少進位解讀):預設為10進位,如果寫0則是以字串的格式為準。
In [45]:
print(int(100), bin(100), oct(100), hex(100))
print(0xFFFFFF, int(0xFFFFFF), int('0xFFFFFF',16))
print(int('144',0), int('0o144',0), int('0x64',0))
100 0b1100100 0o144 0x64
16777215 16777215 16777215
144 100 100

位元運算子

  • 會將數字以二進位表示進行各種運算
  • ~x:NOT,0與1互換,等同於-(x+1)
  • x&y:AND,x,y在同個位元都為1,該位元才會為1
  • x|y:OR,x,y在同個位元只要其一為1,該位元才會為1
  • x^y:XOR,x,y在同個位元都不同,該位元才會為1
  • x<<y:x每個位元往左位移y次,右手邊新的位元補0,等同於 x*(2**y)
  • x>>y:x每個位元往右位移y次,等同於 x//(2**y)
In [46]:
# int(3) = bin(11)  11
# int(2) = bin(10)  10
print(3&2)  # AND   10
print(3|2)  # OR    11
print(3^2)  # XOR   01
2
3
1
In [47]:
# int(3) = bin(11)   11 -> 110      bin(110) = int(6)
#                            ^ 補零
print (3<<1)
6

二補數表示法

  • 位元反轉~x會是-(x+1)
  • 由於Python的整數幾乎可以到無限位數
    • 正數:左邊無限個0
    • 負數:左邊無限個1
十進位 二進位(4個位元表示) 二進位(8個位元表示)
4 0100 0000 0100
3 0011 0000 0011
2 0010 0000 0010
1 0001 0000 0001
0 0000 0000 0000
-1 1111 1111 1111
-2 1110 1111 1110
-3 1101 1111 1101
-4 1100 1111 1100
In [48]:
a = 2
print(~2)
-3

[總練習]

  • 物件、命名、型別
  • 判斷式
  • 各種數值型別、進位方式

判斷是否為閏年

  • 西元年份可被400整除
  • 西元年份可被4整除,但不能被100整除
  • 西元2000年、2060年都是閏年,但1900、2057不是

範圍轉換

遊戲中的角色能力值想從 0~255 轉換到 0~100:

  • 能力良好:200-255 vs. 85-100
  • 能力差勁:0-130 vs. 0-60

在做資料視覺化也有可能會把0~n的數值轉換成色碼表示!

學習資源對應

  • Python 程式設計入門 (適用於 2.x 與 3.x 版) 葉難

    • 02 開始撰寫Python 程式
      • 2.1 名稱、物件、型別、指派
        • 不包含: 串列、可變與不可變、tuple
      • 2.2 運算式
        • 不包含: 串列運算、is、in
      • 2.3 運算式述句、指派述句、if條件判斷述句
      • 2.4 內建函式(部分)
    • 03 數值型別
      • 不包含: 3.2, 3.4
  • The Python Standard Library(Python 3.6.2)

    • 2. Built-in Functions
    • 3. Built-in Constants
    • 4. Built-in Types (4.1~4.5)