1.1 Python3-print()
在Python3中。print()的使用方法如下:
# Pycharm中演示# ==== print() end引數 ====print('hello',end='<----')print('world')# ==== 執行結果 ====# hello<----world
print後面必須跟上括號,所列印的內容必須由單引號、雙引號、三單引號、三雙引號、以上其中任意一種括起來才能使用。這是Python語法規定的死規範。
除此之外print()還可以接收3個引數分別是 sep 和 end以及file:
print()引數詳解 sep 用來顯示間隔中的連結字元,預設為一個空格end 指定當print()結束後的下一個print()的位置相較於上一次print()。預設換行 \nfile 指定print()的內容寫入到某個指定的檔案控制程式碼中。預設為空
** sep示例:**
>>> # ==== print() sep引數 ====>>>>>> print("hello","world") # 不指定sep引數hello world>>> print("hello","world",sep="-------") #指定sep引數hello-------world
** end示例:**
# Pycharm中演示# ==== print() end引數 ====print('hello',end='<----')print('world')hello<----world
** file示例:**
# Pycharm 中演示# ==== print() file引數 ====with open(file='a.text',mode='w',encoding='utf-8') as f: print('這一行將被寫入檔案中去...',file=f)
print()的底層實現原理(自我猜測版本):
在這可以看到sys.stdout的字樣。所以這裡猜想是呼叫了sys.stdout.write()方法,如果我們將file指定為某一個檔案,那麼螢幕上便不會再顯示print()列印的字樣而是直接將內容寫入到了檔案中。
而flush是重新整理的意思,以下程式碼可以在原生Python直譯器中開啟執行一下。分別刪除flush = True 執行2次你就能看到效果了。
# ==== print() flush引數 ====import timetime.sleep(0.1)print('下載中',end="")for i in range(100): print('#',flush=True,end="") # 一種直接全部列印 100 個 #。加了flush = True偶則是慢慢列印。會有一種視覺上的效果
1.2 Python2-print()
Python2的print()允許像Python3那樣使用,但更多人使用Python2的print()是不帶括號的。關於使用方式有這點差別,更深層的東西這裡沒有去研究了。
>>> # ==== Python2 print() ====>>>>>> print("hello,world") # 允許 Python3中的使用方式hello,world>>> print "hello,world" # 允許 不加入括號,這在Python3中是不被允許的hello,world
2.1 Python3-input()
Python3中提供了input()方法來接收使用者輸入的值。但是Python3中的input()方法會將一切使用者輸入的值轉換為str型別。這裡一定要注意!
# ==== Python3 - input() ====name = input("請輸入您的姓名:")age = input("請輸入您的年齡:")print("name的型別是:",type(name))print("age的型別是",type(age)) # <class 'str'># ==== 執行結果 ===="""請輸入您的姓名:yunya請輸入您的年齡:18name的型別是: <class 'str'>age的型別是 <class 'str'>"""
如果我們想求一個整形或者浮點型的資料,我們就將其使用int()或者float()包裹住輸入的資料即可:
int()
- 只能包裹字串str型別以及浮點型float(向下取整)
float()
- 只能包裹字串str型別以及整形
# ==== Python3 input() 型別轉換 ====name = input("請輸入您的姓名:")age = int(input("請輸入您的年齡:")) #注意用int()包裹input()返回的str型別的內容。並且做一次轉換:確保使用者輸入的是 整形樣式的字串,否則會丟擲異常print("name的型別是:",type(name))print("age的型別是",type(age)) # <class 'int'># ==== 執行結果 ===="""請輸入您的姓名:yunya請輸入您的年齡:18name的型別是: <class 'str'>age的型別是 <class 'int'>"""
這裡提一嘴:如果使用者輸入的不是整形樣式的字串,則會丟擲異常。那麼如何處理先不著急,只需要記得肯定有處理的方法。
2.2 Python2-raw_input()
Python2中的 raw_input() 和上面介紹的 Python3 中的input()使用方法和功能全部都是一樣的。這裡不做詳解,需要注意的是:Python3中沒有raw_input()方法。
>>> # ==== Python2中的raw_input() ====>>>>>> name = raw_input("請輸入姓名:")請輸入姓名:yunya>>> age = raw_input("請輸入年齡:")請輸入年齡:18>>> type(name)<type 'str'>>>> type(age)<type 'str'>
2.3 Python2-input()
Python2中的input()與Python3中的input()大不相同。Python3中的input()無論使用者輸入的值是什麼都會轉換為str型別,而Python2中的input()是使用者輸入什麼型別的值就自動轉換成什麼型別,看起來挺好的。但是實際是非常不方便的,具體原因看下圖:
>>> # ==== Python2中的input() ====>>>>>> name = input("請輸入姓名:")請輸入姓名:yunya # 注意:這裡沒加引號,Python2的input()會認為這是一個變數。而改變了未繫結堆區變數值,所以丟擲 yunya 未定義的這麼一個異常。Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<string>", line 1, in <module>NameError: name 'yunya' is not defined>>> name = input("請輸入姓名:")請輸入姓名:"yunya">>> name'yunya' #使用者必須按照Python語法規範來輸入,極大的拉低了使用者體驗>>>>>> city = input("請輸入城市:") #假如使用者輸入了不符合Python語法資料便直接丟擲異常。請輸入城市:["哈爾濱",Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<string>", line 1 ["哈爾濱", ^SyntaxError: invalid syntax>>>
3.1 %
格式化的意思是我們有的時候想讓變數值與定義好的字串做一個融合。這個時候就有三種方法,我們先來看第一種也是最原始的一種 % 方法:
# ==== %格式化 ====name = "yunya"age = 18# ==== 位置傳參 ====# 一個 % 對應一個 變數名。當變數名有多個時便需要%後面跟上括號做解包,如若只有一個則不需要加上括號,% 和後面的 %(a,b,c)位置一一對應msg = "姓名是:%s,年齡是%i"%(name,age) # %意味佔位符,後面的字元代表轉換的型別。如 %s代表接收任意型別的傳值,%i代表只接受int型別的傳值。print(msg)# ==== 關鍵字傳參 ====msg2 = "姓名是:%(name)s,年齡是%(age)i" %{'age':age,'name':name} # 變數名儲存變數值記憶體地址引用。關鍵字傳參打破位置順序必須統一的限制.print(msg2)# ==== 格式化 % 百分號 ====print('%s%%'%3) # %% 百分號代表一個 % 。放在 %s 後面則代表格式化出後的結果是 3%# ==== 執行結果 ==== """姓名是:yunya,年齡是18姓名是:yunya,年齡是183%"""
佔位符說明:
%s 字串(採用str()的顯示) Ps:推薦使用 %s 。 因為它接收所有型別的傳值%r 字串(採用repr()顯示) Ps:原始字串%c 單個字元%b 二進位制整數%d 十進位制整數%i 十進位制整數%o 八進位制整數%x 十六進位制整數%e 指數 (基底寫為e)%E 指數 (基底寫為E)%f 浮點數%F 浮點數,與上相同%g 指數(e)或浮點數 (根據顯示長度)%G 指數(E)或浮點數 (根據顯示長度)
3.2 format()
%雖然能夠滿足基本需求。但是其位置傳參還是顯得太過麻煩,故在Python2.6中新增format() 方法,它更加強大以及速度更快。推薦今後使用format()的方法進行字串格式化 ,注意:format()中的s只接受str型別的傳值而不接受全部型別!!!
# ==== format()格式化 ====name = "yunya"age = 18# ==== 位置傳參 ====msg = "姓名是{:s},年齡是{:d}".format(name, age) # 採用{}進行佔位,需要注意的是format中的 s 不是接收全部型別的引數,而是指定str# msg = "姓名是{},年齡是{}" .format(name,age) 也可不指定型別。預設接收全部型別引數print(msg)# ==== 索引傳參 ====msg2 = "姓名是{1:d},年齡是{0:s}".format(name, age) # 採用{}進行佔位 。 無法使用s接收age.且 format()中沒有 i# msg2 = "姓名是{1},年齡是{0}" .format(name,ageprint(msg2)msg3 = "姓名是{0:s}{0:s}{0:s},年齡是{1:d}{1:d}{1:d}".format(name, age) # 採用{}進行佔位 。 無法使用s接收age# msg3 = "姓名是{0:s}{0:s}{0:s},年齡是{1:d}{1:d}{1:d}".format(name, age) #print(msg3)# ==== 關鍵字傳參 ====msg4 = "姓名是{name:s},年齡是{age:d}".format(name=name, age=age) # 採用{}進行佔位 。 無法使用s接收age# msg4 = "姓名是{name},年齡是{age}" .format(name=name,age=age)print(msg4)# ==== 字元填充 ====print('{0:*<10}'.format('|||')) # < 代表字元 ||| 在左邊,填充符號為 * 排在右邊 一共10 個( 算上字元三個 | )print('{0:%>10}'.format('|||')) # > 代表字元 ||| 在右邊,填充符號為 % 排在左邊 一共10 個 ( 算上字元三個 | )print('{0:$^10}'.format('|||')) # ^ 代表字元 ||| 在中間,填充符號為 $ 排在兩側 兩側加起來共10個 ( 算上字元三個 | )print('{0:$=10}'.format(123)) # = 代表數字 123 在右邊,填充符號為 $ 排在左邊 一共10個 Ps: = 只針對數字 ( 算上字元123 )# ==== 精度控制與格式轉換 ====print('{0:.2f}'.format(3.1415926535)) # f代表接收值型別為float型別,.2代表小數點後保留2位print('{0:b}'.format(10)) # 轉換為二進位制 bprint('{0:x}'.format(10)) # 轉換為十六進位制 xprint('{0:o}'.format(10)) # 轉換為八進位制 oprint('{0:,}'.format(1000000)) # 千分位表示 ,print('{0:.2%}'.format(1)) #百分號表示 2代表2位數,轉換資料1 為 百分之百print('{0:.2%}'.format(0.3)) #百分號表示print('{{{0}}}'.format('笑臉')) # 顯示大括號。 外部套2層大括號# ==== 執行結果 ===="""姓名是yunya,年齡是18姓名是18,年齡是yunya姓名是yunyayunyayunya,年齡是181818姓名是yunya,年齡是18|||*******%%%%%%%|||$$$|||$$$$$$$$$$$1233.141010a121,000,000100.00%30.00%{笑臉}"""
3.3 Python3-f
儘管format()已經非常方便了。但是如果傳入的引數值太多依舊會看著十分混亂,於是Python3.6中新增了 f 格式字串的操作。這種方法的速度最快,但是卻不推薦使用,因為程式還要考慮一個向下相容性的問題。
# ==== f 格式化 ====name = "yunya"age = 18msg = f'我的名字叫做{name},我的年齡是{age}歲。' # f 開頭。 {} 為佔位符用於存放變數名。print(msg)# 其他的關於高階操作如填充字元,精度控制與格式轉換等等均與format()操作方式一樣。# ==== 執行結果 ===="""我的名字叫做yunya,我的年齡是18歲。"""
4.1 +- * /
詳細舉例每種資料型別支援的運算子:
- 加法運算:
int:int float(生成float) bool
float:float int bool
bool:bool int float (均生成int或float)
list:list(改變元素內index的引用值,而不改變list對應棧區變數名的引用值)
str:str(由於是不可變型別,生成新的str)
tuple:tuple (由於是不可變型別,生成新的tuple)
# ==== + 加法運算 ====# 以下程式碼均在Pycharm中測試通過print(1 + 1)print(1 + 1.1)print(1 + True)print([1, 2, 3] + [4, 5, 6])print('OldStr ' + ' NewStr') # 改變引用值,生成新物件print((1, 2, 3) + (4, 5, 6)) # 改變引用值,生成新物件# ==== 執行結果 ===="""22.12OldStrNewStr[1, 2, 3, 4, 5, 6](1, 2, 3, 4, 5, 6)"""
- 減法運算:
int:int float(生成float)bool
float:float int bool
bool:bool int float (均生成int或float)
# ==== - 加法運算 ====# 以下程式碼均在Pycharm中測試通過print(1 - 1)print(1 - 1.1)print(1 - True)# ==== 執行結果 ===="""0-0.100000000000000090"""
- 乘法運算:
int:int float(生成float)bool list(生成list不改變原本引用值) str(新生成str改變原本引用值)tuple(新生成tuple改變原本引用值)
float:float int bool
bool: bool int float
list: int (生成list不改變原本引用值)
str: int (新生成str改變原本引用值)
tuple: int (新生成str改變原本引用值)
# ==== * 乘法運算 ====# 以下程式碼均在Pycharm中測試通過s1 = '#'l1 = [1,2,3]t1 = (1,2,3)print(1 * 2)print(1 * 2.0)print(1 * True)print(3 * l1)print(3 * s1) #改變引用值,生成新的str物件print(3 * t1) #改變引用值,生成新的tuple物件# ==== 執行結果 ===="""22.01[1, 2, 3, 1, 2, 3, 1, 2, 3]###(1, 2, 3, 1, 2, 3, 1, 2, 3)"""
/ 精確除法運算 Ps: 一律生成float:
int: int float bool 注意:0 不能做 除數
float: float int bool 注意:0.0 不能做除數
bool: bool int float 注意:False不能做 除數
# # ==== / 精確除法運算 ====# 以下程式碼均在Pycharm中測試通過print(10 / 2)print(10 / 2.0)print(10.1 / True)print(10.1 / True)print(10.1 / True)print(10.1 / True)print(False / 10)print(True / 2)print(True / 2.0)# ==== 執行結果 ===="""5.05.010.110.110.110.10.00.50.5"""
4.2 // ** %
// 整數除法運算(向下取整) 與精確除法的可用資料型別相同 ,除開 2 個float型別 做運算為float 其他運算結果全是int。
** 冪運算(次方運算) 只支援 int float bool 三種型別。
% 求餘 只支援 int float bool 三種型別。如果被求餘數小於求餘數,那麼餘數就為被求餘數本身。
重點 方法介紹:divmod() 相當於整除法與求餘法的糅合
>>> # ==== divmod()示例 ====>>>>>> divmod(10,3) # 商3餘1(3, 1)>>> 1 % 10 #被求餘數小於求餘數。結果為其本身1
5.1 增量賦值
賦值符號本身就是一個 = 號。左邊是變數名,右邊是變數值這個沒什麼好說的了。增量賦值就是將賦值符號和算術運算子結合起來達到簡寫的目的:
# ==== 增量運算子與普通算術運算子對應關係及使用方式 ==== # 以下程式碼均在Pycharm中測試通過x = 1x = x + 10 # x += 1x = x - 10 # x -= 1x = x * 10 # x *= 1x = x / 10 # x /= 1x = x // 10 # x //= 1x = x ** 10 # x **= 1x = x % 10 # x %= 1
5.2 鏈式賦值
鏈式賦值也被稱為間接賦值:
>>> # ==== 鏈式賦值使用方式 ====>>>>>> x = y = z = 100 # 經常使用的一種鏈式賦值方式>>> x100>>> y100>>> z100>>> i = 100 # 鏈式賦值也被稱為間接賦值>>> j = i>>> i100>>> j100
5.3 交叉賦值
交叉賦值是Python獨有的一種語法:
>>> # ==== 交叉賦值使用方式 ====>>>>>> x = 100>>> y = 1000>>> x,y = y,x #互換2個變數名繫結的記憶體地址,即變數值的引用>>> y100>>> x1000
5.4 解壓賦值
解壓賦值一般只是用來拿到列表或者元組中開頭或結尾的一些資料:
>>> # ==== 解壓賦值使用方式 ====>>>>>> l1 = [1,2,3,4]>>> w,x,y,z = l1>>> w1>>> x2>>> y3>>> z4>>> a,b,*_ = l1 #取出前面2個值。字元 * 代表取所有以列表形式返回,變數名為單下劃線 _ 表示廢棄值不會使用。 >>> a1>>> b2>>>>>> *_,c,d = l1 #取出後面2個值>>> c3>>> d4
為什麼解壓賦值不能拿中間的值呢?因為解壓賦值依賴於字元 * 。假設列表長度為10,我要取第5個和第6個,那麼前面就必須要有4個變數儲存列表中解壓出來的前4個值。這麼做很麻煩所以一般不會用解壓賦值取中間的值。
不光可以對列表進行解壓賦值,字典也同樣可以。但是字典的解壓賦值只會取出key。
>>> # ==== 對字典的解壓賦值 ====>>>>>> dic = {"k1":"v1","k2":"v2","k3":"v3"}>>> a,b,c = dic #只取key>>> dic{'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}
6.1 > < == != >= <=
比較運算子一般是用於比較相同資料型別的2個值。返回一個bool型別的值(True或者False),常用於條件分支結構中。
> 大於 < 小於 == 等於 (注意 = 是賦值符號,不可用於比較運算) != 不等於 >= 大於或者等於 <= 小於或者等於
>>> # ==== 比較運算子的使用 ====>>>>>> 1 < 2True>>> 1 > 2False>>> 1 == 1.0True>>> 1 == TrueTrue
6.2 關於字串之間的比較
請解釋以下現象:
>>> "1235" < "456" #字串比較也是按照索引來比,一位一位去比True>>> ("100",) > ("45","b") #元組之間,或者列表之間的比較都是對同一索引下的值做比較。如果值是字串則繼續分成一位一位比,如果是int或者float則直接進行比較。False
由於是字串,所以按照index繼續一位一位比較。
由於是數字,所以比整體。
其實上面的比較只是初步的比較。詳細一點就來討論單個字元與單個字元之間的比較是怎麼進行的,首先。如果兩個都是字串,則對比索引按位比較沒問題。比如:”y” 單個字元對比 “k”,那麼又是依照什麼對比呢?其實這裡涉及到一個ASCII碼的概念。它們的這個字元就是通過ASCII碼來對比。
>>> ord("y") # 字元轉ASCII的函式ord() , ASCII轉字元則是 chr()121>>> ord("k")107>>> "y" > "k"True
7.1 not and or
邏輯運算子的作用在於做一系列邏輯判斷,常用於分支結構與流程控制中,所以這裡也是先引出概念,其中not代表非,and代表與,or代表否則。
>>> # === 邏輯運算子的使用 ====>>>>>> not True # not 我不管你是什麼,在我這裡只取反False>>> not FalseTrue>>> True and True # and 一真一假取一假,全部為真才取真True>>> True and FalseFalse>>> False and FalseFalse>>> True or True # or 一真一假取一真,全部為假才取假True>>> True or FalseTrue>>> False or FalseFalse
打油詩一首
作者:雲崖
not 我不管你是什麼,在我這裡只取反。
and 一真一假取一假,全部為真才取真。
or 一真一假取一真,全部為假才取假。
我們看一個很有趣的比喻:
# === not and or 優先順序 ==='''二狗子要找女朋友, 年齡不能大於25歲,這個是前提!!, 身高不能超過170或者體重不能超過60公斤。請問下面那個符合二狗子的需求?'''xiaoli = {'age':30,'height':158,'weight':90}xiaohua = {'age':38,'height':190,'weight':50}xiaocui = {'age':22,'height':164,'weight':58}# 人能一眼就看出來。計算機還要做一系列的判斷呢print(xiaoli['age']<25 and xiaoli['height']<170 or xiaoli['weight']<60) # Falseprint(xiaohua['age']<25 and xiaohua['height']<170 or xiaohua['weight']<60) # True 小花按理說是不符合二狗子要求的,為什麼通過了呢?print(xiaocui['age']<25 and xiaocui['height']<170 or xiaocui['weight']<60) # True
原來是優先順序搞的鬼,我們先不管優先順序是什麼。使用括號()可以提升優先順序,這和小學數學的四則運算是相同的道理
# ==== 使用括號修改原本 not and or 的優先順序 ====print(xiaoli['age']<25 and (xiaoli['height']<170 or xiaoli['weight']<60)) # Falseprint(xiaohua['age']<25 and (xiaohua['height']<170 or xiaohua['weight']<60)) # False 這樣就好了,二狗子沒有被騙 ... 注意加了括號改變了優先順序print(xiaocui['age']<25 and (xiaocui['height']<170 or xiaocui['weight']<60)) # True
7.2 區分優先順序
好了,通過上面的例子我們知道了有優先順序這個概念。那麼什麼是優先順序呢?
優先順序就是對於在 有 2 種或者以上的邏輯運算子時決定符號右側數值的歸屬權的問題。如下圖:
關於優先順序就先到這裡了。其他的還有一個偷懶機制名叫短路運算,待會介紹。
8.1 成員運算子
in 判斷一個元素是否在不在另一個集合之中(str,list,tuple,dict,set),也是用於分支結構之中,這裡依舊是引出概念:
>>> # ==== in 與 not 的結合使用 ====>>>>>> str1 = "abcdefg">>> list1 = ["a","b","c"]>>> tuple1 = ("a","b","c")>>> dict1 = {"a":1,"b":2,"c":3}>>> set1 = {"a","b","c","d"}>>> "a" in str1True>>> "a" not in str1False>>> "a" in list1True>>> "a" not in list1False>>> "a" in tuple1True>>> "a" not in tuple1False>>> "a" in dict1 #只會檢索字典的key,不會去檢索valueTrue>>> "a" not in dict1False>>> "a" in set1True>>> "a" not in set1False
8.2 身份運算子
is 判斷物件引用值是否相等,並非形式值。(引用值相同代表2個值資料儲存在同一堆區記憶體),故引用值相等的情況下形式值一定相等,形式值相等的情況下引用值不一定相等。具體可看Python變數與基本資料型別一章。
>>> # ==== is的使用 ====>>>>>> x=y=z=10000>>> x is yTrue>>> x is zTrue>>> y is xTrue>>> y is zTrue
關於邏輯運算子還有一個短路運算沒有說完。
如果一次邏輯運算中的邏輯運算子號全部為 and 或者 or 則會從左至右依次進行邏輯運算。如果每一次都進行運算是很消耗時間的,所以這個時候出現了短路機制。看圖說話:
本作品採用《CC 協議》,轉載必須註明作者和本文連結