面向對象


類的定義 class關鍵字 類名的首字母大寫
類中直接定義屬性:靜態屬性(變量) 和 動態屬性(函數)
類名的兩個作用:屬性的引用,實例化對象
類名和屬性的操作:對象名.屬性名 對象名.__dict__['屬性名'](不能修改)#########(可以修改的)##########
實例化 ——類名(參數)
構造方法:造對象
初始化__init__:給這個赤裸裸的對象添加一些屬性 __init__
返回了一個初始化之後的對象
__init__方法:初始化方法,可以沒有。給對象添加一些必要的基礎屬性
self的含義:就是這個對象本身
對象和屬性的操作:對象名.屬性名 對象名.__dict__['屬性名']
def 函數名():
'''函數體'''
pass
class Person:#類名有兩個作用
country ='中國'#靜態屬性、數據屬性
defwalk(self):#動態屬性、函數屬性、方法
print('walk')
屬性:靜態屬性(直接和類名關聯或者直接定義在class下的變量)
對象屬性(在類內和self關聯,在類外和對象名關聯的變量)
動態屬性(函數)
class Foo:
country = 'China'
country_lst = ['China']
def__init__(self,name):
self.name = name
alex = Foo('alexander')
egg = Foo('egon')
alex.age = 90
alex.country_lst = []
alex.country_lst.append('印度')
類名操作變量 不管操作可變還是不可變數據類型 都是類中對應的變量發生變化
對象名操作靜態變量
引用變量:現在自己的命名空間中查找,找不到就去類的命名空間找
修改變量:
如果是對可變數據類型中的元素進行修改,那麼全局生效
如果是對變量進行重新賦值,那麼只是在對象自己的命名空間裏增加了一個新的屬性
結論:應該儘量用類名去使用靜態變量
二、
面試一、
classFoo:
count = 0
def__init__(self):
Foo.count += 1
f = Foo()
f2 = Foo()
f3 = Foo()
print(f.count)#Foo.count ## 3
print(f2.count)#Foo.count ## 3
print(f3.count)#Foo.count ## 3
面試二、
設計一個類,統計這個類被實例化的次數,且所有的對象共享這個屬性
classFoo:
count = 0
def__init__(self):
Foo.count += 1
f = Foo()
print(f.count## 1
f2 = Foo()
print(f.count)## 2
f3 = Foo()
print(f3.count)## 3
三、小栗子
class Person:
def __init__(self):pass#給一個什麼屬性都沒有的對象賦一些初識的屬性
def eat(self):
print('吃豬食')
alex = Person() #裸着
print(alex.__dict__)# {}
alex.name = 'alexander'
print(alex.__dict__)# {'name': 'alexander'}
alex.eat = '泔水'#對象使用名字的順序:先用自己的,再用類的
print(alex.eat)# 泔水
# alex.eat() # 若沒有 泔水,則吃豬食,否則報錯
#對象可以使用類的
#而類無法使用對象的
print(Person.eat)# <function Person.eat at 0x000000000257A400>
print(alex.eat)#類對象指針的東西 alex = {'eat':eat} # 泔水
四、
函數(定義 調用 返回值 參數、命名空間和作用域);
面向對象(定義 、命名空間)
三大特性:封裝繼承和多態(組合);
組合 : 什麼 有 什麼 的關係
一個對象的屬性是另外一個類的對象
①老師有生日
②圓形有圓環
frommath importpi
classCircle:
def__init__(self,r):
self.radius = r
defperimeter(self):
return2*pi*self.radius
defarea(self):
returnpi*(self.radius**2)
#環形類
classRing:
def__init__(self,outer_r,inner_r):
self.outer_circle = Circle(outer_r)
self.inner_circle = Circle(inner_r)
defperimeter(self):
returnself.outer_circle.perimeter()+self.inner_circle.perimeter()
defarea(self):
returnself.outer_circle.area() -self.inner_circle.area()
ring1 = Ring(20,10)
print(ring1.area())
人狗大戰用組合:
class Dog:  # 定義一個狗類
    def __init__(self, name, breed, aggressivity, life_value):
        self.name = name  # 每一隻狗都有自己的暱稱;
        self.breed = breed  # 每一隻狗都有自己的品種;
        self.aggressivity = aggressivity  # 每一隻狗都有自己的攻擊力;
        self.life_value = life_value  # 每一隻狗都有自己的生命值;
    def bite(self,people):
        people.life_value -= self.aggressivity
class Person:  # 定義一個人類
    def __init__(self, name, aggressivity, life_value, money):
        self.name = name  # 每一個角色都有自己的暱稱;
        self.aggressivity = aggressivity  # 每一個角色都有自己的攻擊力;
        self.life_value = life_value  # 每一個角色都有自己的生命值;
        self.money = money
    def attack(self,dog):
        dog.life_value -= self.aggressivity
    def get_weapon(self,weapon_obj):
        if self.money > weapon_obj.price:
            self.money -= weapon_obj.price  # 金老闆花錢買武器
            self.weapon = weapon_obj  # 金老闆裝備打狗棒
            self.aggressivity += weapon_obj.aggr  # 金老闆的攻擊力增加了
#不公平#武器裝備#人 有 武器 —— 組合
#武器:攻擊力,名字,價格
class Weapon:
    def __init__(self,name,price,aggr):
        self.name = name
        self.price = price
        self.aggr = aggr
dgb = Weapon('打狗棒',99.8,100)
boss_gold = Person('金老闆',5,250,100)
huang = Dog('大黃','藏獒',100,3000)
boss_gold.get_weapon(dgb)
boss_gold.attack(huang)
print(huang.life_value)
---------------------------------------------------------------
python兩種類:經典類 新式類
python3新式類 ——都默認繼承objectclass Animal(object): ==class Animal:
python2經典類和新式類 並存
class Animal:經典類 ——繼承順序個別使用方法
class Animal(object):新式類
----------------------------------------------------------------
繼承:把相同的代碼放在父類中,子類的對象在子類中沒有找到方法的時候,使用父類的
class Animal:
    def __init__(self,name,aggressivity,life_value):
        self.name = name
        self.aggressivity = aggressivity
        self.life_value = life_value
class Dog(Animal):  # 定義一個狗類
    def bite(self,people):
        people.life_value -= self.aggressivity
class Person(Animal):  # 定義一個人類
    def attack(self,dog):
        dog.life_value -= self.aggressivity
    def get_weapon(self,weapon_obj):
        if self.money > weapon_obj.price:
            self.money -= weapon_obj.price  # 金老闆花錢買武器
            self.weapon = weapon_obj  # 金老闆裝備打狗棒
            self.aggressivity += weapon_obj.aggr  # 金老闆的攻擊力增加了
huang = Dog('大黃',100,3000)   #__init__ 找父類
print(huang.life_value)
boss_gold = Person('金老闆',5,250)  #__init__ 自己沒有 找父類
print(boss_gold.life_value)
# Dog.bite(Person)
print(Dog.__bases__)
print(Animal.__bases__)

day25 1121:
一、兩個類中有相同的代碼,引申出繼承:繼承
1、繼承:把相同的代碼放在父類中,子類的對象在子類中沒有找到方法的時候,使用父類的
①單繼承和多繼承 ②父類 超類 基類 ③子類 派生類
④抽象(模糊到具體)和繼承(具體到模糊) 先抽象後繼承
2、兩個比較6的具體事例:
他大舅他二舅都是他舅 —— 實例化
高桌子低板凳都是木頭 —— 繼承
3、小栗子:
class Animal:
    pass
    def __init__(self,sleep):
        self.sleep = sleep
class Cat(Animal):
    def __init__(self, eat, drink,sleep):
        super().__init__(sleep)
        self.eat = eat
        self.drink = drink
    def door(self):
        print('door')
class Dog(Animal):
    def fish(self):
        print('yu')
hua = Cat(1,2,3)
hua.door()         # door
print(hua.eat)     # 1
print(hua.sleep)   # 3 
4、
派生屬性 : 在自己的init方法裏 使用父類的init方法 —— 指名道姓調用方法
派生方法 : 在子類中增加父類沒有的
只要子類有,就用子類的
只要想用父類,Animal.eat(snoopy) 父類名.父類的方法(子類對象)2.7經典類中
5、
class Animal:
    def __init__(self,aggressivity, life_value,name):
        self.name = name  # 每一個角色都有自己的暱稱;
        self.aggressivity = aggressivity  # 每一個角色都有自己的攻擊力;
        self.life_value = life_value  # 每一個角色都有自己的生命值;
    def eat(self):
        self.life_value += 10

class Person(Animal):
    def __init__(self, name, aggressivity, life_value, money):
        # Animal.__init__(self, name, aggressivity, life_value)
        super().__init__(name, aggressivity, life_value)  #新式類
        self.money = money    #派生屬性:父類沒有的屬性

    def attack(self,dog):
        dog.life_value -= self.aggressivity

    def get_weapon(self,weapon_obj):
        if self.money > weapon_obj.price:
            self.money -= weapon_obj.price  # 金老闆花錢買武器
            self.weapon = weapon_obj  # 金老闆裝備打狗棒
            self.aggressivity += weapon_obj.aggr  # 金老闆的攻擊力增加了
class Dog(Animal):
    def __init__(self, name, breed, aggressivity, life_value):
        # Animal.__init__(self,aggressivity,life_value,name)
        # super(Dog,self).__init__(aggressivity,life_value,name)
        super().__init__(aggressivity,life_value,name)
        self.breed = breed  # 每一隻狗都有自己的品種; #派生屬性:父類沒有的屬性

    def bite(self,people):  # 派生方法 :父類沒有的方法
        people.life_value -= self.aggressivity

    def eat(self):
        # Animal.eat(self)
        super().eat()
        print('dog is eating')
snoopy = Dog('太白','京巴',250,500)
print(snoopy.breed)            # 京巴
print(snoopy.name)            #  太白
snoopy.eat()            #  dog is eating
print(snoopy.life_value)        # 510
super(Dog,snoopy).eat()   #Animal.eat(snoopy)      #  外部也可以用super需要制定參數。             # 這個是加血不是吃!!!!!
print(snoopy.life_value)    #   520
總結:
用子類的對象,調用父類的方法:
如果子類中沒有這個方法,直接就使用父類的
如果子類中有同名方法:
經典類 指名道姓 類名.方法名(子類對象) 類內外一致
新式類 super方法super(子類名,子類對象).方法名() 類內可以省略super的參數
二、面試:
class Foo:
def __init__(self):
self.func()
def func():
print(" this is Foo.func")
class Son(Foo):
def func():
print('this is Son.func')
s = Son     # ## this is Son.func(調用自己的func)
實例化子類會調用初始化方法(子類沒有調父類)
三、鑽石繼承問題
用子類的對象,調用父類的方法:
如果子類中沒有這個方法,直接就使用父類的
如果子類中有同名方法:
經典類 指名道姓 類名.方法名(子類對象) 類內外一致
新式類 super方法super(子類名,子類對象).方法名() 類內可以省略super的參數
class D:
    def f(self):
        print('D')
class B(D):
    def f(self):
        print('B')
class C(E):
    def f(self):
        print('C')
class A(B,C):
    def f(self):
        print('A')
a = A()
a.f()
print(A.mro()) 新式類:查看繼承順序
class A(object):pass 新式類
class A(object):pass 新式類
在好多個有繼承關係的類裏面,找一個方法,找的順序問題
繼承三層(一般)
py3 ——廣度優先(只有,因爲3 沒有經典類)
py2 ——新式類在好多個有繼承關係的類裏面,找一個方法,找的順序問題
繼承三層(一般)
py3 ——廣度優先(只有,因爲3 沒有經典類)
py2 ——新式類
面試——能對應 新式類 是廣度優先 經典類是深度優先
四、多態
python中自帶多態。
五、鴨子類型
走的像鴨子,教的像鴨子就認爲是鴨子
python不崇尚繼承,崇尚鴨子類型
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章