type(2/2) float type(2//2) int
雙斜槓是整除,出來的類型是int。單斜槓的出來的是float類型。java
進製表示:python
- 二進制:0b
- 八進制:0o
- 十六進制:0x
進制轉換:c++
- 轉換爲二進制:bin()
- 轉換爲八進制:oct()
- 轉換爲十進制:int()
- 轉換爲十六進制:hex()
- 轉換爲布爾類型:bool()
布爾類型轉換:bool()windows
- bool(0)
- bool('') 中間沒有空格
- bool([])
- bool({})
- bool(None)
- bool(NoneType)
- bool(set{})
三個引號能夠再IDLE下回車不會執行換行。print函數能夠輸出n這樣的反義字符。
單個引號想回車換行能夠再前面加上字符便可。數組
''' sadasdj adas ''' Out[1]: '\nsadasdj\nadas\n' 'asda File "<ipython-input-2-6af9d7d5e65d>", line 1 'asda ^ SyntaxError: EOL while scanning string literal 'asdd\ adsad\ sad' Out[3]: 'asddadsadsad' print('asda\nsada\n') asda sada ''' asda\n ''' Out[5]: '\nasda\n\n'
原始字符串在print時只是輸出裏面的字符,不考慮反義之類的,當心r大寫R都沒有關係。app
print(r'c:\nsda\nsds') c:\nsda\nsds print(r'let's go') File "<ipython-input-3-a81b31c0c433>", line 1 print(r'let's go') ^ SyntaxError: invalid syntax
1.字符串的'+'和'*'函數
"hello"+"world" Out[1]: 'helloworld' "hello"*3 Out[2]: 'hellohellohello'
2.獲取字符串裏的字符ui
"hello world"[0] Out[3]: 'h' "hello world"[-1] Out[4]: 'd' # 包括左面可是不包括右面 "hello world"[0:4] Out[5]: 'hell' "hello world"[0:-1] Out[6]: 'hello worl' # 超出長度時會按字符串最大的長度進行截取 "hello world"[0:20] Out[7]: 'hello world' # 沒有右邊的值的時候,表示直接輸出到末尾 "hello world"[6:] Out[8]: 'world' # 負數在冒號前面的時候 "hello world"[-4:] Out[9]: 'orld'
1.1 基本操做
1.1.1 基本選取(切片)this
["新月打擊","蒼白之瀑","月之降臨","月神衝刺"] Out[10]: ['新月打擊', '蒼白之瀑', '月之降臨', '月神衝刺'] ["新月打擊","蒼白之瀑","月之降臨","月神衝刺"][0] Out[11]: '新月打擊' ["新月打擊","蒼白之瀑","月之降臨","月神衝刺"][0:2] Out[12]: ['新月打擊', '蒼白之瀑'] ["新月打擊","蒼白之瀑","月之降臨","月神衝刺"][-1:] Out[13]: ['月神衝刺'] a = [1,2,3,4,5,6,7,8] print(a[0:3]) print(a[0:len(a):2]) print(a[len(a):0:-2]) [1, 2, 3] [1, 3, 5, 7] [8, 6, 4, 2] #能夠看到,切片操做很簡單,第二個冒號後面的數字能夠看做是步長。注意負數時的用法。
能夠看到,當沒有冒號的時候,單個選取出的是元素的類型。可是當有冒號的時候,選取出的是序列的類型。這裏須要注意debug
1.1.2 列表的相加和乘法
["新月打擊","蒼白之瀑","月之降臨","月神衝刺"]+['虛弱','點燃'] Out[14]: ['新月打擊', '蒼白之瀑', '月之降臨', '月神衝刺', '虛弱', '點燃'] ['虛弱','點燃']*3 Out[15]: ['虛弱', '點燃', '虛弱', '點燃', '虛弱', '點燃']
1.1.3 判斷元素是否存在
3 in [1,2,3,4] Out[21]: True 3 not in [1,2,3,4] Out[22]: False
1.1.4 計算長度,最大小值
len([1,2,3]) Out[23]: 3 len("hesadad") Out[24]: 7 max([1,2,3,4,5,6]) Out[25]: 6 min([1,2,3,4]) Out[26]: 1
1.1.5 append()
能夠向列表中追加元素。
a = [1,2,3,4] a.append('5') Out[22]: [1, 2, 3, 4, '5']
type((1)) Out[16]: int type(('sd')) Out[17]: str type((1,2,3)) Out[18]: tuple
若是括號裏有一個元素,默認爲是一個運算,不會認爲是元組的括號。若是要定義只有一個元素的元組的:
type((1,)) Out[19]: tuple # 括號裏面什麼都沒有表示一個空元組 type(()) Out[20]: tuple
a = (1,2,3,[4,5]) a[3][1] = '2' print(a) (1, 2, 3, [4, '2'])
咱們能夠看到元組裏的列表能夠改變
- 字符串和元組都是不可變的類型
- 序列包括了字符串,列表和元組,序列均可以用下標索引和切片的方式。
{1,2,3,4,5,6} - {1,2} Out[1]: {3, 4, 5, 6} {1,2,3,4,5,6} & {1,2} Out[2]: {1, 2} {1,2,3,4,5,6} | {1,2,7} Out[3]: {1, 2, 3, 4, 5, 6, 7}
type({}) Out[8]: dict type(set()) Out[9]: set len(set()) Out[10]: 0
- 序列,集合和字典屬於組,是Python的基本數據類型。
a = 1 b = a a = 3 print(b) 1 a = [1,2,3,4] b = a a[0] = '1' print(b) ['1', 2, 3, 4]
值類型:int str tuple(不可改變),在從新定義的時候,由於不可改變會生成一個新的對象,這個時候b仍然指向原對象,a指向了一個新對象
引用類型:list,set,dict(能夠改變),在定義一個新對象的時候,會在原對象的基礎上進行改變而不產生新對象,因此不管是a仍是b都會指向已經改變的原對象,因此a和b的值都會變化。
再進一步的,能夠看如下代碼:
a = 'hello' id(a) Out[15]: 1510080259608 a = a + 's' id(a) Out[17]: 1510081716832 a[0] = 's' Traceback (most recent call last): File "<ipython-input-18-02436d67df37>", line 1, in <module> a[0] = 's' TypeError: 'str' object does not support item assignment
id()是查詢在計算機中的內存位置,咱們能夠看到發生了變化。因此a = a + 's'是能夠的。可是對字符串的賦值操做,是不能夠的,由於str是不可變的類型。
0 and 1 Out[1]: 0 1 and 2 Out[2]: 2 1 and 0 Out[3]: 0 1 or 2 Out[4]: 1 0 or 1 Out[5]: 1
由上面的例子咱們能夠看出and和or的邏輯判斷規則和c++一致。空字符串,0等判斷爲空,在上面的筆記中有記載。
成員運算符表示一個元素是否在一個組裏;成員運算符返回值類型是bool類型。在字典中,是判斷key值。
a = 1 a in {1:'1'} Out[7]: True a = '1' a in {1:'1'} Out[9]: False
is, is not
身份運算符比較的是身份而不是值,簡單來講就是內存地址。和關係運算符「==」不同。
a = 1 b = 1 a is b Out[12]: True id(a) Out[13]: 1438837200 id(b) Out[14]: 1438837200 b = 1.0 a is b Out[16]: False id(b) Out[17]: 2197963106536 a ==b Out[18]: True a = {1,2,3} b = {2,1,3} a==b Out[21]: True a is b Out[22]: False c = (1,2,3) d = (2,1,3) c ==d Out[25]: False c is d Out[26]: False id(a) Out[27]: 2197907160424 id(b) Out[28]: 2197990760232
咱們能夠看到,在無序的set集合中,元素順序不同在內存中位置不一樣,雖然值相同可是身份仍然不同。
&, |, ^, ~, <<, >>
以上都是把數字看成二進制進行運算。把數字按照二進制進行換算,以&舉例,相同位1,不一樣爲0。而後再把二進制數轉換成數字原來的進制。eg: 2&3 == 2
python中一切都是對象,對象有三大特徵,值(value), 身份(id), 類型(type)。判斷變量的類型,可使用isinstance()這個函數。
a = 'sds' isinstance(a,str) Out[30]: True isinstance(a,(str,int,float)) Out[31]: True isinstance(a,int) Out[32]: False
isinstance能夠判斷對象中的子類是否知足條件,因此比較好。
+ 單行註釋:# 快捷鍵:ctrl + /
+ 多行註釋:""" """ 快捷鍵:alt + shift + a
python中的普通模塊必須有一個包,當想要把一個可執行文件看成一個普通模塊運行時,可使用-m參數,如:
python -m 命名空間.模塊名
注意:此處若看成普通模塊,必須包括包名/命名空間。python中可執行文件沒有所屬包。此外,當使用-m參數後,頂級包也相對改變。
用來查看模塊或者類內部的變量,包括系統內置變量。
import sys infos = dir(sys) print(infos) ['__displayhook__', '__doc__', '__excepthook__', '__interactivehook__', '__loader__', '__name__', '__package__', '__spec__', '__stderr__', '__stdin__', '__stdout__', '_clear_type_cache', '_current_frames', '_debugmallocstats', '_enablelegacywindowsfsencoding',......] # 可見打出了許多的變量,是sys模塊內部的變量。下面的代碼中也有應用,只不過沒有參數。
if __name__ == '__main__': pass #來判斷模塊是否被看成入口文件被調用,若是被當作模塊就不會打印if條件成立執行的語句,若是被當作入口文件纔會執行
# 由父包引入子包或者同級別引入的狀況 import module # 只能引入同一個包(不包括子包)裏的模塊。注意這裏不能直接引入模塊的變量。 import module as name # 使用的時候name.變量/函數等。 from packet import module # 能夠父包裏的子包引入模塊。 from packet.module import module.變量/函數等 from module import * # 引入module內__all__指定的變量/函數等。 from module import module.變量1, module.變量2,...... # 引入多個變量可用逗號隔開
該文件,能夠在導入一個包,或者導入包中的函數的時候,系統會首先執行該文件。
from packet import * # 這行代碼會引入被引入包中__init__.py中__all__指定的模塊。
a = 2 b = 1 infos = dir() print(infos) ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'a', 'b'] # 上方除了'a','b'都是系統內置的變量。
下面介紹幾個比較重要的內置變量,利用import一個模塊的時候會執行該模塊裏面的內容的機制。對於入口文件和模塊文件,內置變量的值有所不一樣。
''' this is a c3 doc ''' print("name: "+__name__) print("package: "+__package__) print("doc: "+__doc__) print("flie: "+__file__) import sub11.c3 PS D:\pycode\sub1> python c2.py name: sub11.c3 package: sub11 doc: this is a c3 doc flie: D:\pycode\sub1\sub11\c3.py # __doc__記錄的是該模塊的開頭註釋 # __name__記錄該模塊的名字 # __package__記錄該模塊屬於的包 # __file__記錄該模塊的文件的絕對路徑
若是一個.py文件被當作一個應用程序的入口:
①它的名稱再也不是自己的模塊名稱,而是被強制更改成__main__
②它不屬於任何包
③file內置變量不會像普通模塊同樣顯示絕對路徑,它所顯示的值也不是肯定值,和執行命令所在目錄有關
注:python入口文件和普通導入的模塊文件是有差別的。
''' this is a c3 doc ''' print("name: "+__name__) print("package: "+ ( __package__ or "當前模塊不屬於任何包")) print("doc: "+__doc__) print("flie: "+__file__) name: __main__ package: 當前模塊不屬於任何包 doc: this is a c3 doc flie: c3.py # 該文件屬於sub11包(有__init__.py這個文件),可是咱們是直接執行的c3.py文件,可見此時若是在c3.py中打印內置變量,__name__被強制定位__main__,並且package上也不會顯示出所屬於的包,file路徑也發生了變化。
導入機制:
python模塊導入時的搜索路徑:
from ... import...
中若是沒有出現.模塊名
,也是絕對導入。.
號。好比你單獨運行某個模塊,可是在這個模塊裏你用了相對導入,那麼就會報錯。可是你在外面引入這個模塊的時候是不存在問題的。
- 頂級包與入口文件
main.py
的位置有關,與main.py
同級的包就是該包下全部模塊的頂級包。而對於入口文件來講不存在包的概念。- 絕對導入/絕對路徑:從頂級包到被導入模塊名稱的完整路徑。注意必定是完整的路徑。
- 相對導入,一個'.'表示當前包,兩個'..'表示上一級包.'...'上上級包,以此類推。
注意:
sys.path
中會自動添加該工程中的目錄,因此假設你在模塊a中相對引入其餘模塊b,模塊b所在的位置超過了你如今所運行的文件(入口文件)所在的位置,可是隻要不超過當前的工程目錄所在的位置,仍然能夠進行相對導入。import sys sys.setrecursionlimit(10000) # 能夠設置最大迭代10000次。不過理論上雖然設置這麼多,但實際上仍然達不到容許迭代這麼屢次。
python函數返回多個值直接在return後面用逗號分隔要返回的值便可,返回結果是tuple元組類型。比較好的接收函數返回的多個值的方法不是用一個變量接收元組而後用序號訪問它的元素,而是直接用多個值接收而後分別使用這些變量,如:
def damage(skill1, skill2) damage1 = skll1 * 3 damage2 = skill2 * 3 + 10 return damage1, damage2 skill1_damage, skill2_damage = damage(3, 6) print(skill1_danage, skill2_damage)
上面的接受參數的方式叫作序列解包。
d = 1, 2, 3 print(type(d)) a, b, c = d print(a, b, c) print('----------------') a = b = c = 1 print(a, b, c) <class 'tuple'> 1 2 3 ---------------- 1 1 1
由於是序列解包,因此能夠不是元組,列表也是能夠的。最後若是多個變量取同一個值,那麼能夠用上面的方法來進行賦值。
函數參數有:
def demo(*param): print(param) print(type(param)) demo(1,2,3,[4,5,6]) (1, 2, 3, [4, 5, 6]) <class 'tuple'> # 傳入可變參數,會定義爲元組。 def demo(*param): print(param) print(type(param)) a = 1,2,3 demo(a) demo(*a) ((1, 2, 3),) <class 'tuple'> (1, 2, 3) <class 'tuple'> # *能夠解包。 def demo(**param): print(param) print(type(param)) demo(q='萬能牌', w='切牌', e='占卜') {'q': '萬能牌', 'w': '切牌', 'e': '占卜'} <class 'dict'> # 可見傳進來之後是一個字典,很方便。這就是關鍵字可變參數。 def demo(**param): print(param) print(type(param)) for key,value in param.items(): print(key,':',value,end='|| ') demo(q='萬能牌', w='切牌', e='占卜') {'q': '萬能牌', 'w': '切牌', 'e': '占卜'} <class 'dict'> q : 萬能牌|| w : 切牌|| e : 占卜|| # 傳入字典時能夠採用上面的方式取出鍵值和內容。 def demo(**param): print(param) print(type(param)) for key,value in param.items(): print(key,':',value,end='|| ') a = {'q':'萬能牌', 'w':'切牌', 'e':'占卜'} demo(**a) {'q': '萬能牌', 'w': '切牌', 'e': '占卜'} <class 'dict'> q : 萬能牌|| w : 切牌|| e : 占卜|| # 和傳入元組同樣,解序列能夠傳入兩個*。
def demo(param1,param2 = 2,*param3): print(param1) print(param2) print(param3) demo('a', 1,2,3) a 1 (2, 3) # 可見若是默認參數在可變參數以前,會發生錯誤,和預想的(1,2,3)賦值給param3有區別。 --------------------------------------------------------------------------- # 調整一下順序能夠獲得想要的結果 def f1(name1, *args, name2='2', **kw): print(name1) print(name2) print(args) print(kw) f1('1','3','4',a='1',b='2') 1 2 ('3', '4') {'a': '1', 'b': '2'}
__init__(self)
:類名.__init__()
來執行構造函數。__init__()
中;實例變量是定義在___init__()
中的。換句話說,實例變量是對象的,類變量是類的,兩者不能混淆。class Student(): name = 'Catherian' age = 0 high = 170 def __init__(self, name, age, high): self.name = name self.age = age high = high # 注意這裏的身高沒有用self.high來定義 def doHomework(self): print('doHomework') student1 = Student('呵呵噠', 18, 180) student2 = Student('ojbk', 16, 175) print(student1.name, student1.age, student1.high) print(student2.name, student2.age, student2.high) print(Student.name, Student.age, Student.high) print(student1.__dict__) print(Student.__dict__) 呵呵噠 18 170 ojbk 16 170 Catherian 0 170 # 這裏打印出的纔是類變量 # 能夠看到,儘管咱們在實例化student1,student2的時候傳入了身高high這個數據,可是打印的時候咱們發現輸出的是類變量high,並非實例變量。 {'name': '呵呵噠', 'age': 18} # __dict__對與對象,打印出的是對象的實例變量。可見裏面並無high。因此實例變量是用 self. 來定義的。類的__dict__是打印出對象裏面的內容,包括數據成員和方法,下面便是 {'__module__': '__main__', 'name': 'Catherian', 'age': 0, 'high': 170, '__init__': <function Student.__init__ at 0x000001F06B70F9D8>, 'doHomework': <function Student.doHomework at 0x000001F06B70FA60>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}
雖然咱們在實例化對象時傳入了數據,可是咱們發現high是類變量不是實例變量,可是仍然sudent1.high打印出了變量,這是類變量而不是實例變量。這是由於,python中的查找機制:當查找實例變量不存在的時候,會繼續向上查找類中相對應的類變量,若是子類中沒有父類中有(出現繼承)時,會查找到父類。因此咱們打印出了類變量。
self.
給出的是實例變量。self.
的形式來進行調用。由於你傳入的是形參.類名.類變量
和self.__class__.類變量
class Student sum = 0 @classmethod def student_sum(cls): pass # cls能夠更換,函數上面是一個裝飾器,表示了這是一個類方法。cls換成self或者其餘任意的都是能夠的,和實例方法中self能夠任意替換別的字符是同樣的。
對於類方法,調用類變量:cls.類變量
便可。因此cls表明的就是所屬於的類。在調用類方法的時候,能夠 Student.studen_sum
也能夠經過對象來調用,即:student1.student_sum
。可是建議用類名來調用比較好。
class Student sum = 0 @staticmethod def add(x,y) pass
靜態方法上一樣要有裝飾器來修飾,可是函數中不用顯式的傳入self或者cls,更像是一個普通的函數。在類方法和靜態方法中都不能調用實例變量。通常不建議用靜態方法,類方法更方便。
在python中,實際上沒有什麼是不能訪問的。成員可見性更像是一種標誌,一切全靠自覺。定義私有變量或者方法的時候,只須要在變量或者方法前面加上雙下劃線就表明了私有(注意不要同時在後面再加上雙下劃線)。
# 咱們定義一個學生類 class Student(): name = 'Catherian' age = 0 __high = 170 def __init__(self, name, age): self.name = name self.age = age self.__score = 0 def __doHomework(self): print('doHomework') student1 = Student('呵呵噠', 18) print(student1.__score) Traceback (most recent call last): File "c1.py", line 15, in <module> print(student1.__score) AttributeError: 'Student' object has no attribute '__score' # 能夠看到不能這樣訪問。 --------------------------------------------------------------------- # 若是咱們再加上一句再執行: student1 = Student('呵呵噠', 18) student1.__score = -1 print(student1.__score) -1 # 咱們發現居然能夠成功賦值而且訪問的。這是由於 studen1.__score = -1 這個操做實際上是又定義了一個新的實例變量。咱們能夠打印看一下 student1 = Student('okk', 18) student1.__score = -1 # print(student1.__score) print(student1.__dict__) {'name': 'okk', 'age': 18, '_Student__score': 0, '__score': -1} # 咱們能夠看到,咱們再裏面定義的__score變量被定義成了_Student__score變量,__score變量是咱們根據Python動態特性新定義出的實例變量。因此要訪問私有變量也很簡單: print(student1._Student__score) 0 # 因此這個真的全靠自覺,python中沒什麼是不能訪問的。
python中能夠單繼承也能夠多繼承。
類變量和實例變量
中說明的搜索規則進行。super(子類名, self)
進行調用父類重名函數。# 定義一個Human父類 class Human(): sum = 0 def __init__(self, name, age): self.name = name self.age = age self.__class__.sum += 1 def get_name(self): print(self.name) def do_Homework(self): # 重名的方法 print("this is a parent method") # 定義一個子類Student from c2 import Human class Student(Human): sum = 0 # 和父類重名的類變量 def __init__(self, name, age, score): # 父類還有兩個參數,因此這裏有三個參數 Human.__init__(self, name, age) # 這裏注意經過類名調用方法,不能不加self self.score = score self.__class__.sum += 1 def do_Homework(self): # 和父類重名的方法。 super(Student, self).do_Homework() print('doHomework') student1 = Student('okk', 18, 61) print(student1.sum) print(Student.sum) print(student1.get_name()) print(student1.do_Homework()) 2 # 可見經過父類方法裏對sum的操做,繼承到子類中時,對於重名變量仍然能夠操做子類中的重名變量。 2 # 根據搜索機制,實例變量裏沒有找到子類裏的類變量,再沒有找父類。 okk None this is a parent method # 可見調用了父類中的方法。 doHomework None
python中的枚舉類型實際上是一個類。
from enum import Enum class diamond(Enum): # 必需要繼承父類Enum YELLOW = 1 BLUE = 2 GREEN = 3 RED = 4 print(diamond.YELLOW) diamond.YELLOW # 可見打印出的就是diamend.YELLOW
from enum import Enum class diamond(Enum): YELLOW = 1 BLUE = 1 GREEN = 3 RED = 4 print(diamond.BLUE) print(diamond.__members__.items()) # items()能夠不須要。打印出全部的枚舉類型。 diamond.YELLOW # 可打印的是BLUE出來的是YEELOW。 odict_items([('YELLOW', <diamond.YELLOW: 1>), ('BLUE', <diamond.YELLOW: 1>), ('GREEN', <diamond.GREEN: 3>), ('RED', <diamond.RED: 4>)])
diamond.YELLOW = 5
是會報錯的。from enum import Enum class diamond(Enum): YELLOW = 1 BLUE = 2 GREEN = 3 RED = 4 print("枚舉類型爲:", type(diamond.GREEN), diamond.GREEN) print("枚舉的名稱爲", type(diamond.GREEN.name), diamond.GREEN.name) print("枚舉的值爲:", diamond.GREEN.value) 枚舉類型爲: <enum 'diamond'> diamond.GREEN 枚舉的名稱爲 <class 'str'> GREEN 枚舉的值爲: 3
for i in diamond: print(i) diamond.YELLOW diamond.BLUE diamond.GREEN diamond.RED
class diamond(Enum): YELLOW = 1 BLUE = 2 GREEN = 3 RED = 4 a = 1 print(diamond(a)) diamond.YELLOW # 從一個具體的值得到相應的枚舉類型。頗有用。
from enum import IntEnum
,在枚舉類的括號裏爲IntEnum
。from enum import Enum from enum import IntEnum, unique @unique # 裝飾器 class diamond(IntEnum): YELLOW = 1 BLUE = 2 GREEN = 3 RED = 4