Python 基本語法與科學計算套件的使用: Python 基礎(一)

四堂課程大綱

  • 第一堂-Python 基礎(一):Python 簡介及環境建立、Python程式的編寫及執行、資料型態、基本輸入輸出、流程控制
  • 第二堂-Python 基礎(二):檔案讀寫、例外處理、函數、模組、物件導向
  • 第三堂-Python科學計算套件(一):Numpy、Matplotlib
  • 第四堂-Python科學計算套件(二):Scipy、Astropy

Python 簡介

資料型態(整數、浮點數、複數、字串、布林值)及基本輸出輸入

  • Python的變數命名是會區分大小寫
  • 動態定型

In [1]:
# ←此為Python的註解符號,在這之後的文字不會被當作程式碼執行
# Python不用宣告變數型態,在指定變數的值時即會動態決定其型態
n_solar_mass = 10                                           # 整數
MASS_SUN = 1.99 * 10 ** 30                        # 浮點數
z = complex(3., -1.)                                          # 複數                  
unit  = "kg"                                                         #字串
yes = True                                                         #布林值
no = False                                                         #布林值
type(n_solar_mass)


Out[1]:
int
  • 基本輸出輸入

In [2]:
print("伴星的質量為:", n_solar_mass * MASS_SUN, unit)
perid = input("請輸入雙星軌道周期 (單位為秒) : ")


伴星的質量為: 1.99e+31 kg
請輸入雙星軌道周期 (單位為秒) : 72000
  • 強型別
  • 轉型

In [3]:
MASS_SUN + unit


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-3-9045cf533177> in <module>()
----> 1 MASS_SUN + unit

TypeError: unsupported operand type(s) for +: 'float' and 'str'

In [4]:
str(MASS_SUN) + unit


Out[4]:
'1.99e+30kg'
  • 對變數的操作

In [5]:
s = "Hello," + " " + "Python!"
#s.upper()
s.split()


Out[5]:
['Hello,', 'Python!']

資料型態(List、Tuple、Dictionary)

簡介

1. Tuple

  • 內容不可變

In [6]:
x = (1,2)
x


Out[6]:
(1, 2)

In [7]:
x[0] = 12  #無法更改內容


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-7-0bfb67b35805> in <module>()
----> 1 x[0] = 12  #無法更改內容

TypeError: 'tuple' object does not support item assignment
  • tuple 是有順序但不可以變動

In [8]:
# 延續上面範例

constants = (3.14159, 1.99 * 10 ** 30 ,  6.67 * 10 ** -11)   # tuple用小括號
print(constants)
constants.append(-342)


(3.14159, 1.99e+30, 6.67e-11)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-8-dffbb472e278> in <module>()
      3 constants = (3.14159, 1.99 * 10 ** 30 ,  6.67 * 10 ** -11)   # tuple用小括號
      4 print(constants)
----> 5 constants.append(-342)

AttributeError: 'tuple' object has no attribute 'append'

In [9]:
x = (10,11)
y = list(x) #把tuple製作成串列

In [10]:
y[0] = 20
y


Out[10]:
[20, 11]
  • list 是有順序且可以變動

In [11]:
slist = []
slist = ['A','B','C','D','E']
slist


Out[11]:
['A', 'B', 'C', 'D', 'E']

In [12]:
slist[0] = 'B'
slist


Out[12]:
['B', 'B', 'C', 'D', 'E']

In [13]:
# 延續上面範例

radial_velocity = [140, 220, 314, 244, 'km/s']    # list用中括號
print(radial_velocity[0])                                        # 元素的index從零開始
radial_velocity.append(-342)
radial_velocity.insert(2, 592)
print(radial_velocity)
print(len(radial_velocity))


140
[140, 220, 592, 314, 244, 'km/s', -342]
7
  • 雙重list

In [14]:
dlist = [['A','B','C','D','E'],[1,2,3,4,5]]
dlist[1]


Out[14]:
[1, 2, 3, 4, 5]

In [15]:
dlist[1][0]


Out[15]:
1
  • 須注意指定問題

In [16]:
a = [1,2,3]
a


Out[16]:
[1, 2, 3]

In [17]:
b = a
b


Out[17]:
[1, 2, 3]

In [18]:
b[0] = 10
b


Out[18]:
[10, 2, 3]

In [19]:
a # list a 中的數值也一起改變


Out[19]:
[10, 2, 3]

In [20]:
# 如何解決?
c = a[:]
c


Out[20]:
[10, 2, 3]

In [21]:
c[0] = 40
c


Out[21]:
[40, 2, 3]

In [22]:
a


Out[22]:
[10, 2, 3]
  • 判斷項目是否存在於list中 => in

In [23]:
clist = ['A','B','C','D','E']
'B' in clist


Out[23]:
True

In [24]:
'F' in clist


Out[24]:
False
  • 排序

In [25]:
wlist = ['D','A','F','C','E','D']
sorted(wlist)


Out[25]:
['A', 'C', 'D', 'D', 'E', 'F']

In [26]:
nlist = [4,23,1,3,2,98,3]
sorted(nlist)


Out[26]:
[1, 2, 3, 3, 4, 23, 98]
  • dictionary 是無順序且可以變動

In [27]:
dic = {'Jack':84,'Ben':63,'Cathy':76, 'Bob': 83}
dic


Out[27]:
{'Ben': 63, 'Bob': 83, 'Cathy': 76, 'Jack': 84}

In [28]:
dic['Jack']


Out[28]:
84

In [29]:
dic = {'Jack':[84,23,34],'Ben':[63,12,74],'Cathy':[12,43,76],'Bob': [83,81,90]} # key 不能放list value可以
dic


Out[29]:
{'Ben': [63, 12, 74],
 'Bob': [83, 81, 90],
 'Cathy': [12, 43, 76],
 'Jack': [84, 23, 34]}

In [30]:
dic['Jack']


Out[30]:
[84, 23, 34]

In [31]:
dic['Jack'] = [1,2,3]
dic


Out[31]:
{'Ben': [63, 12, 74],
 'Bob': [83, 81, 90],
 'Cathy': [12, 43, 76],
 'Jack': [1, 2, 3]}
  • 新增合併字典

In [32]:
dic.update({'William':[23,43,84],'Eric':[93,31,32]})
dic


Out[32]:
{'Ben': [63, 12, 74],
 'Bob': [83, 81, 90],
 'Cathy': [12, 43, 76],
 'Eric': [93, 31, 32],
 'Jack': [1, 2, 3],
 'William': [23, 43, 84]}
  • 判斷key是否存在

In [33]:
'Ben' in dic


Out[33]:
True

In [34]:
'William' in dic


Out[34]:
True
  • 取得key, value

In [35]:
dic.keys() #取得key not list


Out[35]:
dict_keys(['Bob', 'William', 'Jack', 'Eric', 'Ben', 'Cathy'])

In [36]:
dic.values() #取得value not list


Out[36]:
dict_values([[83, 81, 90], [23, 43, 84], [1, 2, 3], [93, 31, 32], [63, 12, 74], [12, 43, 76]])

In [37]:
dic.items() #取得所有的key, value not list


Out[37]:
dict_items([('Bob', [83, 81, 90]), ('William', [23, 43, 84]), ('Jack', [1, 2, 3]), ('Eric', [93, 31, 32]), ('Ben', [63, 12, 74]), ('Cathy', [12, 43, 76])])

In [38]:
# 延續上面範例

binaries = {'name':["GX 339-4","GRS 1915+105"], 'constants': constants}                   # dictionary用大括號
print(binaries['name'])
print(binaries['constants'])
binaries['mass'] = [ ]
print(binaries)


['GX 339-4', 'GRS 1915+105']
(3.14159, 1.99e+30, 6.67e-11)
{'mass': [], 'name': ['GX 339-4', 'GRS 1915+105'], 'constants': (3.14159, 1.99e+30, 6.67e-11)}
  • Slicing

In [39]:
print(radial_velocity[2:5])                        # [i:j] 從i開始到j-1
print(radial_velocity[:-2:3])                     # [i:j:k] 從i開始每隔k個到j-1


[592, 314, 244]
[140, 314]

流程控制:條件判斷式及迴圈

  • 依據某些條件(條件判斷式)或多次執行某個程式區塊(迴圈),來控制程式的執行流程
  • Python使用冒號及縮排來辨別程式區塊
  • if...else if...else 條件判斷式

In [40]:
if "GRS 1915+105" or "GX 339-4" in binaries['name']:
    print('They are microquasars!')
elif "XTE J1550-564" not in binaries['name']:
    print('XTE J1550-564 is not in the list!')
else:
    binaries['name'].append( input("請輸入下一個microquasars的名稱 : ") )
binaries['name']


They are microquasars!
Out[40]:
['GX 339-4', 'GRS 1915+105']
  • for 迴圈

In [41]:
# Basic example 1.
for i in range(10):
    print(i)


0
1
2
3
4
5
6
7
8
9

In [42]:
# Basic example 2.
arr = [1,3,5,7,9,2,4,6,8,10]
for i in arr:
    print(i)


1
3
5
7
9
2
4
6
8
10

In [43]:
microquasars = ["GRS 1915+105" , "GX 339-4"]
for m in microquasars:
    if m in binaries['name']:
        print(m, "is a microquasar!")
        
for i in range(2, 100, 20):
    print(i, i ** 2)


GRS 1915+105 is a microquasar!
GX 339-4 is a microquasar!
2 4
22 484
42 1764
62 3844
82 6724

In [44]:
# Plot a light curve example
# (Read a LMC X-4 archival data collecting by RXTE/PCA)


import numpy as np
data = np.loadtxt('../files4examples/Tcol_10135-01-01-000_gx0')  # a list of X-ray photon arrival times

# elements of data
n = len(data)

binsize = 20.0                                     # unit: sec
n_col = (data[n-1]-data[0]) // binsize + 1
bintime = np.arange(0, n_col)*binsize + data[0] + 0.5*binsize
crate = np.arange(0, n_col)*0.0                    # an empty array

## for-loop case a.
#for i in range(int(n_col)):
#    for j in range(n):
#        if (data[j] >= bintime[i]-0.5*binsize) and (data[j] < bintime[i]+0.5*binsize):
#            crate[i] = crate[i]+ 1.0
#crate = crate/binsize
## The value used in the function of 'range' must be a integral number.
## Or typing 'range?' to check.

## for-loop case b.
#for i in bintime:
#    for j in data:
#        if (j >= i-0.5*binsize) and (j < i+0.5*binsize):
#            crate[np.where(bintime == i)] = crate[np.where(bintime == i)] + 1.0
#crate = crate/binsize

## for-loop case c.
for i,val in enumerate(bintime):
    nn = np.where((data >= val - 0.5*binsize) & (data < (val + 0.5*binsize)))
    crate[i] = len(nn[0])
crate = crate/binsize


import matplotlib.pyplot as plt
%matplotlib inline
plt.plot(bintime,crate)
#plt.show()


Out[44]:
[<matplotlib.lines.Line2D at 0x111ae44e0>]
  • while 迴圈

In [45]:
# Basic example 
x = 10
while x > 0:
    print (x)
    x = x - 1


10
9
8
7
6
5
4
3
2
1

In [46]:
input_value = "yes"
while input_value == 'yes' :
    input_value = input("請輸入下一個microquasars的名稱,結束請輸入no : ")


請輸入下一個microquasars的名稱,結束請輸入no : no
  • break 及 continue

In [47]:
input_value == "yes"
while True :
    input_value = input("請輸入下一個microquasars的名稱,結束請輸入no : ")
    if input_value == "no":
        break


請輸入下一個microquasars的名稱,結束請輸入no : no

In [48]:
for i in range(2, 100, 20):
    if i == 2 or i == 42:
        continue
    print(i, i ** 2)


22 484
62 3844
82 6724

作業小專題

Mass function: $f(M) = \dfrac{M_2^3}{(M_1 + M_2)^2} \sin^3 i = \dfrac{P}{2\pi G} K_1^3$

利用google、ADS及書籍,儘可能搜尋數個X-ray雙星系統的以下資訊:伴星質量、軌道傾角、軌道周期、伴星的徑向速度,並寫一個程式能讓你能持續輸入雙星系統的名稱及上述資訊(直到你輸入no為止),並在程式中利用mass function計算出主星質量,且當主星質量大於三倍太陽質量時,印出"雙星系統名稱" + "的主星是黑洞"。