day23 01 類的命名空間 一、初識面向對象複習 定義類: class 函數:方法 動態屬性 變數:類屬性 靜態屬性 過程: (1)_init_方法:初始化:def _init_(self,參數) python幫我們創建了一個對象self 每當我們調用類的時候就會自動觸發這個方法 在_init_ ...
day23 01 類的命名空間
一、初識面向對象複習
定義類:
class
函數:方法 動態屬性
變數:類屬性 靜態屬性
過程:
(1)_init_方法:初始化:def _init_(self,參數)
python幫我們創建了一個對象self
每當我們調用類的時候就會自動觸發這個方法
在_init_方法裡面可以對self進行賦值
self是什麼:self擁有屬性都屬於對象
在類的內部,self就是一個對象
比如:someone=person(),someone.walk==person.walk(someone),括弧裡面就是類裡面的walk方法所傳的參數self,
而且這個參數必須傳
(2)實例化:對象=類(參數是_init_方法的)
實例==對象 沒有區別
對象查看屬性:對象.屬性
對象調用方法:對象.方法名(參數)==類名.方法名(對象名,參數)
(3)實例:
求正方形的周長和麵積:
class square: def __init__(self,side_len): self.side_len_=side_len def perimeter(self): return self.side_len_*4 def area(self): return self.side_len_**2 s=square(6) print(s.perimeter()) print(s.area())
運行結果:
24 36
為什麼計算這個周長和麵積要使用類的調用和方法呢?
正方形不同的地方就是邊長不一樣,不同的邊長的正方形就歸為一類
有了固定的邊長,當調用類裡面的方法的時候就不需要再傳參數了:print(s.perimeter()) , print(s.area())都不需要再傳參數
何為python入門,面向對象入門:
python 入門:當你見到一個需求,你能翻譯成python語言
面向對象入門:當你見到一個需求,你能分析這個需求適不適合使用面向對象解決,如果適合,你能有一些想法
二、類和對象的命名空間
類裡面可以定義兩種屬性:
靜態屬性:
動態屬性:
定義一個類:一種課程course,屬性有:老師,課程名字,課程時間,課程費用
class course: language='Chinese' def __init__(self,teacher,course_name,period,price): self.teacher=teacher self.course_name=course_name self.period=period self.price=price def func(self): pass python=course('李白','python','六個月','10000') print(python.teacher) print(python.course_name) print(python.period) print(python.price) course.language='English' #直接類名.靜態屬性是可以修改靜態屬性的 print(course.language) course.__dict__['language']='English' #但是使用類的字典形式去修改靜態屬性是不可能的,會報錯 print(course.language) print(python.language) #使用對象調用和查看類下的靜態屬性是可以的
運行結果:
Traceback (most recent call last): 李白 File "<encoding error>", line 31, in <module> python TypeError: 'mappingproxy' object does not support item assignment 六個月 10000 Chinese English
1、為什麼對象可以直接調用查看類下的靜態屬性呢?
print(python.language)---可以且不會報錯
類下的命名空間有:language, _init_, func
對象self裡面的命名空間有:teacher, course_name, period, price
類對象指針(記憶體地址可以有對象的指向類的):可以根據對象屬性找到對應的類,但是不能根據類找到對應的對象屬性
python.language:首先會在python裡面找,如果找不到就會向對應的類中找,找到了就可以調用查看了
course.name:是找不到的
假設多加一門課程linux:
python=course('李白','python','六個月','10000') linux=course('秋白','linux','六個月','10000')
沒有改變類下的靜態屬性language,然後列印
print(python.language)
print(linux.language)
是都可以列印出來的,且都是Chinese,而當通過
course.language='English'
修改靜態屬性之後,再次列印
print(python.language)
print(linux.language)
結果也都會隨之改變,都會變成English,當只通過對象修改類下的靜態屬性,在列印也是可以改的,如下:
python.language='English' print(python.language)
2、對於不可變數據類下的類下屬性的操作
上面的 python.language='English', print(python.language)的改法實際上是在python對象下創建了一個新的language=‘English’,所以再python裡面可以找得到,就不會繼續往類下麵去找,在類下和linux下麵(Linux指向的是類的命名空間)並沒有創建新的language,類下的language是不可變的數據類下,所以當列印
print(linux.language)
print(course.language)
的結果還是原來的language的結果,即Chinese所以:
註意:對於不可變的數據類型來說,類變數最好使用類名操作
3、對於可變的數據類型類下屬性的操作
比如前面的代碼中類下的屬性如果是: language=['Chinese'],然後按照下麵進行修改列印:
course.language[0]='English' print(course.language) print(linux.language) python.language[0]='English' print(python.language) print(course.language) print(linux.language)
運行結果:
['English']
['English']
['English']
['English']
['English']
此時通過對象名對類下的屬性進行修改的時候就可以修改成功了,為什麼呢?
(1)對於course.language[0]='English'的修改
類下的命名空間裡面的language指向一個list的地址,而list的0元素指向的是Chinese的地址,當你通過 course.language[0]='English'
去修改的時候,並沒有改變language指向list,對象指向類的命名空間的過程,所以最後都可以通過對象找得到改變的類下的屬性;
(2)對於python.language[0]='English'的修改
首先python對象先在自己的命名空間裡面找一個可變的數據類型language,找不到就往類的命名空間裡面找,因為對象指向類的命名空間,並且可以找到可變的數據類型language,所以在做python裡面的修改的時候,類下的也會隨之改變
註意:對於可變數據類型來說,通過對象名修改類下屬性是共用的,但是如果不是修改而是直接重新賦值的話是獨立的(類似於前面的不可變數據類型通過對象名對類下屬性是不能修改的)
4、創建一個類,每實例化一個對象就記錄下來,最終所有的對象都共用這個數據
比較簡單的代碼:
class Foo: count=0 def __init__(self): Foo.count+=1 #使用類名操作類下屬性,對象名調用類下屬性的時候,類下屬性會隨著操作的變化而變化 f1=Foo() f2=Foo() print(f1.count) print(f2.count)
f3=Foo()
print(f1.count) #實例化f3,然後通過對象f1操作類下屬性,也是可以的,說明通過類名操作類下屬性的結果是共用的
運行結果:
2 2
3
這樣就能滿足每次實例化的時候count就會加一
5、認識綁定方法
一個類也是可以沒有_init_方法的初始化的,只不過這樣每次實例化的時候創建對象字典裡面就沒有任何值,是一個空的字典,代碼如下:
class Foo: def func(self): print('func') f1=Foo()
運行結果:為空
class Foo: def func(self): print('func') f1=Foo() print(Foo.func) print(f1.func) #這裡的列印結果<bound method Foo.func of <__main__.Foo object at 0x0000016551112860>>會告訴我們一個綁定方法 print(f1)
什麼叫做綁定方法呢?
只有當對象去調用類下的方法的時候,調用方法的時候必須傳入就是該對象,這樣對象與方法之間就產生了一種綁定的關係,如果用類名調用就不會產生這種綁定關係
先暫時瞭解一下,因為後面會講到類外一種非綁定的方法
6、包中的_init_
為什麼我們每次導入一個包就會自動調用執行裡面的_init_文件?
因為每次導入一個包 import package====類的實例化過程,包每次被導入就成為一個對象了,所以只要導入就可以使用裡面的方法
比如:
import time
time.time