面向對象是一種編程方式,此編程方式的實現是基于對類和對象的使用。
類是一個模板,模板中包裝了多個“函數”供使用(可以講多函數中公用的變量封裝到對象中)。
對象,根據模板創建的實例(即對象),實例用于調用被包裝在類中的函數。類是對象的定義 ,而實例是“ 真正的實物”,它存放了類中所定義的對象的具體信息。
面向對象三大特性:封裝、繼承和多態。
1、類的定義:
1、使用 class 語句來創建一個新類,class 之后為類的名稱并以冒號結尾:
class ClassName:'類的幫助信息' #類文檔字符串class_suite #類體#類的幫助信息可以通過ClassName.__doc__查看。 #class_suite 由類成員,方法,數據屬性組成。


#!/usr/bin/python # -*- coding: UTF-8 -*- class Employee:'所有員工的基類'empCount = 0def __init__(self, name, salary):self.name = nameself.salary = salaryEmployee.empCount += 1def displayCount(self):print "Total Employee %d" % Employee.empCountdef displayEmployee(self):print "Name : ", self.name, ", Salary: ", self.salary#empCount 變量是一個類變量,它的值將在這個類的所有實例之間共享。你可以在內部類或外部類使用 Employee.empCount 訪問。 #第一種方法__init__()方法是一種特殊的方法,被稱為類的構造函數或初始化方法,當創建了這個類的實例時就會調用該方法 #self 代表類的實例,self 在定義類的方法時是必須有的,雖然在調用時不必傳入相應的參數。
2、self代表類的實例,而非類。類的方法與普通的函數只有一個特別的區別——它們必須有一個額外的第一個參數名稱, 按照慣例它的名稱是 self。


class Test:def prt(self):print(self)print(self.__class__)t = Test() t.prt()''' 以上實例執行結果為: <__main__.Test instance at 0x10d066878> __main__.Test從執行結果可以很明顯的看出,self 代表的是類的實例,代表當前對象的地址,而 self.__class__ 則指向類。 '''#self 不是 python 關鍵字,我們把他換成 runoob 也是可以正常執行的: class Test:def prt(runoob):print(runoob)print(runoob.__class__) t = Test() t.prt()''' 以上實例執行結果為: <__main__.Test instance at 0x10d066878> __main__.Test '''


''' 創建實例對象 實例化類其他編程語言中一般用關鍵字 new,但是在 Python 中并沒有這個關鍵字,類的實例化類似函數調用方式。 以下使用類的名稱 Employee 來實例化,并通過 __init__ 方法接收參數。'''#"創建 Employee 類的第一個對象" emp1 = Employee("Zara", 2000) #"創建 Employee 類的第二個對象" emp2 = Employee("Manni", 5000)''' 訪問屬性 您可以使用點號 . 來訪問對象的屬性。使用如下類的名稱訪問類變量:'''emp1.displayEmployee() emp2.displayEmployee() print "Total Employee %d" % Employee.empCount''' 可以使用以下函數的方式來訪問屬性: getattr(obj, name[, default]) : 訪問對象的屬性。 hasattr(obj,name) : 檢查是否存在一個屬性。 setattr(obj,name,value) : 設置一個屬性。如果屬性不存在,會創建一個新屬性。 delattr(obj, name) : 刪除屬性。'''
2、類的成員
1、字段包括:普通字段和靜態字段,他們在定義和使用中有所區別,而最本質的區別是內存中保存的位置不同。普通字段屬于對象,靜態字段屬于類。


#coding=utf-8 class Province:# 靜態字段country = '中國'def __init__(self, name):# 普通字段self.name = name # 直接訪問普通字段 obj = Province('河北省') print(obj.name) # 直接訪問靜態字段 print(Province.country)''' 由上述代碼可以看出【普通字段需要通過對象來訪問】【靜態字段通過類訪問】,在使用上可以看出普通字段和靜態字段的歸屬是不同的。其靜態字段在內存中只保存一份,普通字段在每個對象中都要保存一份。 應用場景: 通過類創建對象時,如果每個對象都具有相同的字段,那么就使用靜態字段。 '''
2、類的方法包括實例方法、類方法、靜態方法。


class Foo(object): def test(self)://定義了實例方法 print("object") @classmethod def test2(clss)://定義了類方法 print("class") @staticmethod def test3()://定義了靜態方法 print("static")


#coding=utf-8 class Apple:def fun1(self):return 'normal'@staticmethoddef fun2():return 'staticmethod'@classmethoddef fun3(cls):return 'classmethod' print Apple.fun1 print Apple.fun2 print Apple.fun3 print "-"*80apple = Apple() print apple.fun1 print apple.fun2 print apple.fun3 print "-"*80apple1 = Apple() print apple1.fun1 print apple1.fun2 print apple1.fun3''' 輸出結果: 1、<unbound method Apple.fun1> 2、<function fun2 at 0x00000000022FC4A8> 3、<bound method classobj.fun3 of <class __main__.Apple at 0x0000000001E7C768>> 4、---------------------------------------------------------------------------- 5、<bound method Apple.fun1 of <__main__.Apple instance at 0x00000000022FAE08>> 6、<function fun2 at 0x00000000022FC4A8> 7、<bound method classobj.fun3 of <class __main__.Apple at 0x0000000001E7C768>> 8、---------------------------------------------------------------------------- 9、 <bound method Apple.fun1 of <__main__.Apple instance at 0x00000000022FAE48>> 10、<function fun2 at 0x00000000022FC4A8> 11、<bound method classobj.fun3 of <class __main__.Apple at 0x0000000001E7C768>> --------------------- ------------------------------------------------------ '''''' 解析: 1、普通方法傳入的第一個參數必須是self(當然也可以不用self,官方要求盡量用self),self是指實例對象本身; 2、靜態方法無需傳參; 3、類方法傳入的第一個參數必須是class,是指類本身。 對比結果1,5,9行: fun1通過class調用時,它是未綁定的方法,而實例化apple和apple1之后,它屬于綁定的方法,且實例化后的apple和apple1內存地址不同,因為它們屬于不同的實例對象。 對比結果2,6,10行: 靜態方法fun2通過class調用或者通過實例化后的對象調用,是沒有任何區別的,全部都是指向同一塊內存地址。可以簡單的理解成靜態方法與類或者實例沒有任何關系,一旦調用后,它的內存地址即確定。 對比結果3,7,11行: 類方法fun3通過class調用或者通過實例化后的對象調用,是沒有任何區別的,全部都是指向同一塊內存地址。為什么?因為實例化對象apple和apple1調用類方法fun3傳入的第一個參數是類本身Apple,也就是說apple.fun3 = apple1.fun3 = Apple.fun3。區別總結: 1、靜態方法裝飾器下定義的方法屬于函數(function); 2、類方法裝飾器下定義的方法屬于方法(method); 3、靜態方法無需傳入任何參數; 4、類方法傳入的第一個參數必須是class本身cls; 5、靜態方法與類方法一旦被調用,內存地址即確定。通過類調用和通過實例化對象調用的結果完全一樣。 6、三種方法從不同層次上來對方法進行了描述:實例方法針對的是實例,類方法針對的是類,他們都可以繼承和重新定義,而靜態方法則不能繼承,可以認為是全局函數 '''
3、如果你已經了解Python類中的方法,那么屬性就非常簡單了,因為Python中的屬性其實是普通方法的變種。


#coding=utf-8 # ############### 定義 ############### class Foo:def func(self):pass# 定義屬性 @propertydef prop(self):pass # ############### 調用 ############### foo_obj = Foo() foo_obj.func() foo_obj.prop #調用屬性''' 由屬性的定義和調用要注意一下幾點: 定義時,在普通方法的基礎上添加 @property 裝飾器; 定義時,屬性僅有一個self參數 調用時,無需括號方法:foo_obj.func()屬性:foo_obj.prop 注意:屬性存在意義是:訪問屬性時可以制造出和訪問字段完全相同的假象屬性由方法變種而來,如果Python中沒有屬性,方法完全可以代替其功能 '''
屬性的兩種定義方式
屬性的定義有兩種方式:
裝飾器 即:在方法上應用裝飾器
靜態字段 即:在類中定義值為property對象的靜態字段


''' 裝飾器方式 裝飾器方式:在類的普通方法上應用@property裝飾器 我們知道Python中的類有經典類和新式類,新式類的屬性比經典類的屬性豐富。( 如果類繼object,那么該類是新式類 ) 經典類,具有一種@property裝飾器(如上一步實例) '''# ############### 定義 ############### class Goods:@propertydef price(self):return "wupeiqi" # ############### 調用 ############### obj = Goods() result = obj.price # 自動執行 @property 修飾的 price 方法,并獲取方法的返回值#新式類,具有三種@property裝飾器 # ############### 定義 ############### class Goods(object):@propertydef price(self):print '@property'@price.setterdef price(self, value):print '@price.setter'@price.deleterdef price(self):print '@price.deleter' # ############### 調用 ############### obj = Goods() obj.price # 自動執行 @property 修飾的 price 方法,并獲取方法的返回值 obj.price= 123 # 自動執行 @price.setter修飾的price方法,并將123賦值給方法的參數 del obj.price # 自動執行 @price.deleter 修飾的 price 方法''' 注:經典類中的屬性只有一種訪問方式,其對應被 @property 修飾的方法新式類中的屬性有三種訪問方式,并分別對應了三個被@property、@方法名.setter、@方法名.deleter修飾的方法 由于新式類中具有三種訪問方式,我們可以根據他們幾個屬性的訪問特點,分別將三個方法定義為對同一個屬性:獲取、修改、刪除 '''


#靜態字段方式,創建值為property對象的靜態字段 #當使用靜態字段的方式創建屬性時,經典類和新式類無區別class Foo:def get_bar(self):return 'good'BAR = property(get_bar) obj = Foo() reuslt = obj.BAR # 自動調用get_bar方法,并獲取方法的返回值 print result''' property的構造方法中有個四個參數 第一個參數是方法名,調用 對象.屬性 時自動觸發執行方法 第二個參數是方法名,調用 對象.屬性 = XXX 時自動觸發執行方法 第三個參數是方法名,調用 del 對象.屬性 時自動觸發執行方法 第四個參數是字符串,調用 對象.屬性.__doc__ ,此參數是該屬性的描述信息 '''
?3、新式類和舊式類


# -*- coding: utf-8 -*- # 經典類或者舊試類 class A:pass a = A()# 新式類 class B(object):pass b = B()# python2不支持 # print(A.__class__) print(a.__class__) print(type(A)) print(type(a))# python2 # __main__.A # <type 'classobj'> # <type 'instance'># python3 # <class 'type'> # <class '__main__.A'> # <class 'type'> # <class '__main__.A'>print(B.__class__) print(b.__class__) print(type(B)) print(type(b))# python2 # <type 'type'> # <class '__main__.B'> # <type 'type'> # <class '__main__.B'># python3 # <class 'type'> # <class '__main__.B'> # <class 'type'> # <class '__main__.B'># 舊式類的實現不夠好,類是類,實例是實例,類的類型是classobj,實例的類型是instance,兩者的聯系只在于__class__, # 這和內置對象是不同的,int對象的類型就是int,同時int()返回的也是int類型的對象,內置對象和自定義對象不同就對代碼統一實現帶來很大困難。 # # 新式類 # # 1. 所有類的類型都是type # 2. 所有類調用的結果都是構造,返回這個類的實例 # 3. 所有類都是object的子類 # 4. 新式類不僅可以用舊類調用父類的方法,也可以用super方法。
?4、類的私有成員
1):單下劃線_開頭:只是告訴別人這是私有屬性,外部依然可以訪問更改
2):雙下劃線__開頭:外部不可通過實例化對象.屬性名來訪問或者更改
實際將其轉化為了_類名_屬性名,只是在內部將變量名修改了,我們仍讓可以通過._類名_屬性名訪問


>>>class Test(): >>> a = 100 >>>Test.__dict__ Out[3]: {'__doc__': None, '__module__': '__main__', 'a': 100}>>>class Test(): >>> __a = 100 >>>Test.__dict__ Out[5]: {'_Test__a': 100, '__doc__': None, '__module__': '__main__'} >>>Test._Test__a Out[6]: 100
私有成員和公有成員的訪問限制不同:
1) 靜態字段
公有靜態字段:類可以訪問;類內部可以訪問;派生類中可以訪問
私有靜態字段:僅類內部可以訪問;
2) 普通字段
公有普通字段:對象可以訪問;類內部可以訪問;派生類中可以訪問
私有普通字段:僅類內部可以訪問;
注意:如果想要強制訪問私有字段,可以通過【對象._類名__私有字段明】訪問(如:obj._C__foo),不建議強制訪問私有成員。方法、屬性的訪問于上述方式相似,即:私有成員只能在類內部使用
5、類成員的修改
1、修改類的對象(實例)屬性


#coding=utf-8 class Test(object):a = 100def __init__(self):pass t1 = Test() t2 = Test() #1.通過實例對象t1修改類屬性的值 print("修改前:t1.a = %d, t2.a = %d, Test.a = %d"%(t1.a, t2.a, Test.a)) t1.a += 100 print("修改后:t1.a = %d, t2.a = %d, Test.a = %d"%(t1.a, t2.a, Test.a))''' 輸出: 修改前:t1.a = 100, t2.a = 100, Test.a = 100 修改后:t1.a = 200, t2.a = 100, Test.a = 100 '''
很明顯,我們通過實例對象修改類屬性的值,并沒有在全局范圍奏效,它只是對t1對象的實例屬性修改了,實際上并沒有對本身定義的類屬性和其它的對象的屬性造成變動。
2、修改類的屬性:


class Test(object):a = 100def __init__(self):pass t1 = Test() t2 = Test() #1.通過類名修改類屬性的值 print("修改前:t1.a = %d, t2.a = %d, Test.a = %d"%(t1.a, t2.a, Test.a)) Test.a += 100 print("修改后:t1.a = %d, t2.a = %d, Test.a = %d"%(t1.a, t2.a, Test.a))''' 輸出: 修改前:t1.a = 100, t2.a = 100, Test.a = 100 修改后:t1.a = 200, t2.a = 200, Test.a = 200 '''
通過類名修改的類屬性,在全局范圍奏效,也就是說確實修改了類屬性的值,在實例對象中我們看到屬性值全部被修改。
6、類的內置特殊成員


#coding=utf-8 class Province:"""Genius is thing but labor and diligence!"""country = 'China'def __init__(self, name, count):self.name = nameself.count = countdef func(self, *args, **kwargs):city="New"print 'func' obj = Province('HeBei',10000) # 自動執行類中的 __init__ 方法 print obj ''' #__init__構造方法,通過類創建對象時,自動觸發執行。輸出: <__main__.Province instance at 0x0000000003989108> '''


#coding=utf-8 class Province:"""Genius is thing but labor and diligence!"""country = 'China'def __init__(self, name, count):self.name = nameself.count = countdef func(self, *args, **kwargs):city="New"print 'func'def __del__(self): #當對象在內存中被釋放時,自動觸發執行。pass obj = Province('HeBei',10000) print obj ''' #__del__析構方法一般無須定義,因為Python是一門高級語言,程序員在使用時無需關心內存的分配和釋放,因為此工作都是交給Python解釋器來執行,所以,析構函數的調用是由解釋器在進行垃圾回收時自動觸發執行的。輸出: <__main__.Province instance at 0x0000000003989108> '''


#coding=utf-8 class Province:"""Genius is thing but labor and diligence!"""country = 'China'def __init__(self, name, count):self.name = nameself.count = countdef func(self, *args, **kwargs):city="New"print 'func'def __del__(self):passdef __call__(self):print "__call__" obj = Province('HeBei',10000) print obj() #對象后面加括號,觸發執行。 ''' #__call__構造方法的執行是由創建對象觸發的,即:對象 = 類名() ;而對于 __call__ 方法的執行是由對象后加括號觸發的,即:對象() 或者 類()()輸出: __call__ None '''


#coding=utf-8 class Province:"""Genius is thing but labor and diligence!"""country = 'China'def __init__(self, name, count):self.name = nameself.count = countdef func(self, *args, **kwargs):city="New"print 'func'def __del__(self):passdef __call__(self):print "__call__"def __str__(self):return("__str__") obj = Province('HeBei',10000) print obj ''' #__str__如果一個類中定義了__str__方法,那么在打印對象時,默認輸出該方法的返回值。輸出: __str__ '''


#用于迭代器,之所以列表、字典、元組可以進行for循環,是因為類型內部定義了 __iter__。 #a)第一步 class Foo(object):pass obj = Foo() for i in obj:print i # 報錯:TypeError: 'Foo' object is not iterable#b) 第二步 #!/usr/bin/env python # -*- coding:utf-8 -*- class Foo(object): def __iter__(self):pass obj = Foo() for i in obj:print i # 報錯:TypeError: iter() returned non-iterator of type 'NoneType'#c) 第三步 #!/usr/bin/env python # -*- coding:utf-8 -*- class Foo(object):def __init__(self, sq):self.sq = sqdef __iter__(self):return iter(self.sq) obj = Foo([11,22,33,44]) for i in obj: print i#d)For循環語法內部 #!/usr/bin/env python # -*- coding:utf-8 -*- obj = iter([11,22,33,44]) while True:val = obj.next()print val


#coding=utf-8 class Foo(object):def __getitem__(self, key):print('__getitem__', key)def __setitem__(self, key, value):# print('__setitem__', key, value)self.key = keyself.value = valueprint(key,value)return self.keydef __delitem__(self, key):print('__delitem__', key)obj =Foo() result = obj['k1'] # 自動觸發執行 __getitem__ obj['k3']='xxxxxx' # 自動觸發執行 __setitem__ del obj['k1'] # 自動觸發執行 __delitem__


#該三個方法用于分片操作,如:列表。 #!/usr/bin/env python # -*- coding:utf-8 -*- class Foo(object):def __getslice__(self, i, j):print '__getslice__',i,jdef __setslice__(self, i, j, sequence):print '__setslice__',i,jdef __delslice__(self, i, j):print '__delslice__',i,j obj = Foo() obj[-1:1] # 自動觸發執行 __getslice__ obj[0:1] = [11,22,33,44] # 自動觸發執行 __setslice__ del obj[0:2] # 自動觸發執行 __delslice__


''' __new__()在Python :類里面的構造方法init()負責將類的實例化,而在init()調用之前,new()決定是否要使用該init()方法, 因為new()可以調用其他類的構造方法或者直接返回別的對象來作為本類 的實例。 如果將類比喻為工廠,那么init()方法則是該工廠的生產工人,init()方法接受的初始化參 數則是生產所需原料,init()方法會按照方法中的語句負責將原料加工成實例以供工廠出貨。而 new()則是生產部經理,new()方法可以決定是否將原料提供給該生產部工人,同時它還決定著出 貨產品是否為該生產部的產品,因為這名經理可以借該工廠的名義向客戶出售完全不是該工廠的產品。 new()方法的特性: new()方法是在類準備將自身實例化時調用。 new()方法始終都是類的靜態方法,即使沒有被加上靜態方法裝飾器。 '''''' 通常來說,新式類開始實例化時,new()方法會返回cls(cls指代當前類)的實例,然后該類的 init()方法作為構造方法會接收這個實例(即self)作為自己的第一個參數,然后依次傳入new ()方法中接收的位置參數和命名參數。 注意:如果new()沒有返回cls(即當前類)的實例,那么當前類的init()方法是不會被調用 的。 如果new()返回其他類(新式類或經典類均可)的實例,那么只會調用被返回的那個類的構造方 法。 ''' class Foo(object):def __init__(self, *args, **kwargs):passdef __new__(cls, *args, **kwargs):return object.__new__(Stranger, *args, **kwargs) #重寫Foo類的new方法,返回Stranger類的實例class Stranger(object):passfoo = Foo() print(type(foo)) #結果顯示foo其實是Stranger類的實例 <class '__main__.Stranger'>#鏈接:https://blog.csdn.net/Four_Infinite/article/details/52798919#__init__與__new__的先后執行順序 class Test(object):def __init__(self,name):self.name = nameprint "hey"def __new__(cls, *args, **kwargs):print "hello"return object.__new__(cls, *args, **kwargs) f = Test("study")''' 輸出:hellohey '''


#閱讀以下代碼: class Foo(object):def __init__(self):pass obj = Foo() # obj是通過Foo類實例化的對象''' 上述代碼中,obj 是通過 Foo 類實例化的對象,其實,不僅 obj 是一個對象,Foo類本身也是一個對象,因為在Python中一切事物都是對象。如果按照一切事物都是對象的理論:obj對象是通過執行Foo類的構造方法創建,那么Foo類對象應該也是通過執行某個類的 構造方法 創建。 print type(obj) # 輸出:<class '__main__.Foo'> 表示,obj 對象由Foo類創建 print type(Foo) # 輸出:<type 'type'> 表示,Foo類對象由 type 類創建 所以,obj對象是Foo類的一個實例,Foo類對象是 type 類的一個實例,即:Foo類對象 是通過type類的構造方法創建。 '''#那么,創建類就可以有兩種方式: #a) 普通方式 class Foo(object):def func(self):print 'hello wupeiqi' #b) 特殊方式(type類的構造函數) def func(self):print 'hello wupeiqi' Foo = type('Foo',(object,), {'func': func}) #type第一個參數:類名 #type第二個參數:當前類的基類 #type第三個參數:類的成員''' ==》 類 是由 type 類實例化產生 那么問題來了,類默認是由 type 類實例化產生,type類中如何實現的創建類?類又是如何創建對象?答:類中有一個屬性 __metaclass__,其用來表示該類由 誰 來實例化創建,所以,我們可以為 __metaclass__ 設置一個type類的派生類,從而查看 類 創建的過程。 '''


''' __new__ is the method called before __init__ It's the function that actually creates the object and returns it. __init__ only initialize the object passed as a parameter. We rarely use __new__, except when we want to control how the object is created. For a metaclass, the object created is a class. And since we want to customize it, we need to override __new__. We can also do something by overriding __init__ to get customized initialization process as well. Advanced usage involves override __call__, but we won't talk about this here.''' #鏈接:https://www.jianshu.com/p/224ffcb8e73e #鏈接:https://www.jianshu.com/p/14b8ebf93b73


class Test(type):pass class Name(object):__metaclass__ = Testf = Name() print type(f) print type(Name) print type(Test)''' 輸出:<class '__main__.Name'><class '__main__.Test'><type 'type'> '''class Test(type):def __init__(self,*args,**kwargs):super(Test,self).__init__(*args,**kwargs)def test(self,name):return name class Name(object):__metaclass__ = Testdef __init__(self,what):self.what = whatdef sayhi(self):return self.whatf = Name("cat") print type(f) print type(Name) print type(Test)''' 輸出:<class '__main__.Name'><class '__main__.Test'><type 'type'> '''


class Fo():passclass FFo(object):passprint type(Fo) print type(type(Fo)) print type(FFo)''' 輸出:<type 'classobj'><type 'type'><type 'type'> '''
?
#__doc__表示類的描述信息
#__module__表示當前操作的對象在那個模塊,類定義所在的模塊(類的全名是'__main__.className',如果類位于一個導入模塊mymod中,那么className.__module__ 等于 mymod)
#__class__表示當前操作的對象的類是什么
#__name__表示類名
#__bases__類的所有父類構成元素(包含了一個由所有父類組成的元組)
#__dict__表示類或對象中的所有成員(包含一個字典,由類的數據屬性組成)。


#coding=utf-8 class Province:"""Genius is thing but labor and diligence!"""country = 'China'def __init__(self, name, count):self.name = nameself.count = countdef func(self, *args, **kwargs):city="New"print 'func' print Province.__doc__ print Province.__module__ #print Province.__class__ #AttributeError: class Province has no attribute '__class__' print Province.__name__ print Province.__bases__ print Province.__dict__''' #__doc__表示類的描述信息 #__module__表示當前操作的對象在那個模塊,類定義所在的模塊(類的全名是'__main__.className',如果類位于一個導入模塊mymod中,那么className.__module__ 等于 mymod) #__class__表示當前操作的對象的類是什么 #__name__表示類名 #__bases__類的所有父類構成元素(包含了一個由所有父類組成的元組) #__dict__表示類的屬性(包含一個字典,由類的數據屬性組成)輸出: Genius is thing but labor and diligence! __main__ Province () {'country': 'China', '__module__': '__main__', 'func': <function func at 0x000000000329C358>, '__doc__': 'Genius is thing but labor and diligence!', '__init__': <function __init__ at 0x000000000329C2E8>}'''


#coding=utf-8 class Province:"""Genius is thing but labor and diligence!"""country = 'China'def __init__(self, name, count):self.name = nameself.count = countdef func(self, *args, **kwargs):city="New"print 'func' obj = Province('HeBei',10000) print obj.__doc__ print obj.__module__ print obj.__class__ #print obj.__name__ #AttributeError: Province instance has no attribute '__name__' #print obj.__bases__ #AttributeError: Province instance has no attribute '__bases__' print obj.__dict__''' #__doc__表示類的描述信息 #__module__表示當前操作的對象在那個模塊,類定義所在的模塊(類的全名是'__main__.className',如果類位于一個導入模塊mymod中,那么className.__module__ 等于 mymod) #__class__表示當前操作的對象的類是什么 #__name__表示類名 #__bases__類的所有父類構成元素(包含了一個由所有父類組成的元組) #__dict__表示類的屬性(包含一個字典,由類的數據屬性組成)輸出: Genius is thing but labor and diligence! __main__ __main__.Province {'count': 10000, 'name': 'HeBei'} '''
7、類的繼承
面向對象編程 (OOP) 語言的一個主要功能就是“繼承”。繼承是指這樣一種能力:它可以使用現有類的所有功能,并在無需重新編寫原來的類的情況下對這些功能進行擴展。


''' 通過繼承創建的新類稱為“子類”或“派生類”,被繼承的類稱為“基類”、“父類”或“超類”,繼承的過程,就是從一般到特殊的過程。在某些 OOP 語言中,一個子類可以繼承多個基類。但是一般情況下,一個子類只能有一個基類,要實現多重繼承,可以通過多級繼承來實現。繼承概念的實現方式主要有2類:實現繼承、接口繼承。 實現繼承是指使用基類的屬性和方法而無需額外編碼的能力。 接口繼承是指僅使用屬性和方法的名稱、但是子類必須提供實現的能力(子類重構爹類方法)。 在考慮使用繼承時,有一點需要注意,那就是兩個類之間的關系應該是“屬于”關系。例如,Employee 是一個人,Manager 也是一個人,因此這兩個類都可以繼承 Person 類。但是 Leg 類卻不能繼承 Person 類,因為腿并不是一個人。OO開發范式大致為:劃分對象→抽象類→將類組織成為層次化結構(繼承和合成) →用類與實例進行設計和實現幾個階段。 ''' #coding=utf-8class Person(object): # 定義一個父類def talk(self): # 父類中的方法print("person is talking....") class Chinese(Person): # 定義一個子類, 繼承Person類def walk(self): # 在子類中定義其自身的方法print('is walking...')c = Chinese() c.talk() # 調用繼承的Person類的方法 c.walk() # 調用本身的方法''' # 輸出 person is talking.... is walking... '''


""" 如果我們要給實例 c 傳參,我們就要使用到構造函數,那么構造函數該如何繼承,同時子類中又如何定義自己的屬性? 繼承類的構造方法:1.經典類的寫法: 父類名稱.__init__(self,參數1,參數2,...)2. 新式類的寫法:super(子類,self).__init__(參數1,參數2,....) """#coding=utf-8 class Person(object):def __init__(self, name, age):self.name = nameself.age = ageself.weight = 'weight'def talk(self):print("person is talking....")class Chinese(Person):def __init__(self, name, age, language): # 先繼承,在重構Person.__init__(self, name, age) #繼承父類的構造方法,也可以寫成:super(Chinese,self).__init__(name,age)self.language = language # 定義類的本身屬性def walk(self):print('is walking...')class American(Person):pass c = Chinese('bigberg', 22, 'Chinese')


class Person(object): def __init__(self, name, age):self.name = nameself.age = ageself.weight = 'weight'def talk(self):print("person is talking....")class Chinese(Person):def __init__(self, name, age, language): Person.__init__(self, name, age) self.language = languageprint(self.name, self.age, self.weight, self.language)def talk(self): # 子類 重構方法print('%s is speaking chinese' % self.name)def walk(self):print('is walking...')c = Chinese('bigberg', 22, 'Chinese') c.talk()''' # 輸出 bigberg 22 weight Chinese bigberg is speaking chinese '''
8、類的多態
多態是面向對象的重要特性,簡單點說:“一個接口,多種實現”,指一個基類中派生出了不同的子類,且每個子類在繼承了同樣的方法名的同時又對父類的方法做了不同的實現,這就是同一種事物表現出的多種形態。


""" 編程其實就是一個將具體世界進行抽象化的過程,多態就是抽象化的一種體現,把一系列具體事物的共同點抽象出來, 再通過這個抽象的事物, 與不同的具體事物進行對話,對不同類的對象發出相同的消息將會有不同的行為。 多態允許將子類的對象當作父類的對象使用,某父類型的引用指向其子類型的對象,調用的方法是該子類型的方法。這里引用和調用方法的代碼編譯前就已經決定了,而引用所指向的對象可以在運行期間動態綁定。 """ #一個抽象類具有多個子類,就是多種形態。多態依賴于繼承,沒有繼承就沒有多態。class Animal(object):def __init__(self, name, age):self.name = nameself.age = agepassclass Dog(Animal):def __init__(self, name, age, breed):super(Dog, self).__init__(name, age)self.breed = breedpassclass Cat(Animal):def __init__(self, name, age, breed):super(Cat, self).__init__(name, age)self.breed = breedpass#我們定義了一個 Animal類,又定義了其兩個子類 :Dog 和 Cat。這兩個子類就表示了Animal這個類的多種形態。
多態性是指具有不同功能的函數可以使用相同的函數名,這樣就可以用一個函數名調用不同內容的函數。在面向對象方法中一般是這樣表述多態性:向不同的對象發送同一條消息,不同的對象在接收時會產生不同的行為(即方法)。也就是說,每個對象可以用自己的方式去響應共同的消息。所謂消息,就是調用函數,不同的行為就是指不同的實現,即執行不同的函數。
9、對象銷毀(垃圾回收)
要保持追蹤內存中的對象,Python使用了引用計數這一簡單技術。也就是說Python內部記錄著所有使用中的對象 各有多少引用。一個內部跟蹤變量,稱為引用計數器。每個對象各有多少個引用,簡稱引用計數。當對象被創建時,就創建了一個引用計數,當這個對象不再需要時,也就是說,這個對象的引用計數變為0時,它被垃圾回收。(并不是100%這樣)
鏈接:https://www.cnblogs.com/bigberg/p/7591463.html