對象:是指現實中的物體實體化,對象有很過屬性(名字、年齡..),也有不少行爲(學習、吃飯..),實例即對象。對象同時也是經過類定義的數據結構實例,對象包括兩個數據成員(類變量和實例變量)和方法。對象能夠包含任意數量和類型的數據。html
實例化:建立一個類的實例,類的具體對象化,實例就是類的實例化,d1 = gog(),d1即爲實例python
類:擁有相同屬性和方法(行爲)的對象劃爲一組,稱爲類,類是建立對象的工具
編程
方法:類中定義的函數數據結構
類變量:在類中被定義的變量,一般以self.variable的形式被定義,類變量一般不做爲實例變量使用ide
方法重寫:若是從父類繼承的方法不能知足子類的需求,能夠對其進行修改,這個過程叫方法的覆蓋,也叫方法的重寫函數
繼承:及一個派生類(derived class)繼承基類(base class)的字段和方法。繼承也容許把一個派生類的對象做爲一個基類對象對待。工具
Python中的類提供了面向對象編程的全部基本功能:類的繼承機制容許多個基類,派生類能夠覆蓋基類中的任何方法,方法中能夠調用基類中的同名方法。學習
類定義 語法格式url
class 類名(繼承列表):spa
"""類的文檔字符串"""
類變量的定義
實例方法的定義
類方法的定義(@classmethod)
靜態方法的定義(@staticmethod)
做用:
建立一個類,類用於描述對象的行爲和屬性,類用於建立此類的一個或者多個對象(實例)類名實質上是變量,它綁定一個類
類內第一個沒有賦值給任何變量的字符串爲類的文檔字符串,類的文檔字符串能夠用類的 __doc__屬性訪問
help(Dog) 查看文檔字符串
類.__doc__屬性用來綁定文檔字符串
類變量就類的屬性,此屬性屬於類,不屬於此類的實例
做用:一般用來存儲該類建立的對象的共有屬性
說明:類變量能夠經過該類或該類的實例直接訪問;類變量能夠經過此類的實例對象的__class__屬性間接訪問
class Human: total_count = 0 # 類變量 def __init__(self, name): print(name, '對象被建立') print(Human.total_count) # 類直接訪問類變量 0 h1 = Human('小張') print(h1.total_count) # 0 用此類的實例能夠訪問類變量 h1.total_count = 100 # 爲對象添加實例變量 print(h1.total_count) # 100, 優先訪問對象的實例變量 print(Human.total_count) # 0, 訪問類的類變量 print(h1.__class__.total_count) # 0 經過此類的實例對象的__class__屬性來訪問類變量
一、初始化方法__init__()會在構造函數建立實例後自動調用
二、初始化方法若是須要return語句返回,則只能返回None
三、通常類都會傾向於將(實例)對象建立爲有初始化狀態的
四、實例方法至少有一個形參,第一個形參表明調用這個方法的實例,通常命名爲'self',所以類可能會定義一個名爲__init__()的特殊方法(構造方法)
五、__init__有形參時,參數會經過__init__()傳遞到實例化對象上。
class complex: # 構造函數,在實例化時作一些類的初始化工做,__init__用來傳參的 def __init__(self, name, age): # 定義類的方法 self.name = name # 實例變量(靜態屬性) self.age = age x = complex("做者",23) # 類的實例化,變成具體對象 print(x.name,x.age) # 做者 23
類的方法與普通的函數只有一個特殊的區別————他們必須有一個額外的第一參數名稱self,按照慣例它的名稱是self,誰調用這個類的方法,self就指向誰。self表明類的實例化,而非類
class Test: #定義一個名爲Test的類 def prt(self): #定義類的方法prt print(self) print(self.__class__) # self.__class__指向類 t = Test() #類的實例化 t.prt() #訪問類的方法 # <__main__.Test object at 0x000001836DFE10B8> # <class '__main__.Test'>
self表明的是類的實例,表明當前對象的地址,而self.__class__則指向類名。
self不是python的關鍵詞,咱們把self換成其餘的表示符也是能夠的(在這裏咱們把self換成runoob)
class Test: # 定義一個名爲Test的類 def prt(runoob): # 定義類的方法prt print(runoob) print(runoob.__class__) t = Test() # 類的實例化 t.prt() # 訪問類的方法 # <__main__.Test object at 0x000001836DFE10B8> # <class '__main__.Test'>
做用:限定一個類建立的實例只能有固定屬性(實例屬性),不容許對象添加列表之外的屬性(實例變量)
說明:__slots__列表綁定一個字符串列表,含有__slots__列表的類所建立的實例對象沒有__dict__屬性,即此實例不用字典來存儲對象的屬性(實例變量)
__slots__ = [" ", " "]
class Human: # 如下列表限制此類的對象只能有'name' 和'age' 屬性 __slots__ = ['name', 'age'] def __init__(self, name, age): self.name, self.age = name, age h1 = Human("Tarena", 15) print(h1.age) # 15 # h1.Age = 18 # 出錯,h1對象沒有Age屬性,也不容許有Age屬性 print(h1.age) # 15
類方法是用於描述類的行爲的方法,類方法屬於類,不屬於類的實例
說明:類方法須要使用@classmethod裝飾器定義,
def關鍵詞來定義一個方法,類方法至少有一個形參,第一個參數用於綁定類,約定寫爲" cls ",類和該類的實例均可以調用類的方法
class people: # 定義一個類 # 定義類的屬性 name = '' age = 0 # 定義私有屬性,私有屬性在類外部沒法直接進行訪問 _weight = 0 # 定義構造的方法 def __init__(self, n, a, w): # 定義類的初始化屬性 self.name = n self.age = a self._weight = w # 定義類的方法 @classmethod def speak(cls): print("%s說:我%d歲" % (self.name, self.age)) # 實例化類 把一個類變成具體對象叫作類的實例化 p = people("做者", 18, 30) p.speak() # 做者說:我18歲
靜態方法是定義在類內部的函數,此函數的做用域是類的內部
說明:靜態方法須要使用 @staticmethod裝飾器定義,
靜態方法與普通函數定義相同,不須要傳入self實例參數和cls參數,靜態方法只能憑藉該類或類建立的實例調用,靜態方法不能訪問類變量和實例變量(屬性)
class A: @staticmethod def myadd(a, b): return a + b print(A.myadd(100, 200)) # 300 a = A() # 建立實例 print(a.myadd(300, 400)) # 700
實例方法、類方法、靜態方法、函數小結
不想訪問類內和實例內的變量,用靜態方法
只想訪問類內變量,不想訪問實例變量,用類方法
即要訪問內變量,也想訪問實例變量用實例方法
函數與靜態方法相同,只是靜態方式的做用域定義在類內
class Classname: @staticmethod def fun(): print('靜態方法') @classmethod def a(cls): print('類方法') # 普通方法 def b(self): print('普通方法') Classname.fun() # 靜態方法 Classname.a() # 類方法 C = Classname() C.fun() # 類方法 C.a() # 類方法 C.b() # 普通方法
類實例化後,可使用其屬性,實際上,建立一個類以後,能夠經過類名訪問其屬性
d1 = dog() # 調用構造函數建立實例化對象
類對象
類對象支持兩種操做:屬性引用和實例化。
類對象建立後,類命名空間中的全部命名都是有效屬性名,類定義以下所示:
class Myclass: # 定義一個本身的類 """一個簡單的類實例""" i = 12345 # 類變量 def f(self): # 定義類的方法 return "你好呀" # 類的實例化,用x來綁定以便後面使用,否則用完以後就釋放了 x = Myclass() # 把一個類變成具體對象的過程叫作實例化(初始化) # 訪問類的屬性和方法 print("Myclass類的屬性i:", x.i) # 12345 print("Myclass類的方法f:", x.f()) # 你好呀!
python支持 在類的外面 建立類的屬性
class Dog: def eat(self, food): # print("小狗正在吃:", food) print(self.color, '的', self.kinds, '正在吃', food) dog1 = Dog() # 類的實例化 dog1.kinds = '京巴' # 爲dog1對象添加kinds屬性,綁定爲'京巴' dog1.color = '白色' # dog1添加屬性 爲'白色' dog1.color = '黃色' # 改變dog1的color屬性 # 訪問dog1 的屬性 print(dog1.color, "的", dog1.kinds) # 黃色 的 京巴 dog2 = Dog() dog2.kinds = '哈士奇' dog2.color = '黑白相間' print(dog2.color, '的', dog2.kinds) # 黑白相間 的 哈士奇 dog1.eat('骨頭') # 黃色 的 京巴 正在吃 骨頭 dog2.eat('窩頭') # 黑白相間 的 哈士奇 正在吃 窩頭
# 定義私有屬性,私有屬性在類外部沒法直接進行訪問 __weight = 0,在變量前面加雙下劃線
刪除屬性del語句
del 變量名 刪除變量
del 列表[整數表達式] 刪除列表中的元素
del 字典[鍵] 刪除字典中的鍵
del 對象.屬性 刪除對象的屬性
析構方法:
class 類名:
def __del__(self):
......
說明:析構方法在對象被銷燬時作任何事情,由於銷燬的時間難以肯定
預置實例屬性:
__dict__屬性
__dict__屬性綁定一個存儲此實例自身變量的字典
class Dog: pass dog1 = Dog() print(dog1.__dict__) # {} dog1.kinds = '京巴' print(dog1.__dict__) # {'kinds': '京巴'}
__class__屬性:
此屬性用於綁定建立此實例的類
做用:能夠藉助於此屬性來訪問建立此實例的類
class Dog: pass dog1 = Dog() print(dog1.__class__) # <class '__main__.Dog'> dog2 = dog1.__class__() print(dog2.__class__) # <class '__main__.Dog'>
用於類的函數:
isinstance(obj, class_or_tuple) 返回這個對象obj是不是某個類的對象或某些類中的一個類的對象,若是是則返回True,不然返回False,type(obj) 返回對象的類型
繼承是指從已有的類中派生出新的類,新類具備原類的行爲,並能擴展新的行爲
派生類就是從一個已有類中衍生成新類,在新類上能夠添加新的屬性和行爲
做用:1.用繼承派生機制,能夠將一些共有功能加在基類中,實現代碼的共享
二、在不改變基類的代碼的基礎上改變原有的功能
名詞:基類(base class)/超類(super class)/父類(father class)
派生類(derived class) / 子類(child class)
單繼承:
語法:
class 類名(基累名):
語句塊
說明:單繼承是指由一個基類衍生出的新的類
class Derived_Class_Name(Base_Class_Name1): <statement-1> . . <statement-N>
單繼承實例
class Human: # 人類的共性 def say(self, what): print("say:", what) def walk(self, distance): # 走路 print("走了", distance, '千米') class Student(Human): def study(self, subject): print("正在學習:", subject) class Teacher(Student): '''說話,行走,教學''' def teach(self, subject): print("正在教:", subject) h1 = Human() h1.say('天氣晴了') h1.walk(5) print('---------------') s1 = Student() s1.walk(4) s1.say('感受有點累') s1.study('Python') print('===============') t1 = Teacher() t1.walk(6) t1.say('吃點啥好呢') t1.teach('面向對象') t1.study('轉魔方')
繼承說明:python3 任何類都直接或間接的繼承自object類,object 類是一切類的超類
類的__base__屬性:__base__屬性用來記錄此類的基類
覆蓋是指在有繼承關係的類中,子類中實現了與基類同名的方法,在子類的實例調用該方法時,實際調用的是子類中的覆蓋版本
class A: def works(self): print("A.works被調用") class B(A): """B類繼承A類""" def works(self): print("B.works被調用") a = A() a.works() # A.works被調用 b = B() b.works() # B方法被調用
用類名顯式調用
子類對象顯式調用基類(被覆蓋)方法的方式:基類名.方法名(實例, 實際調用傳參)
class A: def works(self): print("A.works被調用") class B(A): ''' B類繼承自A類''' def works(self): print("B.works被調用") b = B() b.works() # B.works被調用 A.works(b) # 用類名顯式調用, A.works被調用
super(cls, obj)返回綁定超類的實例(要求obj必須是cls類型的實例),通常obj就是self。cls通常就是當前類的類名。
super() 返回父類的實例,
常見用法:super(__class__, 實例方法的第一個參數),必須在方法內調用,通常super(class_name, self).父類方法 # 中間參數能夠省略,以下例
做用:藉助super() 返回的實例間接調用其父類的覆蓋方法
super().父類方法()
class A: def works(self): print("A.works被調用") class B(A): """B類繼承自A類""" def works(self): print("B.works被調用") def super_work(self): self.works() # B.works被調用 super(B, self).works() # A.works被調用 super().works() # A.works被調用 b = B() b.works() # B.works被調用 super(B, b).works() # A.works被調用 b.super_work() # ... # B.works被調用 # A.works被調用 # A.works被調用 super().works() # 出錯,只能在方法內調用
顯式調用基類的初始化方法
當子類中實現了 __init__方法,基類的構造方法並不會被調用,def __init__(self, ...)
super().__init__(n,a) # 參數不填的話,默認調用父類的全部初始化參數
class Human: def __init__(self, n, a): self.name, self.age = n, a print("Human的__init__方法被調用") def infos(self): print("姓名:", self.name) print("年齡:", self.age) class Student(Human): def __init__(self, n, a, s=0): super().__init__(n, a) # 顯式調用父類的初始化方法 self.score = s # 添加成績屬性 print("Student類的__init__方法被調用") def infos(self): super().infos() # 調用父類的方法 print("成績:", self.score) s1 = Student('小張', 20, 100) s1.infos()
class DerivedClassName(Base1, Base2, Base3): <statement-1> . . <statement-N>
須要注意圓括號中父類的順序,如果父類中有相同的方法名,而在子類使用時未指定,python從左至右搜索 即方法在子類中未找到時,從左到右查找父類中是否包含方法。
class people: name = '' age = 0 __weight = 0 def __init__(self, n, a, w): self.name = n self.age = a self.__weight = w def speak(self): print("%s 說: 我 %d 歲。" % (self.name, self.age)) class speaker(): topic = '' name = '' def __init__(self, n, t): self.name = n self.topic = t def speak(self): print("我叫 %s,我是一個演說家,我演講的主題是 %s" % (self.name, self.topic)) # 多繼承 class sample(speaker, people): a = '' def __init__(self, n, a, w, t): # 調用父類的構函數 people.__init__(self, n, a, w) speaker.__init__(self, n, t) test = sample('凌逆戰', "大學生", 23, 'python') test.speak() # 方法名重複了,默認調用的是括號中排前地父類的方法 # 我叫 凌賢鵬,我是一個演說家,我演講的主題是 python
若是父類方法的功能不能知足需求,能夠在子類重寫父類的方法
class parent: # 定義父類 def my_method(self): print("調用父類的方法") class child(parent): # 定義子類 def my_method(self): print("調用子類方法") c = child() # 子類實例 # 子類調用重寫方法 c.my_method() # 調用子類方法 # 用子類對象調用父類已被覆蓋的方法 super(child, c).my_method() # 調用父類的方法
super()函數是用於調用父類(超類)的方法
__private_attrs:兩個寫劃線開頭,聲明該屬性爲私有類,不能在類地外部被使用或直接訪問,在類內部的方法使用時self.private_attrs。
在類地內部,使用def關鍵字來定義一個方法,與通常函數定義不一樣,類方法必須包含self,且爲第一個參數,self表明的是類的實例。
self的名字並非規定死的,也能夠是其餘的,但最好按照規定用self
__private_method:兩個下劃線開頭,聲明該方法爲私有方法,只能在類的內部調用 ,不能在類地外部調用。self.__private_methods。
類的私有屬性
class JustCounter: __secretCount = 0 # 私有變量 publicCount = 0 # 公開變量 def count(self): self.__secretCount += 1 self.publicCount += 1 print(self.__secretCount) counter = JustCounter() counter.count() # 1 counter.count() # 2 print(counter.publicCount) # 2 print(counter.__secretCount) # 報錯,實例不能訪問私有變量 # Traceback (most recent call last): # File "test.py", line 16, in <module> # print (counter.__secretCount) # 報錯,實例不能訪問私有變量 # AttributeError: 'JustCounter' object has no attribute '__secretCount'
類的私有方法
class Site: def __init__(self, name, url): self.name = name # public self.__url = url # private def who(self): print('name: ', self.name) print('url : ', self.__url) def __foo(self): # 私有方法 print('這是私有方法') def foo(self): # 公共方法 print('這是公共方法') self.__foo() x = Site('菜鳥教程', 'www.runoob.com') x.who() # 正常輸出 x.foo() # 正常輸出 x.__foo() # 報錯
class Vector: def __init__(self, a, b): self.a = a self.b = b def __str__(self): return 'Vector (%d, %d)' % (self.a, self.b) def __add__(self, other): return Vector(self.a + other.a, self.b + other.b) v1 = Vector(2, 10) v2 = Vector(5, -2) print(v1 + v2) # Vector(7,8)