day31 Pyhton 面向物件的基礎 三大特性
阿新 • • 發佈:2018-11-28
一.內容回顧
封裝
1.概念 筆記
2.__名字 在類的外部就不能用了
3.私有化的 不能被子類繼承,也不能在其他任何類中呼叫
三個裝飾器方法(裝飾類中的方法)
1.不被修飾的 普通方法,會使用物件self的屬性
[email protected] 類方法,不使用self的屬性,用類cls的屬性
[email protected] 靜態方法,不用self的屬性和類cls的屬性
[email protected] 將一個方法偽裝成一個屬性
def 函式名
@函式名.setter
@函式名.deleter
# from math import pi # class Circle: # def __init__(self,r): # self.r = r # @property # def area(self): # return pi*self.r**2 # @property # def perimeter(self): # 周長 # return 2*pi*self.r # @perimeter.setter # def perimeter(self,新的周長):# self.r = 新的周長 / 2 / pi
setter修改屬性值
# setter裝飾的函式名叫什麼 perimeter
# 那麼在這個函式中絕對不可以對這個函式名同名的屬性進行修改
# 程式的邏輯問題 # 1. 不可以對某些計算結果直接賦值 # 2. 一般是通過對計算結果產生影響的屬性進行重新賦值 # 比如說對於圓這個例子 : 不能直接修改面積或者周長,應該通過修改半徑來帶動對應周長和麵積的改變
# 反射(不得不用) # 使用字串的方式,操作物件的屬性(物件屬性,類的動態屬性(方法)) # 在python中 一切皆物件(類也是物件,物件也是物件,模組也是物件)# a.b # a就是一個物件 # b本質上是一個變數名,也可以說是a的一個屬性 # 如果b是b 那麼就用a.b # 如果b是'b' 那麼就用getattr(a,'b')
二.面向物件的基礎
三大特性
基礎的繼承
基礎的封裝 __私有
兩個內建函式:issubclass isinstance
反射: setattr/delattr 瞭解
內建方法: 你沒有應用場景
__new__
__call__
__str__/__repr__
__len__
__***item__系列
__hash__
__eq__
issubclass(子類,父類),如果真的有繼承關係,就返回True
class A(object):pass class B(A):pass print(issubclass(B,A))
# isinstance(物件,類) # class A(object):pass # a = A() # print(isinstance(a,A))
# # 繼承
# class A(object):pass
# class B(A):pass
# b = B()
# print(isinstance(b,A)) # 檢測的物件是不是某個類以及其父類的物件
# print(type(b) is B) # 檢測的是物件是不是某一個類的例項
# print(type(b) is A)
所有的反射 都是用字串 操作物件的屬性
class A: def __init__(self,name,age): self.name = name self.age = age a = A('alex',83) # hasattr # print(getattr(a,'name'))#alex # a.sex = '不詳' # setattr(a,'sex','不詳') # print(a.sex)#不詳 del a.age # delattr(a,'age') print(a.__dict__)#{'name': 'alex', 'sex': '不詳'}
# 關於內建方法的名字 # 內建方法 雙下方法 魔術方法 # 內建方法的特點 # 一定有某一個語法或者一種寫法自動觸發這個方法
# 重點掌握的 # 哪些寫法 觸發 對應的內建方法 # 例項化 __new__\__init__ 構造方法(單例模式)\初始化方法 # 物件() __call__ # del 物件 __del__ 析構方法\物件刪除之前的收尾工作 # print(物件) __str__ 讓一個物件的顯示更加清晰 # str(物件) # '%s'%物件 # repr() __repr__ 是__str__的備胎,並且還和repr(),%r格式化有關係 # '%r'%物件 # len(物件) __len__ # 物件[引數] item系列 # == __eq__
__call__ 物件用call方法可以呼叫函式__call__裡的方法
# __call__ class Student(): def __init__(self,name,age): self.name = name self.age = age def call(self):pass def __call__(self, *args, **kwargs): print('呼叫我啦') alex = Student('alex',83) # callable #檢視某個變數能否被呼叫 # callable(變數) #返回True,那麼 變數() --> 呼叫 print(callable(Student))#True print(callable(alex))#True # alex() alex.call()#呼叫我啦
class Dog(object): def __new__(cls, *args, **kwargs): pass dog_obj = object.__new__(cls)#呼叫父類object的__new__內建方法 dog_obj = super().__new__(cls)##呼叫父類object的__new__內建方法,第二種方法 return dog_obj def __init__(self,name,age): self.name = name self.age = age wc = Dog('旺財',2) print(wc.name)
# 一個類 只能例項化一次的方法 class Teacher: flag = None def __new__(cls, *args, **kwargs): if cls.flag is None: cls.flag = object.__new__(cls) # 這一句話只能走一次 return cls.flag def __init__(self,name): self.name = name alex1 = Teacher('alex') alex2 = Teacher('alex') yuan = Teacher('yuan') print(alex2.name)#yuan print(yuan.name)#yuan
__del__
# 析構方法(瞭解) 刪除 class Teacher: def __init__(self,name): self.name = name def __del__(self): print('執行我啦') alex = Teacher('ALEX') del alex print('hahaha')
# del alex # 執行del 物件的時候 觸發__del__,在真正的刪除alex物件之前,執行的方法__del__ # 如果我們自己不刪除alex,那麼在程式的執行過程中或者最後,垃圾回收機制會替你執行del alex # 1.del alex # 2.執行__del__ # 3.刪除alex
class File(object): def __init__(self,file_name): self.f = open('file_name') def read(self): self.f.read(1024) def __del__(self):# 物件使用的一些作業系統的資源的歸還工作/收尾工作 self.f.close()
__str__
class Course: def __init__(self,name,price,period,teacher): self.name = name self.price = price self.period = period self.teacher = teacher def __str__(self): # 必須有返回值,必須返回一個str型別 return '%s,%s,%s,%s'%(self.name,self.price,self.period,self.teacher) course_lst = [] python = Course('python',19800,'6 months','baoyuan') linux = Course('linux',16800,'5 months','oldboy') print(python) print(str(python)) print('課程展示 : %s'%python)
class Course: def __init__(self,name,price,period,teacher): self.name = name self.price = price self.period = period self.teacher = teacher def __str__(self): # 必須有返回值,必須返回一個str型別 return '%s,%s,%s,%s'%(self.name,self.price,self.period,self.teacher) course_lst = [] python = Course('python',19800,'6 months','baoyuan') linux = Course('linux',16800,'5 months','oldboy') print(python) print(str(python)) print('課程展示 : %s'%python)
# list.__str__() l = [1,2,3,4] # 物件 列表的物件 print(l) print('[%s,%s,%s]'%(l[0],l[1],l[2]))
__repr__ 是str方法的備胎(有str呼叫str,沒有str走repr)
class Course: def __init__(self,name,price,period,teacher): self.name = name self.price = price self.period = period self.teacher = teacher def __repr__(self): # 必須有返回值,必須返回一個str型別 return 'repr --> : %s,%s,%s,%s'%(self.name,self.price,self.period,self.teacher) def __str__(self): # 必須有返回值,必須返回一個str型別 return 'str --> : %s,%s,%s,%s'%(self.name,self.price,self.period,self.teacher) python = Course('python',19800,'6 months','baoyuan') linux = Course('linux',16800,'5 months','oldboy') print(python) print(linux)
class Course: def __init__(self,name,price,period,teacher): self.name = name self.price = price self.period = period self.teacher = teacher def __repr__(self): # 必須有返回值,必須返回一個str型別 return 'repr --> : %s,%s,%s,%s'%(self.name,self.price,self.period,self.teacher) def __str__(self): # 必須有返回值,必須返回一個str型別 return 'str --> : %s,%s,%s,%s'%(self.name,self.price,self.period,self.teacher) python = Course('python',19800,'6 months','baoyuan') linux = Course('linux',16800,'5 months','oldboy') print('%r'%python)#repr --> : python,19800,6 months,baoyuan print('%s'%python)#str --> : python,19800,6 months,baoyuan print(str(python))#str --> : python,19800,6 months,baoyuan print(repr(python))#repr --> : python,19800,6 months,baoyuan
# 流暢的python : repr和str 如果只能寫一個的 寫repr
class Course: def __init__(self,name,price,period,teacher): self.name = name self.price = price self.period = period self.teacher = teacher def __len__(self): return len(self.__dict__) def __getitem__(self,item): return self.__dict__[item] def __setitem__(self, key, value): self.__dict__[key] = value def __delitem__(self, key): self.__dict__.pop(key) python = Course('python',19800,'6 months','baoyuan') print(len(python)) print(python.name) print(python['name']) # ==> 呼叫getitem print(python['price']) # ==> 呼叫getitem python['name'] = 'python2.0' print(python.name) # del python.name#與下一句功能一樣 del python['name'] print(python.__dict__)#{'price': 19800, 'period': '6 months', 'teacher': 'baoyuan'} # 有一些內建的函式/模組 要想能正確的使用它們 那麼必須按照它規定的語法來實現
__len__ 測量物件長度
class Ruler: def __init__(self,price,length,jingdu): self.length = length self.price = price self.jingdu = jingdu def __len__(self): return self.length stu_ruler = Ruler(2.5,15,0.1) print(len(stu_ruler))#15
__eq__ s1==s2 等於 s1.__eq__(s2)
class Student(): def __init__(self,name,age): self.name = name self.age = age def __eq__(self, other): if self.name == other.name and self.age == other.age: return True return False s1 = Student('賈衛東',20) s2 = Student('賈衛東',20) print(s1 == s2) # s1.__eq__(s2)#True print(s1 is s2) # s1.__eq__(s2)#False
#夠通過這個字串 --> 程式中的變數名(類名\函式名\變數名\方法名\物件名)
class Manager:pass class Student:pass class Teacher:pass identify = 'Student' print(eval(identify)())#<__main__.Student object at 0x00000000025657B8>
反射 hasattr getattr
class Person: role = '人類' Country = '中國' attr = input('>>>') # role 人類 # # Country 中國 print(getattr(Person,'role')) print(getattr(Person,'Country')) if hasattr(Person,attr): print(getattr(Person,attr)) if attr == 'role': print(Person.role) elif attr == 'Country': print(Person.Country)
class Person: role = '人類' @staticmethod def show_courses(): print('所有課程')
# 反射類中的方法 # class Person: # role = '人類' # @staticmethod # def show_courses(): # print('所有課程') # Person.role == getattr(Person,'role') # Person.show_courses() == getattr(Person,'show_courses')() # ret = getattr(Person,'show_courses') # ret()
# 有一個類,有很多靜態屬性,也有很多靜態方法/類方法 # 使用者輸入input任意的屬性名或者方法名, # 如果是屬性 直接列印 - 用到一個內建函式#getattr(Person,'role') # 如果是方法 直接呼叫 - 用到一個內建函式#getattr(Person,'show_courses') # 要求程式不報錯