[TOC]
## 前言
題目來自TQC網站公開的參考試題,可以自行去搜尋相關詳情。
自己研究的解法,不一定是最好或最正確的,歡迎留言討論!
若對你有幫助請幫忙按讚以及留言,轉載請註明出處,畢竟也是花費時間心血想出來的。
希望對學習有幫助~~~ ^ O ^
順便用此機會練習用pylint改善code,使pylint可以達到滿分10分,來增加寫法的可讀性以及通用性
pylint是一種python 格式語法檢查器,其他還可以使用pyflakes或pep8。
試卷編號:PY3-0001
考試時間100分鐘,滿分100分,合格分數70分。
## 進入正題-TQC Python3 術科參考試題與參考解答
1. 數字、字串格式處理

* 參考答案
```PYTHON=
import math
def main():
num_list=[]
count = 0
print("Enter 1 to 4 digits below the decimal point")
while count< 4:
input_num = input('')
# limit input less or equal to 4 digits below the decimal point
# check not a symbol or char
# check enter total 4 numbers
if(len(input_num.split(".")[1])<=4 and float(input_num) and count<=4):
count+=1
num_list.append(input_num)
else:
print("Usage: Enter 1 to 4 digits below the decimal point")
quit()
# print num_list align to right
for i in range(0,4):
# display a float with two decimal places
list_num = str('%.2f'% float(num_list[i]))
if (i+1)%2!=0:
print("|", end="")
#str.rjust(align in n space)
print(list_num.rjust(7,' '),end="")
elif (i+1)%2==0:
print(list_num.rjust(8,' '), end="")
print("|")
# print num_list align to left
for i in range(0,4):
# display a float with two decimal places
list_num = str('%.2f'% float(num_list[i]))
if (i+1)%2!=0:
print("|", end="")
#str.rjust(align in n space)
print(list_num.ljust(8,' '),end="")
elif (i+1)%2==0:
print(list_num.ljust(7,' '), end="")
print("|")
main()
```
* result:

</br>
* 1st time scored by pylint

</br></br>
看起來很糟糕只有5.52分,查pylint doc改寫一下。
```python=
"""Module print 4 numbers align to left and right, having 7 spaces for each number"""
import sys
def main():
"""print out numbers formated as:
|....num.....num|
|....num.....num|
|num.....num....|
|num.....num....|"""
num_list=[]
count = 0
print("Enter 1 to 4 digits below the decimal point")
while count< 4:
input_num = input('')
if(len(str(float(input_num)).split(".")[1])<=4 and float(input_num) and count<=4):
count+=1
num_list.append(input_num)
else:
print("Usage: Enter 1 to 4 digits below the decimal point")
sys.exit()
# print num_list align to right, using str.rjust(align in n space)
for i in range(0,4):
# display a float with two decimal places
if (i+1)%2!=0:
print("|" + f"{float(num_list[i]):0.2f}".rjust(7,' '),end="")
elif (i+1)%2==0:
print(f"{float(num_list[i]):0.2f}".rjust(8,' ') + "|")
# print num_list align to left, using str.ljust(align in n space)
for i in range(0,4):
if (i+1)%2!=0:
print("|" + f"{float(num_list[i]):0.2f}".ljust(8,' '),end="")
elif (i+1)%2==0:
print(f"{float(num_list[i]):0.2f}".ljust(7,' ') + "|")
main()
```
* 再次確認輸出結果正確

* 不斷的改進後得到pylint新的評價為滿分




* 其他解法,盡量用f string的方式以及內建函式:
```python=
"""Using other expression"""
def main():
"""use format()"""
listnum = [input("") for _ in range(4)]
try:
check_if_number = [f'{float(string):0.2f}' for string in listnum]
# alternative: check_if_number = ['{:0.2f}'.format(float(string)) for string in listnum]
align_rtext = '|'+ '{:>7}' + '{:>8}' + '|'
align_ltext = '|'+ '{:<8}' + '{:<7}' + '|'
print(align_rtext.format(check_if_number[0], check_if_number[1]))
print(align_rtext.format(check_if_number[2], check_if_number[3]))
print(align_ltext.format(check_if_number[0], check_if_number[1]))
print(align_ltext.format(check_if_number[2], check_if_number[3]))
except ValueError:
print("Usage: Enter 4 numbers")
main()
```
</br></br></br>
2. 確認是否是某數的倍數__

</br>
* 參考答案
```PYTHON=
"""Module function checks the input number is multiply of 5 or 3 or both or neither"""
import sys
while True:
try:
input_num = int(input("Enter a positive integer: "))
if input_num % 5==0 or input_num%3==0:
if input_num % 5==0 and input_num%3==0:
print(f"{input_num}" +" "+"is a multiple of 3 and 5.")
elif input_num % 5==0:
print(f"{input_num }" +" "+"is a multiple 5.")
else:
print(f"{input_num }" +" "+"is a multiple 3.")
else:
print(f"{input_num }" +" "+"is not a multiple of 3 or 5.")
except ValueError:
sys.exit("Usage: Enter a positive integer")
```
增加功能:如果使用者輸入非整數(小數或符號),則會顯示"Usage: Enter a positive integer",並離開程式。
* result:

</br></br></br>
3. 迴圈偶數連加

* 參考答案
```python=
"""This module calculate sum range from input numbers, if it's even"""
import sys
def check_even(num):
"""check input number is even or odd"""
if num%2==0:
return True
return False
def main():
"""calculate and print sum"""
list_num=[]
try:
for _ in range(2):
num=input(" ")
if num.isdigit():
list_num.append(int(num))
except IndexError:
sys.exit("Enter 2 positive integers a, b. a < b")
if list_num[1]<list_num[0]:
print("The first input has to be smaller than the second input")
sys.exit()
else:
if check_even(list_num[0]):
stnum = list_num[0]
else:
stnum = list_num[0]+1
if check_even(list_num[1]):
endnum = list_num[1]
else:
endnum = list_num[1]-1
sum_even = (stnum + endnum)*((endnum-stnum)//2+1)//2
print(sum_even)
main()
```
* result

</br></br></br>
4.不定數迴圈-最小值

* 參考答案
```python=
"""This module print out the smallest number"""
import sys
list_num=[]
while True:
try:
num = int(input(""))
list_num.append(num)
if num ==9999:
break
except TypeError:
sys.exit("Enter numeric number")
list.remove(list[len(list)-1])
print(min(list))
sys.exit()
```
* result

</br></br></br>
5. 乘積

* 參考答案
```python=
"""This module compute sum"""
import sys
def compute(x, y):
"""compute multiply of two input numbers"""
return x*y
def main():
"""Print out result"""
try:
a = (int)(input(""))
b = (int)(input(""))
except TypeError:
sys.exit("Enter 2 integers")
print(compute(a, b))
main()
```
* result

</br></br>
6. 撲克牌總和

</br>
* 參考答案
```python=
"""This module prints the sum of 5 cards in the poker cards"""
def main():
"""print out 5 cards user typed, and the sum of cards"""
card=('A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K')
total = 0
for _ in range(5):
rank=input("")
if rank in card and rank.isdigit() is True:
total = total + int(rank)
elif rank.isalpha() is True:
rank = rank.upper()
if rank=='A':
total = total + 1
elif rank=='J':
total = total + 11
elif rank=='Q':
total = total + 12
elif rank=='K':
total = total + 13
else:
print("Usage: Enter rank in deck of the card: A, J, Q, K, 2~10")
exit()
else:
print("Usage: Enter rank in deck of the card: A, J, Q, K, 2~10")
exit()
print(total)
main()
```
* result

上述程式雖然執行出正確結果,但寫法十分不簡潔, 改用另一種資料結構dict的方式後改進後如下:
```python=
"""This module prints the sum of 5 cards in the poker cards"""
import sys
def main():
"""print out 5 cards user typed, and the sum of cards"""
card={'A':1, '2':2, '3':3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9,
'10':10, 'J':11, 'Q':12, 'K':13}
total = 0
for _ in range(5):
rank=input("").upper()
if rank in card:
total = total + card[rank]
else:
sys.exit("Usage: Enter rank in deck of the card: A, J, Q, K, 2~10")
print(total)
main()
```
</br></br></br>
7. 數組合併排序

</br>
* 參考答案
```python=
"""This module print list before and after sorting"""
import fontstyle
def create_num():
"""create tuple, till enter -9999"""
list_number=[]
value = input('')
while value !='-9999':
list_number.append(int(value))
value = input('')
return list_number
def main():
"""print out sorted and unsorted combined tuple/list"""
text1 = fontstyle.apply('Create tuple1:', 'bold')
print(text1)
list1 = create_num()
text2 = fontstyle.apply('Create tuple2:', 'bold')
print(text2)
list2 = create_num()
combined_tuple = str(tuple(list1 + list2))
text_before = "Combined tuple before sorting: "
combined_before_sorting = fontstyle.apply(text_before + combined_tuple, 'bold')
print(combined_before_sorting)
combined_list = list1 + list2
combined_list.sort()
text_after = "Combined list after sorting: "
combined_after_sorting = fontstyle.apply(text_after + str(combined_list), 'bold')
print(combined_after_sorting)
main()
```
* result

在正式考試當中,不能加入新的套件,所以字體變粗體的方式可以改用ANSI的方式:
```python=
print("\033[1m" + "Create tuple1:" + "\033[1m")
```
在下一題中也會應用到
</br></br></br>
8. 字元對應

</br>
* 參考答案
```python=
"""This module returns ascll value of input"""
string = input(" ")
lstring=list(string)
TOTAL = 0
for i, lstring in enumerate(lstring):
TEXT_1 = "\033[31mASCII\033[0m code \033[34mfor\033[0m "
TEXT_2 = "\033[32m'\033[0m"+f"\033[32m{string[i]}\033[0m"+"\033[32m'\033[0m"+ " is "
TEXT_3 = f"\033[31m{str(ord(lstring))}\033[0m"
print(TEXT_1+TEXT_2+TEXT_3)
TOTAL = ord(lstring) + TOTAL
print(f"\033[31m{TOTAL}\033[0m")
```
* result

</br></br></br>
---
## 綜合一下遇到的Pylint建議
從pylint列出來的建議當中,發現有許多是源於不良的程式撰寫習慣,像是在檔案一開頭添加檔案功能註解、函式下一行添加函示功能說明,或是刪除多餘空格,沒有使用或錯誤使用snake_case變數命名方式等。藉此機會改寫,讓程式碼遵守通用規範並讓其他人便於閱讀。
1. Trailing whiltspace
2. Final newline missing
3. Missing module docstring
4. Missin function or method docstring
5. Variable name "Sum_even" doesn't conform to snake_case naming style
6. No exception type(s) specified (bare-except)
這個error是在使用try...except遇到的,當時以為只要印出錯誤信息即可:
```python=
try:
...
except :
sys.exit("Enter 2 positive integers, and the first input has to be smaller than the second one.")
```
但卻沒列出exception的types,exception 的 types可以在官方文件上找到[pylint doc](https://pylint.readthedocs.io/en/latest/user_guide/messages/warning/bare-except.html),並查詢pylint的error code:

或是如果有裝pylint 在vscode上的extension的話,滑鼠懸空在有問題的程式碼上方,就可以點擊連結查看建議。

[點進去錯誤代碼w0702的頁面建議](https://pylint.readthedocs.io/en/latest/user_guide/messages/warning/bare-except.html)
---
## Reference material
* [基本-熟悉built-in function](https://docs.python.org/3/library/functions.html#ord)
* [pylint messages doc](https://pylint.readthedocs.io/en/latest/user_guide/messages/messages_overview.html)
* [python exceptions lib](https://docs.python.org/3/library/exceptions.html)