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
當類之間有顯著不同,並且較小的類是較大的類所需要的元件時,用組合比較好