值及其相應(yīng)的運算
導讀:歡迎你來到站長在線的站長書籍欄目,你正在學習的是李笑來著作的《自學是門手藝》一書中的《值及其相應(yīng)的運算》原文內(nèi)容如下:
永久美國免備案虛擬主機1元1天,15元1月,100元1年,1000元永久
站長在線旗下答案網(wǎng)站,全站所有題目,免費查看答案和答案解析
導讀:歡迎你來到站長在線的站長書籍欄目,你正在學習的是李笑來著作的《自學是門手藝》一書中的《值及其相應(yīng)的運算》原文內(nèi)容如下:
值及其相應(yīng)的運算
從結(jié)構(gòu)上來看,一切的計算機程序,都由且只由兩個最基本的成分構(gòu)成:
- 運算(Evaluation)
- 流程控制(Control Flow)
沒有流程控制的是計算器而已;有流程控制的才是可編程設(shè)備。
看看之前我們見過的計算質(zhì)數(shù)的程序:(按一下 ?
,即 ESC
,確保已經(jīng)進入命令模式,? L
可以切換是否顯示代碼行號)
def is_prime(n): # 定義 is_prime(),接收一個參數(shù)
if n < 2: # 開始使用接收到的那個參數(shù)(值)開始計算……
return False # 不再是返回給人,而是返回給調(diào)用它的代碼……
if n == 2:
return True
for m in range(2, int(n**0.5)+1):
if (n % m) == 0:
return False
else:
return True
for i in range(80, 110):
if is_prime(i): # 調(diào)用 is_prime() 函數(shù),
print(i) # 如果返回值為 True,則向屏幕輸出 i
83
89
97
101
103
107
109
if...
,for...
在控制流程:在什么情況下運算什么,在什么情況下重復運算什么;
第 13 行 is_prime()
這個函數(shù)的調(diào)用,也是在控制流程 —— 所以我們可以*把函數(shù)看作是 “子程序” *;
一旦這個函數(shù)被調(diào)用,流程就轉(zhuǎn)向開始執(zhí)行在第 1 行中定義的 is_prime()
函數(shù)內(nèi)部的代碼,而這段代碼內(nèi)部還是 計算 和流程控制,決定一個返回值 —— 返回值是布爾值;再回到第 13 行,將返回值交給 if
判斷,決定是否執(zhí)行第 14 行……
而計算機這種可編程設(shè)備之所以可以做流程控制,是因為它可以做布爾運算,即,它可以對布爾值進行操作,而后將布爾值交給分支和循環(huán)語句,構(gòu)成了程序中的流程控制。
值
從本質(zhì)上看,程序里的絕大多數(shù)語句包含著運算(Evaluation),即,在對某個值進行評價。這里的 “評價”,不是 “判斷某人某事的好壞”,而是 “計算出某個值究竟是什么” —— 所以,我們用中文的 “運算” 翻譯這個 “_Evaluation_” 可能表達得更準確一些。
在程序中,被運算的可分為常量(Literals)和變量(Variables)。
a = 1 + 2 * 3
a += 1
print(a)
在以上代碼中,
1
、2
、3
,都是常量。Literal 的意思是 “字面的”,顧名思義,常量的值就是它字面上的值。1
的值,就是 1
。
a
是變量。顧名思義,它的值將來是可變的。比如,在第 2 句中,這個變量的值發(fā)生了改變,之前是 7
,之后變成了 8
。
第 1 句中的 +
、*
,是操作符(Operators),它用來對其左右的值進行相應(yīng)的運算而后得到一個值。先是由操作符 *
對 2
和 3
進行運算, 生成一個值,6
;然后再由操作符 +
對 1
和 6
進行運算,生成一個值 7
。先算乘除后算加減,這是操作符的優(yōu)先級決定的。
=
是賦值符號,它的作用是將它右邊的值保存到左邊的變量中。
值是程序的基礎(chǔ)成分(Building blocks),它就好像蓋房子用的磚塊一樣,無論什么樣的房子,到最后都主要是由磚塊構(gòu)成。
常量,當然有個值 —— 就是它們字面所表達的值。
變量必須先賦值才能使用,也就是說,要先把一個值保存到變量中,它才能在其后被運算。
在 python 中每個函數(shù)都有 返回值 ,即便你在定義一個函數(shù)的時候沒有設(shè)定返回值,它也會加上默認的返回值 None
…… (請注意 None
的大小寫?。?/p>
def f():
pass
print(f()) # 輸出 f() 這個函數(shù)被調(diào)用后的返回值,None
print(print(f())) # 這一行最外圍的 print() 調(diào)用了一次 print(f()),所以輸出一個 None,
# 而后再輸出這次調(diào)用的返回值,所以又輸出一次 None
None
None
None
當我們調(diào)用一個函數(shù)的時候,本質(zhì)上來看,就相當于:
我們把一個值交給某個函數(shù),請函數(shù)根據(jù)它內(nèi)部的運算和流程控制對其進行操作而后返回另外一個值。
比如,abs()
函數(shù),就會返回傳遞給它的 值 的絕對值;int()
函數(shù),會將傳遞給它的值的小數(shù)部分砍掉;float()
接到整數(shù)參數(shù)之后,會返回這個整數(shù)的浮點數(shù)形式:
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_Node_interactivity = "all"
abs(-3.14159)
int(abs(-3.14159))
float(int(abs(-3.14159)))
3.14159
3
3.0
值的類型
在編程語言中,總是包含最基本的三種數(shù)據(jù)類型:
既然有不同類型的數(shù)據(jù),它們就分別對應(yīng)著不同類型的值。
運算的一個默認法則就是,通常情況下應(yīng)該是 相同類型的值才能相互運算 。
顯然,數(shù)字與數(shù)字之間的運算是合理的,但你讓 +
這個操作符對一個字符串和一個數(shù)字進行運算就不行:
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
11 + 10 - 9 * 8 / 7 // 6% 5
'3.14' + 3 # 這一句會報錯
20.0
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-18-e922b7565e53> in <module>
3
4 11 + 10 - 9 * 8 / 7 // 6 % 5
----> 5 '3.14' + 3 # 這一句會報錯
TypeError: can only concatenate str (not "int") to str
所以,在不得不對不同類型的值進行運算之前,總是要事先做 Type Casting(類型轉(zhuǎn)換)。比如,
- 將字符串轉(zhuǎn)換為數(shù)字用
int()
、float()
;- 將數(shù)字轉(zhuǎn)換成字符串用
str()
;
另外,即便是在數(shù)字之間進行計算的時候,有時也需要將整數(shù)轉(zhuǎn)換成浮點數(shù)字,或者反之:
- 將整數(shù)轉(zhuǎn)換成浮點數(shù)字用
float()
;- 將浮點數(shù)字轉(zhuǎn)換成整數(shù)用
int()
;
有個函數(shù),type()
,可以用來查看某個值屬于什么類型:
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
type(3)
type(3.0)
type('3.14')
type(True)
type(range(10))
type([1,2,3])
type((1,2,3))
type({1,2,3})
type({'a':1, 'b':2, 'c':3})
int
float
str
bool
range
list
tuple
set
dict
操作符
針對不同類型的數(shù)據(jù),有各自專用的操作符。
數(shù)值操作符
針對數(shù)字進行計算的操作符有加減乘除商余冪:+
、-
、*
、/
、//
、%
、**
。
其中 +
和 -
可以對單個值進行操作,-3
;其它的操作符需要有兩個值才能操作。
從優(yōu)先級來看,這些操作符中:
- 對兩個值進行操作的
+
、-
的優(yōu)先級最低;- 稍高的是
*
、/
、//
、%
;- 更高的是對單個值進行操作的
+
、-
;- 優(yōu)先級最高的是
**
。
完整的操作符優(yōu)先級列表,參見官方文檔:expressions
布爾值操作符
針對布爾值,操作符有與
、或
、非
:and
、or
、not
。
它們之中,優(yōu)先級最低的是或 or
,然后是與 and
, 優(yōu)先級最高的是非 not
:
True and False or not True
False
最先操作的是 not
,因為它優(yōu)先級最高。所以,上面的表達式相當于 True and False or (not True)
,即相當于 True and False or False
;
然后是 and
,所以,True and False or False
相當于是 (True and False) or False
,即相當于 False or False
;
于是,最終的值是 False
。
邏輯操作符
數(shù)值之間還可以使用邏輯操作符,1 > 2
返回布爾值 False
。邏輯操作符有:<
(小于)、<=
(小于等于)、>
(大于)、>=
(大于等于)、!=
(不等于)、==
(等于)。
邏輯操作符的優(yōu)先級,高于布爾值的操作符,低于數(shù)值計算的操作符。 即:數(shù)值計算的操作符優(yōu)先級最高,其次是邏輯操作符,布爾值的操作符優(yōu)先級最低。
n = -95
n < 0 and (n + 1) % 2 == 0
True
字符串操作符
針對字符串,有三種操作:
- 拼接:
+
和' '
(后者是空格)- 拷貝:
*
- 邏輯運算:
in
、not in
;以及,<
、<=
、>
、>=
、!=
、==
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
'Awesome' + 'Python'
'Awesome' 'Python'
'Python, ' + 'Awesome! ' * 3
'o' in 'Awesome' and 'o' not in 'Python'
'AwesomePython'
'AwesomePython'
'Python, Awesome! Awesome! Awesome! '
False
字符之間,字符串之間,除了 ==
和 !=
之外,也都可以被邏輯操作符 <
、<=
、>
、>=
運算:
'a' < 'b'
True
這是因為字符對應(yīng)著 Unicode 碼,字符在被比較的時候,被比較的是對應(yīng)的 Unicode 碼。
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
'A' > 'a'
ord('A')
ord('a')
False
65
97
當字符串被比較的時候,將從兩個字符串各自的第一個字符開始逐個比較,“一旦決出勝負馬上停止”:
'PYTHON' > 'Python 3'
False
列表的操作符
數(shù)字和字符串(由字符構(gòu)成的序列)是最基本的數(shù)據(jù)類型,而我們往往需要批量處理數(shù)字和字符串,這樣的時候,我們需要數(shù)組(array)。不過,在 Python 語言中,它提供了一個容器(Container)的概念,用來容納批量的數(shù)據(jù)。
Python 的容器有很多種 —— 字符串,其實也是容器的一種,它的里面容納著批量的字符。
我們先簡單接觸一下另外一種容器:列表(List)。
列表的標示,用方括號 []
;舉例來說,[1, 2, 3, 4, 5]
和 ['ann', 'bob', 'cindy', 'dude', 'eric']
,或者 ['a', 2, 'b', 32, 22, 12]
都是一個列表。
因為列表和字符串一樣,都是 有序容器 (容器還有另外一種是無序容器),所以,它們可用的操作符其實相同:
- 拼接:
+
(與字符串不一樣的地方是,不能用空格' '
了)- 拷貝:
*
- 邏輯運算:
in
、not in
;以及,<
、<=
、>
、>=
、!=
、==
兩個列表在比較時(前提是兩個列表中的數(shù)據(jù)元素類型相同),遵循的還是跟字符串比較相同的規(guī)則:“一旦決出勝負馬上停止”。但實際上,由于列表中可以包含不同類型的元素,所以,通常情況下沒有實際需求對他們進行 “大于、小于” 的比較。(比較時,類型不同會引發(fā) TypeError
…… )
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
a_list = [1, 2, 3, 4, 5]
b_list = [1, 2, 3, 5]
c_list = ['ann', 'bob', 'cindy', 'dude', 'eric']
a_list > b_list
10 not in a_list
'ann' in c_list
False
True
True
更復雜的運算
對于數(shù)字進行加、減、乘、除、商、余、冪的操作,對于字符串進行拼接、拷貝、屬于的操作,對布爾值進行或、與、非的操作,這些都是相對簡單的運算。
更為復雜一點的,我們要通過調(diào)用函數(shù)來完成 —— 因為在函數(shù)內(nèi)部,我們可以用比 “單個表達式” 更為復雜的程序針對傳遞進來的參數(shù)進行運算。換言之,函數(shù)就相當于各種事先寫好的子程序,給它傳遞一個值,它會對其進行運算,而后返回一個值(最起碼返回一個 None
)。
以下是 Python 語言所有的內(nèi)建函數(shù)(Built-in Functions):
(PythonBuilt-inFunctions)abs()delattr()hash()memoryview()set()
all()dict()help()min()setattr()
any()dir()hex()next()slice()
ascii()divmod()id()object()sorted()
bin()enumerate()input()oct()staticmethod()
bool()eval()int()open()str()
breakpoint()exec()isinstance()ord()sum()
bytearray()filter()issubclass()pow()super()
bytes()float()iter()print()tuple()
callable()format()len()property()type()
chr()frozenset()list()range()vars()
classmethod()getattr()locals()repr()zip()
compile()globals()map()reversed()__import__()
complex()hasattr()max()round()
現(xiàn)在倒不用著急一下子全部了解它們 —— 反正早晚都會的。
這其中,針對數(shù)字,有計算絕對值的函數(shù) abs()
,有計算商余的函數(shù) divmod()
等等。
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
abs(-3.1415926)
divmod(11, 3)
3.1415926
(3, 2)
這些內(nèi)建函數(shù)也依然只能完成 “基本操作”,比如,對于數(shù)字,我們想計算三角函數(shù)的話,內(nèi)建函數(shù)就幫不上忙了,于是,我們需要調(diào)用標準庫(Standard Library)中的 math 模塊(Module):
import math
math.sin(5)
-0.9589242746631385
代碼 math.sin(5)
這里的 .
,也可以被理解為 “操作符”,它的作用是:
從其它模塊中調(diào)用函數(shù)。
代碼 math.sin(5)
的作用是:
把
5
這個值,傳遞給math
這個模塊里的sin()
函數(shù),讓sin()
根據(jù)它內(nèi)部的代碼對這個值進行運算,而后返回一個值(即,計算結(jié)果)。
類(Class)中定義的函數(shù),也可以這樣被調(diào)用 —— 雖然你還不明白類(Class)究竟是什么,但從結(jié)構(gòu)上很容易理解,它實際上也是保存在其他文件中的一段代碼,于是,那段代碼內(nèi)部定義的函數(shù),也可以這樣調(diào)用。
比如,數(shù)字,其實屬于一個類,所以,我們可以調(diào)用那個類里所定義的函數(shù),比如,float.as_integer_ratio()
,它將返回兩個值,第一個值除以第二個值,恰好等于傳遞給它的那個浮點數(shù)字參數(shù):
3.1415926.as_integer_ratio()
3.1415926.as_integer_ratio()
關(guān)于布爾值的補充
當你看到以下這樣的表達式,而后再看看它的結(jié)果,你可能會多少有點迷惑:
True or 'Python'
True
這是因為 Python 將 True
定義為:
By default, an object is considered true unless its class defines either a __bool__() method that returns
False
or a __len__() method that returns zero, when called with the object.
這一段文字,初學者是看不懂的。但下一段就好理解了:
Here are most of the built-in objects considered
False
:
所以,'Python'
是個非空的字符串,即,不屬于是 empty sequences
,所以它不被認為是 False
,即,它的布爾值是 True
于是,這么理解就輕松了:
每個變量或者常量,除了它們的值之外,同時還相當于有一個對應(yīng)的布爾值。
關(guān)于值的類型的補充
除了數(shù)字、布爾值、字符串,以及上一小節(jié)介紹的列表之外,還有若干數(shù)據(jù)類型,比如 range()
(等差數(shù)列)、tuple
(元組)、set
(集合)、dictionary
(字典),再比如 Date Type
(日期)等等。
它們都是基礎(chǔ)數(shù)據(jù)類型的各種組合 —— 現(xiàn)實生活中,更多需要的是把基礎(chǔ)類型組合起來構(gòu)成的數(shù)據(jù)。比如,一個通訊簿,里面是一系列字符串分別對應(yīng)著若干字符串和數(shù)字。
entry[3662] = {
'first_name': 'Michael',
'last_name': 'Willington',
'birth_day': '12/07/1992',
'mobile': {
'+714612234',
'+716253923'
}
'id': 3662,
...
}
針對不同的類型,都有相對應(yīng)的操作符,可以對其進行運算。
這些類型之間有時也有不得不相互運算的需求,于是,在相互運算之前同樣要 _Type Casting_,比如將 List 轉(zhuǎn)換為 Set,或者反之:
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
a = [1, 2, 3, 4, 5, 6, 7]
b = set(a)
c = list(b)
a
b
c
[1, 2, 3, 4, 5, 6, 7]
{1, 2, 3, 4, 5, 6, 7}
[1, 2, 3, 4, 5, 6, 7]
總結(jié)
回到最開始:從結(jié)構(gòu)上來看,一切的計算機程序,都由且只由兩個最基本的成分構(gòu)成:
- 運算(Evaluation)
- 流程控制(Control Flow)
這一章主要介紹了基礎(chǔ)數(shù)據(jù)類型的運算細節(jié)。而除了基礎(chǔ)數(shù)據(jù)類型,我們需要由它們組合起來的更多復雜數(shù)據(jù)類型。但無論數(shù)據(jù)的類型是什么,被操作符操作的總是該數(shù)據(jù)的值。所以,雖然絕大多數(shù)編程書籍按照慣例會講解 “數(shù)據(jù)類型”,但為了究其本質(zhì),我們在這里關(guān)注的是 “值的類型”。雖然只是關(guān)注焦點上的一點點轉(zhuǎn)換,但實踐證明,這一點點的不同,對初學者更清楚地把握知識點有巨大的幫助。
針對每一種 值 的類型,無論簡單復雜,都有相應(yīng)的操作方式:
- 操作符
- 值運算
- 邏輯運算
- 函數(shù)
- 內(nèi)建函數(shù)
- 其他模塊里的函數(shù)
- 其本身所屬類之中所定義的函數(shù)
所以,接下來要學習的,無非就是熟悉各種 數(shù)據(jù)類型 ,及其相應(yīng)的操作,包括能對它們的值進行操作的操作符和函數(shù);無論是操作符還是函數(shù),最終都會返回一個相應(yīng)的值,及其相應(yīng)的布爾值 —— 這么看來,編程知識結(jié)構(gòu)沒多復雜。因為換句話講,
接下來你要學習的無非是各種 數(shù)據(jù)類型 的運算而已。
另外,雖然現(xiàn)在尚未來得及對函數(shù)進行深入講解,但最終你會發(fā)現(xiàn)它跟操作符一樣,在程序里無所不在。
備注
另外,以下幾個鏈接先放在這里,未來你會返回來參考它們,還是不斷地參考它們:
- 關(guān)于表達式:
- 關(guān)于所有操作的優(yōu)先級:
- 上一條鏈接不懂 BNF 的話根本讀不懂:
- Python 的內(nèi)建函數(shù):
- Python 的標準數(shù)據(jù)類型:
另外,其實所有的操作符,在 Python 內(nèi)部也是調(diào)用函數(shù)完成的……
本文地址:http://003188.cn/zhijiqixiangyingdeyunsuan.html
阿里云虛擬主機1G空間,120元一年
香港、美國虛擬主機100元一年,1000元永久
騰訊云雙十一0.4折起,2核8G5M三年僅700元,2核4G8M三年僅198元
猜你喜歡