1. 程式人生 > >python面向物件組合-day22

python面向物件組合-day22

class A:
    Country = 'China'
    def talk(self):
        print('%s is talking'%self.name)
alex = A()          #相當於A(self)
alex.name = 'alex'  #相當於A(self,name)
alex.talk()
一個類可以沒有__init__
在沒有__init__的情況下,例項化經歷了哪些步驟???
    1.建立一個空間給物件
    2.將這個空間的地址返回

class A:
    Country = 'China'
    def __init__(self,name):
        self.name = name
    def talk(self):
        print('%s is talking'%self.name)
#新增靜態屬性
A.靜態屬性名 = 'abc'
print(A.靜態屬性名)
#修改靜態屬性
A.Country = '印度'
print(A.Country)
#刪除靜態屬性
del A.Country
print(A.Country)   # 報錯
#檢視類中的方法,只能看,不能改也不能刪
print(A.__dict__)

類的名稱空間中有什麼:
    靜態屬性(共享給所有物件的)
    動態屬性(繫結到所有物件的)

物件的名稱空間和類的名稱空間之間的關係:
    物件和類之間有一個單向的聯絡,類物件指標
    建立一個物件/例項就會建立一個物件/例項的名稱空間,存放物件/例項的名字,稱為物件/例項的屬性
    物件在使用某個名字的時候,如果在自己的空間中沒有找到,就找父類,如果父類找不到,就要到類的空間中去找,最後到找不到拋異常
    物件可以檢視類的靜態屬性,但是不能修改
    並且一旦修改,就不能取到類當中的內容了(除非手動刪除這個修改的屬性)
    所有的靜態屬性的修改,都應該由類名來完成,而不應該使用物件名來完成
class A:
    Country = 'China'
    def __init__(self,name):
        self.name = name
    def talk(self):
     print('%s is talking'%self.name)
alex = A('alex')
baoyuan = A('baoyuan')
print(alex.Country)
alex.Country = '泰國'
print(alex.Country)
del alex.Country
print(alex.Country)
print(A.Country)
print(baoyuan.Country)

靜態屬性就是用來描述所有的物件都共享的某一個值
class People:
    money = 1000
    def salary(self):
        People.money += 1000
mother = People()
father = People()
mother.salary()
father.salary()
print(People.money,mother.money,father.money)

寫一個類,能夠記錄這個類有多少個物件了(每一次例項化都能夠被記錄下來)
    class A:
        count = 0
        def __init__(self):
            A.count += 1
    print(A.count)
    a = A()
    print(A.count)
方法二
    class A:
        count = 0
        def __init__(self):
            self.counter()
        def counter(self):
            A.count+=1
    a = A()

class People:
    money = 1000
    def salary(self):
        People.money += 1000
mother = People()
father = People()
mother.salary()
father.salary()
print(People.money,mother.money,father.money)

class B:
    l = []
    def __init__(self,name):
        self.l.append(name)
alex = B('alex')
baoyuan = B('寶元')
print(B.l)
print(alex.l)
print(baoyuan.l)

如果靜態變數是一個不可變資料型別,那麼只要物件修改這個資料,就相當於在物件的空間中新建
如果靜態變數是一個可變資料型別,那麼物件修改這個容器中的元素,相當於修改類的空間中的元素
如果靜態變數是一個可變資料型別,那麼物件直接對這個變數重新賦值,相當於修改物件自己空間中的元素

大結論
只要是靜態變數,就用類名去修改,永遠修改成功,並且所有的物件都共享這個改變

總結
物件的名稱空間:類指標\物件的所有屬性
類的名稱空間:方法和(靜態屬性\欄位)
物件在尋找名字的時候 : 先找物件自己記憶體空間中的,找不到就去類的名稱空間中尋找
類中的名字是什麼時候寫入記憶體的 : 程式碼從上到下執行的時候就已經寫入的.一定是在例項化之前
靜態變數 : 儘量用類名去操作

組合 : 一個類物件的屬性是另外一個類的物件
class Person:
    def __init__(self,name,sex,hp,mp,ad):
        self.name = name
        self.sex = sex
        self.hp = hp
        self.mp = mp
        self.ad =ad
    def attack(self,dog):
        print('%s攻擊了%s'%(self.nme,dog.name))
        dog.hp -= self.ad
class Dog:
    def __init__(self,name,kind,hp,ad):
        self.name = name
        self.kind = kind
        self.hp = hp
        self.ad = ad
    def bite(self,person):
        print('%s咬了%s'%(self.name,person.name))
        person.hp -= self.ad
alex = Person('alex','man',10,10,0.1)
hei = Dog('小黑','中華田園犬',999,1.1)
hei.bite(alex)
class Weapon:
    def __init__(self,name,price,ad):
        self.name = name
        self.price = price
        self.ad = ad
    def skill(self,dog):
        print('%s被%s攻擊了'%(dog.name,self.name))
        dog.hp -= self.ad
        print(dog.hp)
sh = Weapon('棍子',9.99,66)
sh.skill(hei)
alex.武器 = sh
alex.武器.skill(hei)
# sh.ad -= 10
alex.武器.skill(hei)
#解耦 (降低耦合)

class Birthday:
    def __init__(self,y,m,d):
        self.y = y
        self.m = m
        self.d = d
class Student:
    def __init__(self,name,sex,birth_day):
        self.name = name
        self.sex = sex
        self.birth_day = birth_day
birth = Birthday(1990,11,22)
bobo = Student('bobo','male',birth)
#bobo.birthday == birth
print(birth.year)
print(bobo.birthday.year)


class Circle:
    def __init__(self,r):
        self.r = r
    def area(self):
        return 3.14*self.r**2
    def perimter(self):
        return 3.14*2*self.r
c1 = Circle(10)
print(c1.area())
print(c1.perimter())

class Ring:
    def __init__(self,outer_r,inner_r):
        self.out_r = outer_r
        self.in_r = inner_r
    def area(self):
        return self.out_r**2*3.14 - self.in_r**2*3.14
    def perimeter(self):
        return self.out_r*2*3.14 - self.in_r*2*3.14
r1 = Ring(10,5)
print(r1.area())
print(r1.perimeter())

圓環是由兩個圓組成的,圓環的面積是外面圓的面積減去內部圓的面積。圓環的周長是內部圓的周長加上外部圓的周長。
這個時候,我們就首先實現一個圓形類,計算一個圓的周長和麵積。然後在"環形類"中組合圓形的例項作為自己的屬性來用
from math import pi
class Circle:
    def __init__(self,r):   #r為圓半徑
        self.r = r
    def area(self):
        return pi*self.r**2
    def perimeter(self):
        return pi*self.r*2
c1 = Circle(10)         #例項化一個圓半徑為10
print(c1.area())        #計算圓的面積
print(c1.perimeter())   #計算圓的周長
class Ring:
    def __init__(self,outer_r,inner_r):
        self.out_c1 = Circle(outer_r)
        self.in_c2 = Circle(inner_r)
        # c1 = Circle(outer_r)
        # c2 = Circle(inner_r)
        # self.out_c = c1
        # self.in_c = c2
    def area(self):
        return self.out_c1.area() - self.in_c2.area()
    def perimeter(self):
        return self.out_c1.perimeter() + self.in_c2.perimeter()
r1 = Ring(10,5)         #例項化一個環形
print(r1.area())        #計算環形的周長
print(r1.perimeter())   #計算環形的面積

事例二
class BirthDate:
    def __init__(self,year,month,day):
        self.year=year
        self.month=month
        self.day=day

class Couse:
    def __init__(self,name,price,period):
        self.name=name
        self.price=price
        self.period=period

class Teacher:
    def __init__(self,name,gender,birth,course):
        self.name=name
        self.gender=gender
        self.birth=birth
        self.course=course
    def teach(self):
        print('teaching')

p1=Teacher('egon','male',BirthDate('1995','1','27'),
           Couse('python','28000','4 months')
           )
print(p1.birth.year,p1.birth.month,p1.birth.day)
print(p1.course.name,p1.course.price,p1.course.period)
結果
1995 1 27
python 28000 4 months
當類之間有顯著不同,並且較小的類是較大的類所需要的元件時,用組合比較好