---
# System prepended metadata

title: Python OOP
tags: [' object', python, ' class']

---

---
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.