python學習筆記(12):高階面向物件
阿新 • • 發佈:2018-12-30
一、__slots__和property
1.__slots__魔術函式動態的新增方法和屬性
2.直接暴露屬性的侷限性
3.使用get/set方法
4.利用@property簡化get/set方法
5.利用@property實現只讀屬性
6.裝飾器與property實現
# import traceback # from types import MethodType # # class MyClass(object): # # pass # #在做新的類的時候,限制動態新增的屬性,這個時候需要用到__slots__魔術變數,系統內為了實現某些特定功能的 # __slots__= ['name','set_name'] # 這個地方,能新增的屬性和方法就會受到限制,只能新增name或者set_name這兩個名詞的屬性或者方法 # def set_name(self,name): # self.name = name # cls = MyClass() #例項化類 # cls.name='Tom' #動態的新增屬性 # cls.set_name=MethodType(set_name,cls) #動態的新增方法 將set_name作用於cls上面 # cls.set_name('Jerry') # print(cls.name) # try: # cls.age=30 #動態新增屬性 ,這個地方要注意,age不在__slots__規定的陣列中,所以會報錯 # except AttributeError: # traceback.print_exc() #打印出異常資訊 AttributeError: 'MyClass' object has no attribute 'age' # # class ExtMyClass(MyClass): #繼承自MyClass # pass # ext_cls = ExtMyClass() # ext_cls.age=30 # print(ext_cls.age)
2.property
import traceback class Student: @property # 這個地方用裝飾器進行修飾的時候,實際上是生成了一個新的物件,名字叫做score,這個相當於set函式 def score(self): return self._score @score.setter def score(self,value): if not isinstance(value,int): #進行value的型別檢查,如果不是int型的值,就會報錯not int raise ValueError('not int') elif (value<0) or (value>100): #如果value只不是在這個區間之間的話,就會報錯值不在0~100之間,這個地方相當於get函式 raise ValueError('not between 0 ~ 100') self._score=value @property #注意,這裡沒有set方法,所以只能讀取,不能寫 def double_score(self): return self._score*2 s= Student() s.score=75 print(s.score) print(s.double_score) try: s.double_score=150 except AttributeError: traceback.print_exc() try: s.score='abc' except ValueError: traceback.print_exc() try: s.score=101 except ValueError: traceback.print_exc()
3.列舉類
from enum import Enum Month = Enum('Month',('Jan','Feb','Mar','Apr')) for name,member in Month.__members__.items(): print(name,'=>',member,',',member.value) jan = Month.Jan print(jan)
二、元類
1.執行時動態建立 vs 編譯時定義
def init(self,name): #自定義建構函式, self.name=name def say_hello(self): #自定義成員函式 print('hello, %s!' %self.name) Hello = type('Hello',(object, ),dict(__init__ = init,hello=say_hello)) #(object, )是一個基類的列表 """ 這個地方的程式碼等價於下面的這些程式碼: class Hello: def __init__(.......) def hello(..........) """ h = Hello('Tom') h.hello()
2.使用type建立新型別
3.metaclass(元類)
(1)metaclass -> class -> instance
(2)繼承和動態繫結可以解決問題嗎?
(3)__new__函式
class ListMetaclass(type): def __new__(cls,name,bases,attrs): # print(cls) #打印出傳進來的類時什麼 # print(name) #打印出傳進來的name是什麼 # print(bases) #打印出傳入進來的基類是什麼 基類是list類 attrs['add'] = lambda self,value:self.append(value) return type.__new__(cls,name,bases,attrs) class MyList(list,metaclass=ListMetaclass): #從list類繼承下來,就是一個數組,但是額外的增加add方法,實際等價於append pass mli = MyList() mli.add(1) mli.add(2) mli.add(3) print(mli)
三、ORM框架例項(重點的重點)