1. 程式人生 > >python第六周學習類容

python第六周學習類容

super 廣度優先 out 屬於 深度 程序 之一 life src

面向對象編程:

世界萬物,皆可分類

世界萬物,對象

只要是對象,就肯定屬於某種品類

只要是對象,就肯定有屬性

oop編程利用"類"和"對象"來創建各種模型來實現對真實世界的描述,使用面向對象對象編程原因之一是它可以使程序的維護和擴展變得簡單,且可以大大提高程序的開發效率,另外,基於面向對象的程序可以使他人更加容易理解你的代碼邏輯,從而使團隊開發變得從容。

面向對象的核心特性:
1.class 類

一個類即是對一類擁有相同屬性的對象的抽象、藍圖原型。在類中定義了這些對象的都具備的屬性、共同的方法。

class Dog:
    def __init__(self,name,age):
        self.name 
= name self.age = age def bark(self): print("%s: wang wang wang!"%self.name)
‘‘‘
name、age是靜態屬性簡稱屬性
bark()是動態屬性簡稱方法
‘‘‘

2.object 對象(也可以稱之為實例)

一個對象即是一個類的實例化後的實例,一個類必須經過實例化後方可在程序中調用,一個類可以實例化多個對象,每個對象亦有不同的屬性,就像人類指所有人,每個人指具體的對象,人與人之間有共性,亦有不同

class Dog:
    def __init__(self,name,age):
        self.name 
= name self.age = age def bark(self): print("%s: wang wang wang!"%self.name) d1 = Dog("Alex") d2 = Dog("San Pao") d3 = Dog("San San")
‘‘‘
d1、d2、d3即實例:把一個類變成一個具體的對象的過程就叫實例化
‘‘‘

3.Encapsulation 封裝

在類中對數據的賦值、內部的調用對外部用戶是透明的,這使類變成了一個膠囊或容器,裏面包含了類的數據和方法,把一些功能的實現細節不對外暴露

4.Inheritance 繼承 (組合:用來關聯其他對象)

一個類可以派生出子類·,在這個父類裏定義的公有屬性、公有方法自動被子類繼承

python2 經典類是按照深度優先來繼承的,新式類是按照廣度優先來繼承的

python3 經典類和新式類都是統一按照廣度優先來繼承的

#class People: #經典類
class People(object): #新式類
    def __init__(self,name,age):
        self.name = name
        self.age = age
        self.friends = []
    def eat(self):
        print("%s is eating..."%self.name)
    def sleep(self):
        print("%s is sleeping...."%self.name)
    def talk(self):
        print("%s is talking...."%self.name)

class Relation(object):
    def make_friends(self,obj):
        print("%s is making friend with %s"%(self.name,obj.name))
        self.friends.append(obj)

class Man(People,Relation):
    def __init__(self,name,age,money):
‘‘‘重構父類的構造方法‘‘‘
#People.__init__(self,name,age)#經典類寫法 super(Man, self).__init__(name,age)#新式類寫法 self.money = money def piao(self): print("%s is piaoing....20s.....done."%self.name) def sleep(self): #重構父類的方法 People.sleep(self) print("man is sleeping") class Woman(People,Relation): def get_birth(self): print("%s is born a baby......"%self.name) m1 = Man("Mr Wu",19,10000) w1 = Woman("Bai Zao",20) m1.make_friends(w1) print(m1.friends[0].name) #---output----- #Mr Wu is making friend with Bai Zao #Bai Zao

5.Polymorphism 多態

多態是面向對象的重要特性,簡單點說:“一個接口,多種實現”,指一個基類中衍生出了不同的子類,且每個子類中在繼承了同樣的方法名是又對父類的方法做了不同的實現,這就是同一種事物表現出的多種形態。

多態性是允許你將對象設置成為和一個或更多的它的子對象相等的技術,賦值之後,父對象就可以根據當前給它的子對象的特性以不同的方式運作。簡單地說:允許子類型的指針賦值給父類類型的指針。

那麽多態的作用是什麽呢?
我們知道,封裝可以隱藏實現細節,是代碼模塊化;繼承可以擴展已存在的代碼模塊(類);它們的目的都是為了---代碼重用!。而多態是為了實現另一個目的---接口重用!多態的作用,就是為了在繼承和派生的時候,保證使用“家譜”中的任一類的實例的某一屬性時的正確調用。

python不支持多態,但可以間接調用。

class Animal(object):
    def __init__(self,name):
        self.name = name
    def talk(self):
        pass
class Cat(Animal): def talk(self): print(Meow!) class Dog(Animal): def talk(self): print(woof! woof!) def animal_talk(obj): obj.talk() d1 = Dog("San Pao") c1 = Cat("Li Si") animal_talk(d1) animal_talk(c1) #----output----- #Meow! #woof! woof!

面向對象初級語法:

1.屬性:構造函數中定義的變量是靜態屬性簡稱為屬性

類中定義的函數是動態屬性簡稱為方法

2.類變量(大家共用的屬性,可以節省開銷)、實例變量

類變量定義:在構造函數和其他函數之外定義的變量就叫類變量

實例變量:在構造函數或實例中定義的變量

class Role(object):
    n = 123 #類變量
    name = "我是類name" #類變量
    def __init__(self,name,role,weapon,life_value=100,money=15000):
        #構造函數
        #在實例化時做一些類的初始化的工作
        self.name = name
        #self.name中的name和構造函數的參數name沒有任何關系,它們兩個一樣,
        #只不過是一種起巧合
        self.role = role #實例變量(靜態屬性),作用域是實例本身
        self.weapon = weapon
        self.money = money
    def shot(self): #類的方法,功能(動態屬性)
        print("shooting.....")
    def get_shot(self):
        print("an....,i got shot....")
    def buy_gun(self,gun_name):
        print("%s just bought %s"%(self.name,gun_name))

print(Role)#<class ‘__main__.Role‘>
print(Role.n) #123
r1 = Role("Alex","police","AK47") 
r2 = Role("Jack","terrorist","B22")
#實例變量與類變量的優先級
print(r1.n,r1.name)
# 123 Alex,故實例變量優先於類變量
#修改實例變量
r1.name = "Mr Wu"
print(r1.name)# Mr Wu
#刪除實例變量
del r1.weapon
#添加實例變量
r1.bullet_prove = True
#修改類變量(列表、字典例外,無論在哪兒修改都會影響全部實例)
r1.n = "改類變量" 
#這是在r1的內存中創建了一個新的變量n,並沒有修改類變量
print("r1:",r1.n,",","r2:",r2.n)
#------output------
#r1: 改類變量 , r2: 123
Role.n = "ABC"
print("r1:",r1.n,",","r2:",r2.n)
#-------output------
#r1: 改類變量 , r2: ABC

3.構造函數:
在實例化的時候做一些初始化工作

def  __init__(self,name,age):
    self.name = name

    self.age = age

實例化過程:
技術分享圖片

4.析構函數

在實例釋放、銷毀的時候自動執行,通常用於做一些收尾工作,如關閉一些數據庫連接、臨時打開的文件

def __del__(self):
    #析構函數

    print("%s 徹底死了......"%self.name)

5.私有方法、私有屬性

在屬性、方法前加__即可

例如:

class Dog(object):
    def __init__(self,name):
        self.__name = name
    def __eat(self):
        pass
d = Dog("Da Nao")
d.__name #error
d.__eat() #error

面向對象高級語法:
1.靜態方法、類方法、屬性方法

(1)靜態方法:只是名義上歸類管理,實際上在靜態方法裏訪問不了類或實例中的任何屬性和方法

class Dog(object):
    def __init__(self,name):
        self.name = name
    @staticmethod #靜態方法,實際上跟類沒什麽關系了
    def eat():
        print("%s is eating %s"%(self.name,"dd")) #error
        #print("dddd is eating dd ") #ok
d = Dog("陳榮華")
d.eat() 
#Name Error:name ‘selif‘ is not defined

(2)類方法:只能訪問類變量,不能訪問實例變量

class Dog(object):
    name = "Mr Wu"
    def __init__(self,name):
        self.name = name

    @classmethod #類方法,
    def eat(cls):
        print("【\033[1;35m%s\033[0m】 \033[1;38mis eating\033[0m 【\033[1;33m%s\033[0m】"%(cls.name,"雞排"))

d = Dog("dddddd")
d.eat() 
#【Mr Wu】 is eating 【雞排】

(3)屬性方法:把一個方法變成一個靜態屬性,對用戶隱藏實現細節(對用戶來說,只需要調用屬性即可,無需關心其內部如何操作)

class Dog(object):
    def __init__(self,name):
        self.name = name
        self.__food = None
    @property #屬性方法
    def eat(self): #不能添加其他參數
        print("%s is eating %s"%(self.name,self.__food))
    @eat.setter #給一個屬性賦值
    def eat(self,food):
        self.__food = food
        #print("set to food:",food)
    @eat.deleter #刪除屬性方法
    def eat(self):
        del self.__food
        print("刪完了")
d = Dog("chenronghua")
d.eat #chenronghua is eating None
d.eat = "baozi"
d.eat #chenronghua is eating baozi
del d.eat #刪完了
#d.eat #error
class Flight(object):
    def __init__(self,name):
        self.flight_name = name

    def checking_status(self):
        print("checking flight %s status"%self.flight_name)
        return 2
    @property
    def flight_status(self):
        status = self.checking_status()
        if status == 0:
            print("\033[1;33m flight got canceled.....\033[0m")
        elif status == 1:
            print("\033[1;34m flight is arrived....\033[0m")
        elif status == 2:
            print("\033[1;35m flight has departured already....\033[0m")
        else:
            print("\033[1;36m cannot confirm the flight status...\033[0m")
    @flight_status.setter
    def flight_status(self,status):
        print("flight %s has changed status to %s"%(self.flight_name,status))


f = Flight("CA980")
f.flight_status
f.flight_status = 1
‘‘‘output‘‘‘
‘‘‘
checking flight CA980 status
 flight has departured already....
flight CA980 has changed status to 1
‘‘‘

2.類的特殊成員方法

(1)__doc__:表示類的描述信息

class People(object):
    ‘‘‘this is the description of People‘‘‘
    def __init__(self,name,sex,age):
        self.name = name
        self.sex = sex
        self.age = age
    def eat(self):
        print("%s is eating...."%self.name)
    def piao(self):
        print("%s is piaoing..."%self.name)

print(People.__doc__)
#this is the description of People

(2)__module__、__class__

__module__ 表示當前操作的對象在哪個模塊

__class__ 表示當前操作的對象的類是什麽

class People(object):
    ‘‘‘this is the description of People‘‘‘
    def __init__(self,name,sex,age):
        self.name = name
        self.sex = sex
        self.age = age
    def eat(self):
        print("%s is eating...."%self.name)
    def piao(self):
        print("%s is piaoing..."%self.name)

man = People("dog","male",19)
print(man.__module__) 
print(man.__class__)
#output
#__main__
#<class ‘__main__.People‘>

(3)__init__

構造方法,通過類創建對象時,自動觸發進行(做一些初始化工作)

程序:略

(4)__call__:對象後面加括號,觸發執行

class People(object):
    ‘‘‘this is the description of People‘‘‘
    def __init__(self,name,sex,age):
        self.name = name
        self.sex = sex
        self.age = age
    def eat(self):
        print("%s is eating...."%self.name)
    def piao(self):
        print("%s is piaoing..."%self.name)
    def __call__(self, *args, **kwargs):
        print("My name is Mr Wu")

man = People("dog","male",19)
man() #My name is Mr Wu

(5)__dict__:查看類或對象中的所有成員

class People(object):
    ‘‘‘this is the description of People‘‘‘
    def __init__(self,name,sex,age):
        self.name = name
        self.sex = sex
        self.age = age
    def eat(self):
        print("%s is eating...."%self.name)
    def piao(self):
        print("%s is piaoing..."%self.name)
    def __call__(self, *args, **kwargs):
        print("My name is Mr Wu")

man = People("dog","male",19)
print(People.__dict__)
‘‘‘
{‘__weakref__‘: <attribute ‘__weakref__‘ of ‘People‘ objects>, 
‘__doc__‘: ‘this is the description of People‘, 
‘__dict__‘: <attribute ‘__dict__‘ of ‘People‘ objects>, 
‘__init__‘: <function People.__init__ at 0x006D6030>, 
‘__call__‘: <function People.__call__ at 0x006D6108>,
 ‘__module__‘: ‘__main__‘, ‘eat‘: <function People.eat at 0x006D6078>, 
 ‘piao‘: <function People.piao at 0x006D60C0>}
‘‘‘

(6)__str__:如果一個類定義了__str__方法,那麽在打印對象時,默認輸出該方法的返回值

class People(object):
    ‘‘‘this is the description of People‘‘‘
    def __init__(self,name,sex,age):
        self.name = name
        self.sex = sex
        self.age = age
    def eat(self):
        print("%s is eating...."%self.name)
    def piao(self):
        print("%s is piaoing..."%self.name)
    def __call__(self, *args, **kwargs):
        print("My name is Mr Wu")
    def __str__(self):
        return "hello world"

man = People("dog","male",19)
print(man)
#hello world

(8)__getitem__、__setitem__、__delitem__

用於索引操作,如字典。以上分別是獲取、設置、刪除數據

程序:略

(9)__new__、__metaclass__:類的創建過程、定制類

預備知識:

‘‘‘
python中一切皆對象,Foo類本身也是一個對象
f對象是通過執行Foo類的構造方法創建.
Foo類對象也是通過執行type類的構造方法創建
我們稱呼type為類的類或源類
‘‘‘
class Foo(object):
    def __init__(self,name):
        self.name = name

f = Foo("alex")
print(type(f))#<class ‘__main__.Foo‘>
print(type(Foo))#<class ‘type‘>

*******創建類的兩種方式*******

#a).普通方式
class Foo(object):
    def func(self):
        print("hello alex!")

#b).特殊方式
def __init__(self,name,age):
    self.name = name
    self.age = age
def func(self):
    print("hello %s!"%self.name)
Foo = type("Foo",(object,),{"say":func,"__init__":__init__})
#type第一個參數:類名(傳入字符串)
#type第二個參數:當前類的基類(傳入元組)
#type第三個參數:類的成員(傳入字典)
f = Foo("Mr Wu",19)
f.say()#hello Mr Wu!
print(f.name)#Mr Wu
print(type(Foo))#<class ‘type‘

type類是如何實現的創建類?類又是如何創建對象?

答:類中有一個屬性:__mataclass__,其用來表示該類有誰來實例化創建,所以我們可以為__metaclass__設置一個type類的派生類,從而查看類的創建過程

class MyType(type):
    def __init__(self,what,bases=None,dict=None):
        print("--MyType init---")
        super(MyType,self).__init__(what,bases,dict)
    def __call__(self, *args, **kwargs):
        print("--MyType call---")
        obj = self.__new__(self,*args,**kwargs)
        self.__init__(obj,*args,**kwargs)

class Foo(object):
    __metaclass__ = MyType
    def __init__(self,name):
        print("Foo ---init__")
    def __new__(cls, *args, **kwargs):
        print("Foo ---new--")
        return object.__new__(cls) #繼承父親的__new__方法

obj = Foo("alex")

‘‘‘
------output-----
Foo ---new--
Foo ---init__
原因:
在實例化的時候,首先調用__new__(),再將__new__()的結果傳給__init__()完成實例創建,
故 __new__()是用來創建實例的
‘‘‘

技術分享圖片

python第六周學習類容