Python 基礎(2)
===
## 綜合練習
到網路上隨意複製一篇英文文章,以長字串的方式先指定給變數 `article`,例:
``` python=
article = """
Other nuke deal nations craft plan to keep doing business with Iran UNITED NATIONS
-- Five world powers and Iran agreed late Monday to establish a financial facility
in the European Union to facilitate payments for Iranian imports and exports including
oil, a key move sought by Tehran following the U.S. pullout from the 2015 nuclear
deal and its re-imposition of sanctions. Foreign ministers from Britain, France,
Germany, Russia, China and Iran said in a joint statement that the so-called
"Special Purpose Vehicle" will "assist and reassure economic operators pursuing
legitimate business with Iran." The nuclear agreement, formally known as the Joint
Comprehensive Plan of Action (JCPOA) is meant to prevent Tehran from developing
nuclear weapons, but U.S. President Donald Trump announced in May he was unilaterally
pulling out because he felt it wasn't strong enough and didn't cover other issues of
concern to the U.S. and its allies, such as Iran's military influence in the Middle
East and ballistic missile program. The U.S. has also accused Iran of promoting
international terrorism, which Tehran vehemently denies. Iran's economy is already
suffering from the sanctions that Washington re-imposed after walking away from the
nuclear agreement, and the U.S. has threatened to punish companies from other nations
that continue doing business with Iran. In sharp contrast, the five other world
powers who signed the nuclear deal remain strongly committed to it, and the new
financial facility is almost certain to anger the Trump administration. Earlier
this week, before heading to the United Nations General Assembly in New York, British
Prime Minister Theresa May told "CBS This Morning" co-host John Dickerson that she
trusts Mr. Trump, but believes Iran is holding up its end of the nuclear deal.
"I do have a difference of opinion with President Trump, because we (Britain) believe
the JCPOA should stay in…place. And others involved in putting that deal together
believe that it should stay in place. We do agree with the United States that there
are other aspects of Iran's behavior that we need to be dealing with, too. So looking
at the issue of ballistic missiles. Looking at the way in which Iran is acting
in the region to destabilize the region. We need to address those issues, too.
But we also want to ensure that we have a nuclear deal in place that prevents them
from, of getting a nuclear weapon." "The important thing about the JCPOA," said May,
"is that it is still in place. Yes, the United States has taken a particular view on
how to deal with this issue. That's a view which we disagree with. We take a different
view. But that deal is still in place." The Trump administration has been pushing
its allies around the world to stop buying Iranian oil for months, but as of August
it had received no firm commitments from the biggest purchasers of Iranian petroleum
products to find other suppliers. May's interview with Dickerson came on the heels of
a fresh warning from U.S. Ambassador to the U.N. that Britain and other nations
doing business with Iran would not be given any passes. Asked on "Face the Nation"
whether remaining signatories of the nuclear pact could face U.S. penalties for
continued business relationships with Iran, Haley said those countries would have to
weigh the benefit of dealing with Iran against the risk of U.S. sanctions. "The
Europeans have a decision to make. And I think that decision is already being made. If
you look, they are dropping business from Iran left and right," Haley said. "We will
have decisions to make in terms whether they get exemptions or not, but I'll tell you
right now, we're going to be really tough on Iran. We're not giving them a pass."
European Union foreign policy chief Federica Mogherini told reporters after the
closed-door ministerial meeting that the financial facility is aimed in part at
preserving the nuclear agreement. The EU and Iran say the deal is working, and the
joint statement notes that the International Atomic Energy Agency has now certified
12 times that Iran is in compliance with its obligations. "In practical terms,"
Mogherini said, "this will mean that EU member states will set up a legal entity
to facilitate legitimate financial transactions with Iran and this will allow European
companies to continue to trade with Iran in accordance with European Union law and
could be open to other partners in the world." She said the agreement follows extensive
exchanges and announced that a meeting of technical experts will be held to
"operationalize" the new financial facility. The joint statement said the six countries
that signed the 2015 nuclear agreement "reconfirmed their commitment to its full and
effective implementation in good faith and in a constructive atmosphere." They
called the agreement "a key element of the global non-proliferation architecture
and a significant achievement of multilateral diplomacy." The participants reaffirmed
their joint statement on July 6, "in particular to pursue concrete and effective
measures to secure payment channels with Iran."
"""
```
### 練習1: 計算文章內的大寫字母個數
``` python=66
count = 0 # 一開始還沒看到任何大寫字母,先設成 0
for c in article: # 將 article 中每一個符號都拿出來看,每拿到一個都先記在變數 c 裡
if c in "ABCDEFGHIJKLMNOPQRSTUVWXYZ": # 如果變數 c 的內容是 A~Z 中任何一個符號
count = count + 1 # 就把 count 的值加 1
print(count) # 印出 count 的內容
```
- ++第 67 行++,把 `article` 裡每個符號拿出來看,每回合拿到一個符號都先把它放到變數 `c` 中
- ++第 68 行++,如果變數 `c` 的內容有出現在 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 中的話,表示本回拿取得暫存在變數 `c` 裡的符號是大寫字母
- ++第 69 行++,把 `count` 的值加 `1` 再放回 `count`,這行也可以縮寫為
``` python
count += 1
```
- ++第 71 行++,迴圈結束後,印出 `count` 的值
::: info
:bulb: **另一種寫法**
``` python=66
count = 0
for c in article:
if c >= 'A' and c <= 'Z': # 利用 ASCII 碼表中的關係來比對
count = count + 1
print(count)
```
:::
### 練習2: 計算非大寫字母的字元數
``` python=66
count = 0
for c in article:
if c not in "ABCDEFGHIJKLMNOPQRSTUVWXYZ": # 如果變數 c 的內容不在 A~Z 的範圍內
count = count + 1
print(count)
```
跟前一個練習一樣,只是將++第 68 行++的 `if c in` 改為 `if c not in`,只有在 `c` 變數中暫存的符號不在大寫字母裡才需要將 `count` 加 `1`。
::: info
:bulb: **另一種寫法**
``` python=66
count = 0
for c in article:
if not c >= 'A' and c <= 'Z':
count = count + 1
print(count) # 印出 count 的內容
```
:::
### 練習3: 同時計算大小寫字母個數
``` python=66
count = 0 # 全部字元數
caps = 0 # 大寫字元數
lowers = 0 # 小寫字元數
others = 0 # 其他字元數
for c in article:
if c in "ABCDEFGHIJKLMNOPQRSTUVWXYZ": # c 是大寫字母?
caps = caps + 1
elif c in "abcdefghijklmnopqrstuvwxyz": # c 是小寫字母?
lowers += 1
else: # c 不是大寫字母,也非小寫字母
others += 1
count = count + 1 # 不受 if 控制,但受 for 控制
print(caps, lowers, others, count)
```
### 練習4: 分別計算每個字母的出現次數
``` python=66
count = {} # 建立一個空字典
letters = 0 # 總字元數
for c in article:
capc = c.capitalize() # 轉大寫
if capc in "ABCDEFGHIJKLMNOPQRSTUVWXYZ": # capc 是大寫字母?
if capc not in count: # 如果 capc 尚未在 count 字典中
count[capc] = 0 # 在 count 中新增一筆紀錄
count[capc] += 1 # 把 count 中 capc 對應到的值加 1
letters += 1
print("Total letters = ", letters)
for capc in count:
print(capc, ':', count[capc])
```
- 要算某個符號出現的次數,有符號與數值的對應關係,因此適合以字典來紀錄每個符號的出現次數,以字母當鍵值,對應值為該字母目前出現過的次數。
- ++第 73 行++是要將 `capc` 所記錄的大寫字母的個數加 `1`,但是若字典 `count` 裡原先沒有 `capc` 這個大寫字母的相關紀錄,所引發 `KeyError` 的錯誤。因此加了++第 71, 72 行++的判斷,在增加個數之前,確保字典中有相關紀錄存在。
以範例文章的內容來說,++第 77-78 行++印出的結果如下:
```
O : 270
T : 413
H : 192
E : 485
R : 238
N : 354
U : 118
K : 21
D : 128
A : 363
L : 175
I : 387
S : 259
C : 128
F : 84
P : 91
G : 85
B : 45
W : 76
V : 34
M : 109
Y : 47
X : 6
J : 10
Z : 2
```
### 練習5: 分別計算每個字母的出現次數並排序
``` python=66
count = {}
letters = 0
for c in article:
capc = c.capitalize()
if capc in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
if capc not in count:
count[capc] = 0
count[capc] += 1
letters += 1
print("Total letters = ", letters)
items = sorted(count.items(), key=lambda d: d[1], reverse=True)
for item in items:
print("{}: {}".format(item[0], item[1]))
print('出現次數最多的字母是', items[0][0], ',次數為', items[0][1], '次')
print('出現次數最少的字母是 {}, 次數為 {} 次'.format(items[-1][0], items[-1][1])) # 格式化輸出
```
- ++第 78 行++,取出 `count` 字典中所有的項目 `(key, value)` 的值組(Tuple), 排序的時候以 `value` 當比較的依據, 反向排序
- ++第 80-81 行++,將排序完的結果印出來,這邊使用了 Python 格式化字串的方式來進行輸出。
``` python
"{}: {}".format(item[0], item[1])
```
的意思是,輸出的格式為 `"{}: {}"`,有兩個需要被替換的資料標記,中間有一個冒號以及空格 `": "` 隔開,接著使用 `.format()` 方法,讓 `item[0]` 的內容替換第一組 `{}`,而第二組 `{}` 則由 `item[1]` 的內容取代。
- ++第 83 行++,印出出現頻率最高的符號。因為是反向排序,所以最大的會出現在第一筆(`items[0]`)。
- ++第 84 行++,印出出現頻率最低的符號。因為是反向排序,所以最小的會出現在最後一筆(`items[-1]`)。
## 作業
:::info
請將下面程式碼區塊的內容複製貼上到 ImmortalRegret.py 檔案,並修改程式碼,計算長恨歌中的中文字(非標點符號及換行)總數,以及出現次數最高的中文字是哪一個,以及其次數為何?
```
中文字(不含標點符號及換行)共 xxx 字
出現頻率最高的中文字是 Z, 次數為 yy 次
```
:::
``` python
text = """漢皇重色思傾國,御宇多年求不得。楊家有女初長成,養在深閨人未識。
天生麗質難自棄,一朝選在君王側。回眸一笑百媚生,六宮粉黛無顏色。
春寒賜浴華清池,溫泉水滑洗凝脂;侍兒扶起嬌無力,始是新承恩澤時。
雲鬢花顏金步搖,芙蓉帳暖度春宵;春宵苦短日高起,從此君王不早朝。
承歡侍宴無閑暇,春從春遊夜專夜。後宮佳麗三千人,三千寵愛在一身。
金屋妝成嬌侍夜,玉樓宴罷醉和春。姊妹弟兄皆列土,可憐光彩生門戶。
遂令天下父母心,不重生男重生女。驪宮高處入青雲,仙樂風飄處處聞。
緩歌慢舞凝絲竹,盡日君王看不足。漁陽鼙鼓動地來,驚破霓裳羽衣曲。
九重城闕煙塵生,千乘萬騎西南行。翠華搖搖行復止,西出都門百餘里;
六軍不發無奈何?宛轉蛾眉馬前死。花鈿委地無人收,翠翹金雀玉搔頭。
君王掩面救不得,回看血淚相和流。黃埃散漫風蕭索,雲棧縈紆登劍閣。
峨嵋山下少人行,旌旗無光日色薄。蜀江水碧蜀山青,聖主朝朝暮暮情。
行宮見月傷心色,夜雨聞鈴腸斷聲。天旋地轉迴龍馭,到此躊躇不能去。
馬嵬坡下泥土中,不見玉顏空死處。君臣相顧盡霑衣,東望都門信馬歸。
歸來池苑皆依舊,太液芙蓉未央柳;芙蓉如面柳如眉,對此如何不淚垂?
春風桃李花開日,秋雨梧桐葉落時。西宮南內多秋草,落葉滿階紅不掃。
梨園子弟白髮新,椒房阿監青娥老。夕殿螢飛思悄然,孤燈挑盡未成眠。
遲遲鐘鼓初長夜,耿耿星河欲曙天。鴛鴦瓦冷霜華重,翡翠衾寒誰與共?
悠悠生死別經年,魂魄不曾來入夢。臨邛道士鴻都客,能以精誠致魂魄;
為感君王輾轉思,遂教方士殷勤覓。排空馭氣奔如電,升天入地求之遍;
上窮碧落下黃泉,兩處茫茫皆不見。忽聞海上有仙山,山在虛無縹緲間。
樓閣玲瓏五雲起,其中綽約多仙子。中有一人字太真,雪膚花貌參差是。
金闕西廂叩玉扃,轉教小玉報雙成。聞道漢家天子使,九華帳裡夢魂驚;
攬衣推枕起徘徊,珠箔銀屏迤邐開。雲鬢半偏新睡覺,花冠不整下堂來。
風吹仙袂飄飄舉,猶似霓裳羽衣舞。玉容寂寞淚闌干,梨花一枝春帶雨。
含情凝睇謝君王,一別音容兩渺茫。昭陽殿裡恩愛絕,蓬萊宮中日月長。
回頭下望人寰處,不見長安見塵霧。唯將舊物表深情,鈿合金釵寄將去。
釵留一股合一扇,釵擘黃金合分鈿。但教心似金鈿堅,天上人間會相見。
臨別殷勤重寄詞,詞中有誓兩心知,七月七日長生殿,夜半無人私語時。
在天願作比翼鳥,在地願為連理枝。天長地久有時盡,此恨綿綿無絕期。"""
# 在此填入你的程式碼
# 輸出答案
print("中文字(不含標點符號及換行)共 __ 字")
print("出現頻率最高的中文字是 __, 次數為 __ 次")
```