類的詳解

面向對象是一種編程方式,此編程方式的實現是基于對類和對象的使用。
類是一個模板,模板中包裝了多個“函數”供使用(可以講多函數中公用的變量封裝到對象中)。
對象,根據模板創建的實例(即對象),實例用于調用被包裝在類中的函數。類是對象的定義 ,而實例是“ 真正的實物”,它存放了類中所定義的對象的具體信息。
面向對象三大特性:封裝、繼承和多態。

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
'''
self
''' 創建實例對象
實例化類其他編程語言中一般用關鍵字 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方法。
View Code

?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
'''
View Code

很明顯,我們通過實例對象修改類屬性的值,并沒有在全局范圍奏效,它只是對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
'''
View Code

通過類名修改的類屬性,在全局范圍奏效,也就是說確實修改了類屬性的值,在實例對象中我們看到屬性值全部被修改。

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>
'''
__init__
#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>
'''
__del__
#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
'''
__call__
#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__
'''
__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
__iter__
#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__
__getitem__、__setitem__、__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__
__getslice__、__setslice__、__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
'''
__new__
#閱讀以下代碼:
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類的派生類,從而查看 類 創建的過程。
'''
__metaclass__
'''
__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
__new__ and __init__
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'>
'''
__metaclass__2
class Fo():passclass FFo(object):passprint type(Fo)
print type(type(Fo))
print type(FFo)'''
輸出:<type 'classobj'><type '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...
'''
View Code
"""
如果我們要給實例 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這個類的多種形態。
View Code

多態性是指具有不同功能的函數可以使用相同的函數名,這樣就可以用一個函數名調用不同內容的函數。在面向對象方法中一般是這樣表述多態性:向不同的對象發送同一條消息,不同的對象在接收時會產生不同的行為(即方法)。也就是說,每個對象可以用自己的方式去響應共同的消息。所謂消息,就是調用函數,不同的行為就是指不同的實現,即執行不同的函數。

9、對象銷毀(垃圾回收)

要保持追蹤內存中的對象,Python使用了引用計數這一簡單技術。也就是說Python內部記錄著所有使用中的對象 各有多少引用。一個內部跟蹤變量,稱為引用計數器。每個對象各有多少個引用,簡稱引用計數。當對象被創建時,就創建了一個引用計數,當這個對象不再需要時,也就是說,這個對象的引用計數變為0時,它被垃圾回收。(并不是100%這樣)

鏈接:https://www.cnblogs.com/bigberg/p/7591463.html

轉載于:https://www.cnblogs.com/windyrainy/p/10654862.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/394412.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/394412.shtml
英文地址,請注明出處:http://en.pswp.cn/news/394412.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

leetcode279. 完全平方數(動態規劃)

給定正整數 n&#xff0c;找到若干個完全平方數&#xff08;比如 1, 4, 9, 16, …&#xff09;使得它們的和等于 n。你需要讓組成和的完全平方數的個數最少。 示例 1: 輸入: n 12 輸出: 3 解釋: 12 4 4 4. 解題思路 數組含義&#xff1a;dp[i]數字i對應組成和的完全平方…

什么情況不能辦理房產抵押貸款 房產抵押貸能貸多少?

所謂房產抵押貸款是指以自己或親友的房產作為抵押物向貸款機構申請貸款&#xff0c;款項可用于企業經營、買房、買車、裝修及其他用途的融資方式。但是有些情況是規定不能申請房產抵押貸款的&#xff0c;而且貸款的數額是有限的&#xff0c;不是想貸多少就多少。那么&#xff0…

Android RecyclerView 二級列表實現

Android RecyclerView 二級列表實現

2數據庫表增加一個字段_14個實用的數據庫設計技巧!

1. 原始單據與實體之間的關系可以是一對一、一對多、多對多的關系。在一般情況下&#xff0c;它們是一對一的關系&#xff1a;即一張原始單據對應且只對應一個實體。在特殊情況下&#xff0c;它們可能是一對多或多對一的關系&#xff0c;即一張原始單證對應多個實體&#xff0c…

錯誤: 找不到或無法加載主類 helloworld_全面剖析虛擬機類加載機制

1.引言java源文件經過編譯后生成字節碼class文件&#xff0c;需要經過虛擬機加載并轉換成匯編指令才能執行&#xff0c;那么虛擬機是如何一步步加載這些class文件的對于java程序員是完全透明的&#xff0c;本文嘗試全面分析jvm類加載機制。2.思考開始之前我們來簡單思考一下&am…

nginx反向代理和shiro權限校驗產生的404問題

問題描述: 我們的項目A&#xff08;以下簡稱A&#xff09;用了shiro做權限校驗&#xff0c;nginx做反向代理&#xff0c;在另一個項目B&#xff08;以下簡稱B&#xff09;中點擊某個A的鏈接時實現單點登錄并會跳轉到該路徑。跳轉到原路徑的時候nginx報了404。出現404之后再次點…

android 揭示動畫_如何使用意圖揭示函數名稱使代碼更好

android 揭示動畫Discover Functional JavaScript was named one of the best new Functional Programming books by BookAuthority!“發現功能JavaScript”被BookAuthority評為最佳新功能編程書籍之一 &#xff01; Code is a way to communicate with developers reading it…

200道物理學難題——038蚱蜢躍樹

轉載于:https://www.cnblogs.com/hanford/p/6168514.html

(轉)dp動態規劃分類詳解

dp動態規劃分類詳解 轉自&#xff1a;http://blog.csdn.NET/cc_again/article/details/25866971 動態規劃一直是ACM競賽中的重點&#xff0c;同時又是難點&#xff0c;因為該算法時間效率高&#xff0c;代碼量少&#xff0c;多元性強&#xff0c;主要考察思維能力、建模抽象能力…

strcmp可以比較數組么_大家都用過百度云,但你面試過百度云么

作者&#xff1a;黃小斜百度研發面經百度智能云軟件研發工程師百度智能云研發崗好像是做控制臺方面的組一面&#xff1a;1自我介紹&#xff0c;項目2 static關鍵字有什么用&#xff0c;static修飾不同東西時有什么作用&#xff0c;內部類用static修飾和不用static修飾有何區別。…

leetcode785. 判斷二分圖(dfs和bfs染色)

給定一個無向圖graph&#xff0c;當這個圖為二分圖時返回true。 如果我們能將一個圖的節點集合分割成兩個獨立的子集A和B&#xff0c;并使圖中的每一條邊的兩個節點一個來自A集合&#xff0c;一個來自B集合&#xff0c;我們就將這個圖稱為二分圖。 graph將會以鄰接表方式給出…

bdd cucumber_如何使用BDD構建堅如磐石的Ruby on Rails應用

bdd cucumberby Marko Anastasov通過Marko Anastasov 如何使用BDD構建堅如磐石的Ruby on Rails應用 (How to build rock-solid Ruby on Rails apps with BDD) 了解通過行為驅動開發來構建可持續Web應用程序的最佳實踐。 (Learn best practices for building sustainable web a…

go kegg_KEGG分析及可視化

上一篇推文中我們解釋了GO富集分析及可視化&#xff08;GO富集分析及可視化&#xff09;&#xff0c;除了GO富集分析&#xff0c;我們經常在paper中看到KEGG分析&#xff0c;KEGG是什么呢&#xff0c;Kyoto Encyclopedia of Genes and Genomes&#xff0c;京都基因和基因組百科…

IntelliJ IDEA注冊碼

IntelliJ IDEA注冊碼 http://idea.lanyus.com/ 1.導航欄下 2.help下 3.register點擊 4.單選Activation code 5.粘貼注冊碼 轉載于:https://www.cnblogs.com/YUJIE666/p/10662561.html

單詞本.

offset 偏移量 charset字符集 str 代表String字符串 IgnoreCase忽略大小寫 Object 對象 argument 參數 if and only if:當且僅當 value:值 specified:指定 Parameters:參數 iterator:迭代器 invoke:調用 variable:變量 resolved:解決 sequnence 序列 default:默認轉載于:http…

leetcode931. 下降路徑最小和(動態規劃)

給定一個方形整數數組 A&#xff0c;我們想要得到通過 A 的下降路徑的最小和。 下降路徑可以從第一行中的任何元素開始&#xff0c;并從每一行中選擇一個元素。在下一行選擇的元素和當前行所選元素最多相隔一列。 示例&#xff1a; 輸入&#xff1a;[[1,2,3],[4,5,6],[7,8,9…

lvm使用

注&#xff1a;新添加的硬盤&#xff0c;如果沒有分區&#xff0c;可以直接使用pvcreate進行創建&#xff0c;然后用vgextend進行擴展如果新添加的硬盤經過分區&#xff0c;則要把需要擴展的分區修改為8e格式&#xff0c;則進行擴展以上內容實測~相關概念&#xff1a;pv:物理卷…

python django用戶登錄系統_Django實現用戶注冊登錄

學習Django中&#xff1a;試著著寫一個用戶注冊登錄系統&#xff0c;開始搞事情 O(∩_∩)O哈哈~Ubuntupython 2.7.12Django 1.10.4IDE&#xff1a;PycharmBootstrap(其實沒怎么用~~)新建項目&#xff1a;(我是直接用pycharm直接生成的)使用終端&#xff1a;(創建項目)django-ad…

ubantu 添加防火墻策略_ubuntu安裝防火墻并策略配置

1、安裝ubuntu防火墻sudo apt-get install ufw啟用sudo ufw enablesudo ufw default deny作用&#xff1a;開啟了防火墻并隨系統啟動同時關閉所有外部對本機的訪問(本機訪問外部正常)。關閉sudo ufw disable查看防火墻狀態sudo ufw status2、開啟/禁用相應端口或服務舉例sudo u…

如何使用React Native構建嵌套的抽屜菜單

by Dhruvdutt Jadhav由Dhruvdutt Jadhav 如何使用React Native構建嵌套的抽屜菜單 (How to build a nested drawer menu with React Native) Screen space is a precious commodity on mobile. The drawer menu (or “hamburger menu”) is one of the most popular navigatio…