--- title: Python OOP tags: python, class, object --- [TOC] --- ## Class and Object ### Basic Class Prototype ```python= class ClassName(object): def __init__(self, args): # Initialize data members self.public_data # No underline self._protected_data # Single underline self.__private_data # Double underline def __del__(self): # Destructor pass def func(self): # Define member function pass def __private_func(self): pass ``` 1. Class 一般名稱開頭會大寫 2. Class 的每個member function第一個參數一定要是self - self 指的就是該類別本身 - 在class內部存取自己的data member都要透過self 3. `__init__` 相當於建構元,用於初始化data member - 在Python建立物件的流程,事實上是,`__new__ -> __init__` 4. `__del__` 相當於解構元(我還沒用過) 5. 關於`public、protected、private` - Python 並沒有實作太多這樣的存取機制(protected 不常見到,一般最多就publice、private) - Default 都是public - 若要private,前面加雙底線 6. `class ClassName(object):` 可以寫成 `class ClassName:` - 後面繼承會談到 ```python= def getGender(self): return self.gender class Person: """ This is Person class description """ def __init__(self, name, gender, age=18): self.name = name self.gender = gender self.__age = age # 提供我知道的一些方法 def showName(self): print(self.name) getAge = lambda self : self.__age getGender = getGender Mary = Person('Mary', 'woman', 20) # Class 往下如果是一個多行註解,它會變成該class的說明文字 # 也可以在help(Person)、help(Mary)查看該說明內容 print(Person.__doc__, Mary.__doc__) # 示範使用member function Mary.showName() print(Mary.getGender(), Mary.getAge()) # Raise AttributeError print(Mary.__age) ``` ### Inheritance #### Concept 在Python中,每個東西都是物件,在這樣的前提下,它們都有同一個根源,叫做「Object」,每一個物件都是繼承該類別而來,包括我們自定義的類別。 #### Simple Syntax Intro ```python= # Single Inheritance class SuperClass: pass class SubClass(SuperClass): def __init__(self, args) # 兩種方式呼叫父類別建構元 super().__init__(args) SuperClass.__init__(self, args) # Multiple Inheritance class SubClass(Class1, Class2, ...): pass ``` ### Polymorphism ### Opeartor Overloading ![](http://1.bp.blogspot.com/-FnIuZ0OPYk8/VcJSm4w254I/AAAAAAAAIpA/Y6_3b2r53TA/s1600/operator_overloading.PNG) - `int() <=> __int__(self)` - `float() <=> __float__(self)` - `str() <=> __str__(self)` - `[index] <=> __getitem__(self, index)` - `in <=> __contains__(self, other)` - `len <=> __len__(self)` ```python= # Inheritance、Operator Overloading、Override # 題目為用現成的PriorityQueue實作Reverse import queue # 該Class用來封裝資料,目的是要使用自定義的比大小方式 # 藉此達到Reverse class Wrapper(): def __init__(self, data): self.data = data getValue = lambda self : self.data # >= def __ge__(self, other): if isinstance(other, Wrapper): return not self.data >= other.data else: raise TypeError # > def __gt__(self, other): if isinstance(other, Wrapper): return not self.data > other.data else: raise TypeError # <= def __le__(self, other): if isinstance(other, Wrapper): return not self.data <= other.data else: raise TypeError # < def __lt__(self, other): if isinstance(other, Wrapper): return not self.data < other.data else: raise TypeError # == def __eq__(self, other): if isinstance(other, Wrapper): return self.data == other.data else: raise TypeError # 該class繼承了現有PriorityQueue # 並對put、get兩個function做改寫 # 將送進去儲存的資料用上面的class包裝起來 class MyPriorityQueue(queue.PriorityQueue): def put(self, data): super().put(Wrapper(data)) def get(self): return super().get().getValue() # 測試函式 if __name__ == '__main__': pq = MyPriorityQueue() aList = [5,6,73,1,42,3,9,75] for e in aList: pq.put(e) while True: if not pq.empty(): print(pq.get(), end=' ') else: break ``` 有空用Assert改寫程式 ### Callable Object - 改寫 `__call__` --- ## Note - `self` - Python's self is the same as the this pointer in C++ or Java, but self is always explicit in both headers and bodies of Python methods to make attribute accesses more obvious.