## 語言元素
#### 指令和程序
計(jì)算機(jī)的硬件系統(tǒng)通常由五大部件構(gòu)成岖研,包括:運(yùn)算器显押、控制器浸踩、存儲(chǔ)器叔汁、輸入設(shè)備和輸出設(shè)備。其中检碗,運(yùn)算器和控制器放在一起就是我們通常所說的中央處理器据块,它的功能是執(zhí)行各種運(yùn)算和控制指令以及處理計(jì)算機(jī)軟件中的數(shù)據(jù)。我們通常所說的程序?qū)嶋H上就是指令的集合折剃,我們程序就是將一系列的指令按照某種方式組織到一起另假,然后通過這些指令去控制計(jì)算機(jī)做我們想讓它做的事情。今天我們大多數(shù)時(shí)候使用的計(jì)算機(jī)怕犁,雖然它們的元器件做工越來越精密边篮,處理能力越來越強(qiáng)大,但究其本質(zhì)來說仍然屬于[“馮·諾依曼結(jié)構(gòu)”](https://zh.wikipedia.org/wiki/%E5%86%AF%C2%B7%E8%AF%BA%E4%BC%8A%E6%9B%BC%E7%BB%93%E6%9E%84)的計(jì)算機(jī)奏甫「杲危“馮·諾依曼結(jié)構(gòu)”有兩個(gè)關(guān)鍵點(diǎn),一是指出要將存儲(chǔ)設(shè)備與中央處理器分開阵子,二是提出了將數(shù)據(jù)以二進(jìn)制方式編碼思杯。二進(jìn)制是一種“逢二進(jìn)一”的計(jì)數(shù)法,跟我們?nèi)祟愂褂玫摹胺晔M(jìn)一”的計(jì)數(shù)法沒有實(shí)質(zhì)性的區(qū)別款筑,人類因?yàn)橛惺种杆允褂昧耸M(jìn)制(因?yàn)樵跀?shù)數(shù)時(shí)十根手指用完之后就只能進(jìn)位了智蝠,當(dāng)然凡事都有例外,瑪雅人可能是因?yàn)殚L(zhǎng)年光著腳的原因把腳趾頭也算上了奈梳,于是他們使用了二十進(jìn)制的計(jì)數(shù)法杈湾,在這種計(jì)數(shù)法的指導(dǎo)下瑪雅人的歷法就與我們平常使用的歷法不一樣,而按照瑪雅人的歷法攘须,2012年是上一個(gè)所謂的“太陽紀(jì)”的最后一年漆撞,而2013年則是新的“太陽紀(jì)”的開始,后來這件事情被以訛傳訛的方式誤傳為”2012年是瑪雅人預(yù)言的世界末日“這種荒誕的說法,今天我們可以大膽的猜測(cè)浮驳,瑪雅文明之所以發(fā)展緩慢估計(jì)也與使用了二十進(jìn)制有關(guān))悍汛。對(duì)于計(jì)算機(jī)來說,二進(jìn)制在物理器件上來說是最容易實(shí)現(xiàn)的(高電壓表示1至会,低電壓表示0)离咐,于是在“馮·諾依曼結(jié)構(gòu)”的計(jì)算機(jī)都使用了二進(jìn)制。雖然我們并不需要每個(gè)程序員都能夠使用二進(jìn)制的思維方式來工作奉件,但是了解二進(jìn)制以及它與我們生活中的十進(jìn)制之間的轉(zhuǎn)換關(guān)系宵蛀,以及二進(jìn)制與八進(jìn)制和十六進(jìn)制的轉(zhuǎn)換關(guān)系還是有必要的。如果你對(duì)這一點(diǎn)不熟悉县貌,可以自行使用[維基百科](https://zh.wikipedia.org/wiki/%E4%BA%8C%E8%BF%9B%E5%88%B6)或者[百度百科](https://baike.baidu.com)科普一下术陶。
> **說明**:近期關(guān)于**量子計(jì)算機(jī)**的研究已經(jīng)被推倒了風(fēng)口浪尖,量子計(jì)算機(jī)基于量子力學(xué)進(jìn)行運(yùn)算煤痕,使用量子瞬移的方式來傳遞信息梧宫。2018年6月,Intel宣布開發(fā)出新款量子芯片并通過了在接近絕對(duì)零度環(huán)境下的測(cè)試摆碉;2019年塘匣,IBM和Google都推出了自己的量子計(jì)算機(jī)。
### 變量和類型
在程序設(shè)計(jì)中巷帝,變量是一種存儲(chǔ)數(shù)據(jù)的載體馆铁。計(jì)算機(jī)中的變量是實(shí)際存在的數(shù)據(jù)或者說是存儲(chǔ)器中存儲(chǔ)數(shù)據(jù)的一塊內(nèi)存空間,變量的值可以被讀取和修改锅睛,這是所有計(jì)算和控制的基礎(chǔ)。計(jì)算機(jī)能處理的數(shù)據(jù)有很多種類型历谍,除了數(shù)值之外還可以處理文本现拒、圖形、音頻望侈、視頻等各種各樣的數(shù)據(jù)印蔬,那么不同的數(shù)據(jù)就需要定義不同的存儲(chǔ)類型。Python中的數(shù)據(jù)類型很多脱衙,而且也允許我們自定義新的數(shù)據(jù)類型(這一點(diǎn)在后面會(huì)講到)侥猬,我們先介紹幾種常用的數(shù)據(jù)類型。
- 整型:Python中可以處理任意大小的整數(shù)(Python 2.x中有`int`和`long`兩種類型的整數(shù)捐韩,但這種區(qū)分對(duì)Python來說意義不大退唠,因此在Python 3.x中整數(shù)只有int這一種了),而且支持二進(jìn)制(如`0b100`荤胁,換算成十進(jìn)制是4)瞧预、八進(jìn)制(如`0o100`,換算成十進(jìn)制是64)、十進(jìn)制(`100`)和十六進(jìn)制(`0x100`垢油,換算成十進(jìn)制是256)的表示法盆驹。
- 浮點(diǎn)型:浮點(diǎn)數(shù)也就是小數(shù),之所以稱為浮點(diǎn)數(shù)滩愁,是因?yàn)榘凑湛茖W(xué)記數(shù)法表示時(shí)躯喇,一個(gè)浮點(diǎn)數(shù)的小數(shù)點(diǎn)位置是可變的,浮點(diǎn)數(shù)除了數(shù)學(xué)寫法(如`123.456`)之外還支持科學(xué)計(jì)數(shù)法(如`1.23456e2`)硝枉。
- 字符串型:字符串是以單引號(hào)或雙引號(hào)括起來的任意文本廉丽,比如`'hello'`和`"hello"`,字符串還有原始字符串表示法、字節(jié)字符串表示法檀咙、Unicode字符串表示法雅倒,而且可以書寫成多行的形式(用三個(gè)單引號(hào)或三個(gè)雙引號(hào)開頭,三個(gè)單引號(hào)或三個(gè)雙引號(hào)結(jié)尾)弧可。
- 布爾型:布爾值只有`True`蔑匣、`False`兩種值,要么是`True`棕诵,要么是`False`裁良,在Python中,可以直接用`True`校套、`False`表示布爾值(請(qǐng)注意大小寫)价脾,也可以通過布爾運(yùn)算計(jì)算出來(例如`3 < 5`會(huì)產(chǎn)生布爾值`True`,而`2 == 1`會(huì)產(chǎn)生布爾值`False`)笛匙。
- 復(fù)數(shù)型:形如`3+5j`侨把,跟數(shù)學(xué)上的復(fù)數(shù)表示一樣,唯一不同的是虛部的`i`換成了`j`妹孙。實(shí)際上秋柄,這個(gè)類型并不常用,大家了解一下就可以了蠢正。
#### 變量命名
對(duì)于每個(gè)變量我們需要給它取一個(gè)名字骇笔,就如同我們每個(gè)人都有屬于自己的響亮的名字一樣。在Python中嚣崭,變量命名需要遵循以下這些必須遵守硬性規(guī)則和強(qiáng)烈建議遵守的非硬性規(guī)則笨触。
- 硬性規(guī)則:
? - 變量名由字母(廣義的Unicode字符,不包括特殊字符)雹舀、數(shù)字和下劃線構(gòu)成芦劣,數(shù)字不能開頭。
? - 大小寫敏感(大寫的`a`和小寫的`A`是兩個(gè)不同的變量)说榆。
? - 不要跟關(guān)鍵字(有特殊含義的單詞持寄,后面會(huì)講到)和系統(tǒng)保留字(如函數(shù)源梭、模塊等的名字)沖突。
- PEP 8要求:
? - 用小寫字母拼寫稍味,多個(gè)單詞用下劃線連接废麻。
? - 受保護(hù)的實(shí)例屬性用單個(gè)下劃線開頭(后面會(huì)講到)。
? - 私有的實(shí)例屬性用兩個(gè)下劃線開頭(后面會(huì)講到)模庐。
當(dāng)然烛愧,作為一個(gè)專業(yè)的程序員,給變量(事實(shí)上應(yīng)該是所有的標(biāo)識(shí)符)命名時(shí)做到見名知意也是非常重要的掂碱。
#### 變量的使用
下面通過幾個(gè)例子來說明變量的類型和變量使用怜姿。
```Python
"""
使用變量保存數(shù)據(jù)并進(jìn)行加減乘除運(yùn)算
Version: 0.1
Author: 駱昊
"""
a = 321
b = 12
print(a + b)? ? # 333
print(a - b)? ? # 309
print(a * b)? ? # 3852
print(a / b)? ? # 26.75
```
在Python中可以使用`type`函數(shù)對(duì)變量的類型進(jìn)行檢查。程序設(shè)計(jì)中函數(shù)的概念跟數(shù)學(xué)上函數(shù)的概念是一致的疼燥,數(shù)學(xué)上的函數(shù)相信大家并不陌生沧卢,它包括了函數(shù)名、自變量和因變量醉者。如果暫時(shí)不理解這個(gè)概念也不要緊但狭,我們會(huì)在后續(xù)的章節(jié)中專門講解函數(shù)的定義和使用。
```Python
"""
使用type()檢查變量的類型
Version: 0.1
Author: 駱昊
"""
a = 100
b = 12.345
c = 1 + 5j
d = 'hello, world'
e = True
print(type(a))? ? # <class 'int'>
print(type(b))? ? # <class 'float'>
print(type(c))? ? # <class 'complex'>
print(type(d))? ? # <class 'str'>
print(type(e))? ? # <class 'bool'>
```
可以使用Python中內(nèi)置的函數(shù)對(duì)變量類型進(jìn)行轉(zhuǎn)換撬即。
- `int()`:將一個(gè)數(shù)值或字符串轉(zhuǎn)換成整數(shù)立磁,可以指定進(jìn)制。
- `float()`:將一個(gè)字符串轉(zhuǎn)換成浮點(diǎn)數(shù)剥槐。
- `str()`:將指定的對(duì)象轉(zhuǎn)換成字符串形式唱歧,可以指定編碼。
- `chr()`:將整數(shù)轉(zhuǎn)換成該編碼對(duì)應(yīng)的字符串(一個(gè)字符)粒竖。
- `ord()`:將字符串(一個(gè)字符)轉(zhuǎn)換成對(duì)應(yīng)的編碼(整數(shù))颅崩。
下面的代碼通過鍵盤輸入兩個(gè)整數(shù)來實(shí)現(xiàn)對(duì)兩個(gè)整數(shù)的算術(shù)運(yùn)算。
```Python
"""
使用input()函數(shù)獲取鍵盤輸入(字符串)
使用int()函數(shù)將輸入的字符串轉(zhuǎn)換成整數(shù)
使用print()函數(shù)輸出帶占位符的字符串
Version: 0.1
Author: 駱昊
"""
a = int(input('a = '))
b = int(input('b = '))
print('%d + %d = %d' % (a, b, a + b))
print('%d - %d = %d' % (a, b, a - b))
print('%d * %d = %d' % (a, b, a * b))
print('%d / %d = %f' % (a, b, a / b))
print('%d // %d = %d' % (a, b, a // b))
print('%d %% %d = %d' % (a, b, a % b))
print('%d ** %d = %d' % (a, b, a ** b))
```
> **說明**:上面的print函數(shù)中輸出的字符串使用了占位符語法蕊苗,其中`%d`是整數(shù)的占位符挨摸,`%f`是小數(shù)的占位符,`%%`表示百分號(hào)(因?yàn)榘俜痔?hào)代表了占位符岁歉,所以帶占位符的字符串中要表示百分號(hào)必須寫成`%%`),字符串之后的`%`后面跟的變量值會(huì)替換掉占位符然后輸出到終端中膝蜈,運(yùn)行上面的程序锅移,看看程序執(zhí)行結(jié)果就明白啦。
### 運(yùn)算符
Python支持多種運(yùn)算符饱搏,下表大致按照優(yōu)先級(jí)從高到低的順序列出了所有的運(yùn)算符非剃,運(yùn)算符的優(yōu)先級(jí)指的是多個(gè)運(yùn)算符同時(shí)出現(xiàn)時(shí),先做什么運(yùn)算然后再做什么運(yùn)算推沸。除了我們之前已經(jīng)用過的賦值運(yùn)算符和算術(shù)運(yùn)算符备绽,我們稍后會(huì)陸續(xù)講到其他運(yùn)算符的使用券坞。
| 運(yùn)算符? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | 描述? ? ? ? ? ? ? ? ? ? ? ? ? |
| ------------------------------------------------------------ | ------------------------------ |
| `[]` `[:]`? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | 下標(biāo),切片? ? ? ? ? ? ? ? ? ? |
| `**`? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | 指數(shù)? ? ? ? ? ? ? ? ? ? ? ? ? |
| `~` `+` `-`? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | 按位取反, 正負(fù)號(hào)? ? ? ? ? ? ? |
| `*` `/` `%` `//`? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | 乘肺素,除恨锚,模,整除? ? ? ? ? ? ? |
| `+` `-`? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | 加倍靡,減? ? ? ? ? ? ? ? ? ? ? ? |
| `>>` `<<`? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | 右移猴伶,左移? ? ? ? ? ? ? ? ? ? |
| `&`? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | 按位與? ? ? ? ? ? ? ? ? ? ? ? |
| `^` `\|`? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | 按位異或,按位或? ? ? ? ? ? ? |
| `<=` `<` `>` `>=`? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | 小于等于塌西,小于他挎,大于,大于等于 |
| `==` `!=`? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | 等于捡需,不等于? ? ? ? ? ? ? ? ? |
| `is`? `is not`? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | 身份運(yùn)算符? ? ? ? ? ? ? ? ? ? |
| `in` `not in`? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | 成員運(yùn)算符? ? ? ? ? ? ? ? ? ? |
| `not` `or` `and`? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | 邏輯運(yùn)算符? ? ? ? ? ? ? ? ? ? |
| `=` `+=` `-=` `*=` `/=` `%=` `//=` `**=` `&=` `|=` `^=` `>>=` `<<=` | (復(fù)合)賦值運(yùn)算符? ? ? ? ? ? |
>**說明:** 在實(shí)際開發(fā)中办桨,如果搞不清楚運(yùn)算符的優(yōu)先級(jí),可以使用括號(hào)來確保運(yùn)算的執(zhí)行順序站辉。
#### 賦值運(yùn)算符
賦值運(yùn)算符應(yīng)該是最為常見的運(yùn)算符呢撞,它的作用是將右邊的值賦給左邊的變量。下面的例子演示了賦值運(yùn)算符和復(fù)合賦值運(yùn)算符的使用庵寞。
```Python
"""
賦值運(yùn)算符和復(fù)合賦值運(yùn)算符
Version: 0.1
Author: 駱昊
"""
a = 10
b = 3
a += b? ? ? ? # 相當(dāng)于:a = a + b
a *= a + 2? ? # 相當(dāng)于:a = a * (a + 2)
print(a)? ? ? # 算一下這里會(huì)輸出什么
```
### 比較運(yùn)算符和邏輯運(yùn)算符
比較運(yùn)算符有的地方也稱為關(guān)系運(yùn)算符狸相,包括`==`、`!=`捐川、`<`脓鹃、`>`、`<=`古沥、`>=`瘸右,我相信沒有什么好解釋的,大家一看就能懂岩齿,唯一需要提醒的是比較相等用的是`==`太颤,請(qǐng)注意這個(gè)地方是兩個(gè)等號(hào),因?yàn)閌=`是賦值運(yùn)算符盹沈,我們?cè)谏厦鎰倓傊v到過龄章,`==`才是比較相等的比較運(yùn)算符。比較運(yùn)算符會(huì)產(chǎn)生布爾值乞封,要么是`True`要么是`False`做裙。
邏輯運(yùn)算符有三個(gè),分別是`and`肃晚、`or`和`not`锚贱。`and`字面意思是“而且”,所以`and`運(yùn)算符會(huì)連接兩個(gè)布爾值关串,如果兩個(gè)布爾值都是`True`拧廊,那么運(yùn)算的結(jié)果就是`True`监徘;左右兩邊的布爾值有一個(gè)是`False`,最終的運(yùn)算結(jié)果就是`False`吧碾。相信大家已經(jīng)想到了凰盔,如果`and`左邊的布爾值是`False`,不管右邊的布爾值是什么滤港,最終的結(jié)果都是`False`廊蜒,所以在做運(yùn)算的時(shí)候右邊的值會(huì)被跳過(短路處理),這也就意味著在`and`運(yùn)算符左邊為`False`的情況下溅漾,右邊的表達(dá)式根本不會(huì)執(zhí)行山叮。`or`字面意思是“或者”,所以`or`運(yùn)算符也會(huì)連接兩個(gè)布爾值添履,如果兩個(gè)布爾值有任意一個(gè)是`True`屁倔,那么最終的結(jié)果就是`True`。當(dāng)然暮胧,`or`運(yùn)算符也是有短路功能的锐借,在它左邊的布爾值為`True`的情況下,右邊的表達(dá)式根本不會(huì)執(zhí)行往衷。`not`運(yùn)算符的后面會(huì)跟上一個(gè)布爾值钞翔,它的作用是得到與該布爾值相反的值,也就是說席舍,后面的布爾值如果是`True`運(yùn)算結(jié)果就是`False`布轿,而后面的布爾值如果是`False`則運(yùn)算結(jié)果就是`True`。
```Python
"""
比較運(yùn)算符和邏輯運(yùn)算符的使用
Version: 0.1
Author: 駱昊
"""
flag0 = 1 == 1
flag1 = 3 > 2
flag2 = 2 < 1
flag3 = flag1 and flag2
flag4 = flag1 or flag2
flag5 = not (1 != 2)
print('flag0 =', flag0)? ? # flag0 = True
print('flag1 =', flag1)? ? # flag1 = True
print('flag2 =', flag2)? ? # flag2 = False
print('flag3 =', flag3)? ? # flag3 = False
print('flag4 =', flag4)? ? # flag4 = True
print('flag5 =', flag5)? ? # flag5 = False
```
> **說明**:比較運(yùn)算符的優(yōu)先級(jí)高于賦值運(yùn)算符来颤,所以`flag0 = 1 == 1`先做`1 == 1`產(chǎn)生布爾值`True`汰扭,再將這個(gè)值賦值給變量`flag0`。`print`函數(shù)可以輸出多個(gè)值福铅,多個(gè)值之間可以用`,`進(jìn)行分隔萝毛,輸出的內(nèi)容之間默認(rèn)以空格分開。
### 練習(xí)
#### 練習(xí)1:華氏溫度轉(zhuǎn)換為攝氏溫度滑黔。
> 提示:華氏溫度到攝氏溫度的轉(zhuǎn)換公式為:$C=(F - 32) \div 1.8$笆包。
參考答案:
```Python
"""
將華氏溫度轉(zhuǎn)換為攝氏溫度
Version: 0.1
Author: 駱昊
"""
f = float(input('請(qǐng)輸入華氏溫度: '))
c = (f - 32) / 1.8
print('%.1f華氏度 = %.1f攝氏度' % (f, c))
```
> **說明**:在使用`print`函數(shù)輸出時(shí),也可以對(duì)字符串內(nèi)容進(jìn)行格式化處理略荡,上面`print`函數(shù)中的字符串`%1.f`是一個(gè)占位符庵佣,稍后會(huì)由一個(gè)`float`類型的變量值替換掉它。同理撞芍,如果字符串中有`%d`,后面可以用一個(gè)`int`類型的變量值替換掉它跨扮,而`%s`會(huì)被字符串的值替換掉序无。除了這種格式化字符串的方式外验毡,還可以用下面的方式來格式化字符串,其中`{f:.1f}`和`{c:.1f}`可以先看成是`{f}`和`{c}`帝嗡,表示輸出時(shí)會(huì)用變量`f`和變量`c`的值替換掉這兩個(gè)占位符晶通,后面的`:.1f`表示這是一個(gè)浮點(diǎn)數(shù),小數(shù)點(diǎn)后保留1位有效數(shù)字哟玷。
>
> ```Python
> print(f'{f:.1f}華氏度 = {c:.1f}攝氏度')
> ```
#### 練習(xí)2:輸入圓的半徑計(jì)算計(jì)算周長(zhǎng)和面積狮辽。
參考答案:
```Python
"""
輸入半徑計(jì)算圓的周長(zhǎng)和面積
Version: 0.1
Author: 駱昊
"""
radius = float(input('請(qǐng)輸入圓的半徑: '))
perimeter = 2 * 3.1416 * radius
area = 3.1416 * radius * radius
print('周長(zhǎng): %.2f' % perimeter)
print('面積: %.2f' % area)
```
#### 練習(xí)3:輸入年份判斷是不是閏年。
參考答案:
```Python
"""
輸入年份 如果是閏年輸出True 否則輸出False
Version: 0.1
Author: 駱昊
"""
year = int(input('請(qǐng)輸入年份: '))
# 如果代碼太長(zhǎng)寫成一行不便于閱讀 可以使用\對(duì)代碼進(jìn)行折行
is_leap = year % 4 == 0 and year % 100 != 0 or \
? ? ? ? ? year % 400 == 0
print(is_leap)
```
> **說明**:比較運(yùn)算符會(huì)產(chǎn)生布爾值巢寡,而邏輯運(yùn)算符`and`和`or`會(huì)對(duì)這些布爾值進(jìn)行組合喉脖,最終也是得到一個(gè)布爾值,閏年輸出`True`抑月,平年輸出`False`树叽。