Python入門-Day8:物件導向

閱讀時間約 14 分鐘

類別(Class)

在Python中,我們可以使用class關鍵字來定義一個類別。類別是一種包含相關方法和變數的模板。

以下是一個Python類別的範例,這個類別定義了一個名為Car的類別,並包含一個變數color和一個方法drive:

class Car:
def __init__(self, color):
self.color = color

def drive(self):
print("The " + self.color + " car is driving")

在這個範例中,__init__是一個特殊的方法,稱為類別的建構函數。這個方法在創建類別的實例時會被調用,並將參數color設定為該實例的屬性。

drive方法是我們為Car類別定義的一個方法,這個方法會輸出一條訊息。

我們可以創建一個Car類別的實例,並呼叫其方法,如下所示:

my_car = Car("red")
my_car.drive()

輸出將為:

The red car is driving

繼承(Inheritance)

在Python中,一個類別可以繼承另一個類別的屬性和方法,這種概念被稱為繼承。我們可以使用super()函數來繼承父類別的屬性和方法。

以下是一個繼承的程式碼範例:

class Person:
def __init__(self, fname, lname):
self.firstname = fname
self.lastname = lname

class Student(Person):
pass

x = Student("Mike", "Olsen")
print(x.firstname)
print(x.lastname)

在這個範例中,有兩個類別:PersonStudentPerson 類別是父類別,它有兩個屬性 firstnamelastnameStudent 類別是子類別,它繼承了 Person 類別的所有屬性和方法。

當我們創建 Student 類別的對象 x 時,我們可以使用 Person 類別的屬性。在這個例子中,我們給 x 設定了 firstname 為 "Mike",lastname 為 "Olsen",然後我們可以打印出這兩個屬性。

繼承允許我們重用代碼,因為我們可以使用父類別的屬性和方法,而不需要在每個子類別中重新定義它們。這也使得我們的代碼更易於維護。

多型(Polymorphism)

在Python中,多型意味著我們可以定義具有相同名稱但具有不同實現的方法。多型允許我們在不考慮它們的類型的情況下使用這些方法。

以下是一個多型的程式碼範例:

class Parrot:

def fly(self):
print("Parrot can fly")

def swim(self):
print("Parrot can't swim")

class Penguin:

def fly(self):
print("Penguin can't fly")

def swim(self):
print("Penguin can swim")

def flying_test(bird):
bird.fly()

blu = Parrot()
peggy = Penguin()

flying_test(blu)
flying_test(peggy)

在這個範例中,我們定義了兩個類別:ParrotPenguin。每個類別都有一個 fly 和一個 swim 方法,但它們的實現是不同的。

然後,我們定義了一個名為 flying_test 的函數,它接受一個 bird 參數,並調用該參數的 fly 方法。

最後,我們創建了一個 Parrot 物件 blu 和一個 Penguin 物件 peggy,並將它們傳遞給 flying_test 函數。儘管 blupeggy 是不同類別的物件,但因為它們都有一個 fly 方法,所以我們可以在不知道它們類別的情況下使用這個方法。這就是多型的概念。

封裝(Encapsulation)

在Python中,我們可以將物件的狀態(變數)和行為(方法)封裝在一起。這樣可以保護數據,並防止外部程式直接訪問或修改物件的狀態。

以下是一個封裝的程式碼範例:

class Computer:

def __init__(self):
self.__maxprice = 900

def sell(self):
print("Selling Price: {}".format(self.__maxprice))

def setMaxPrice(self, price):
self.__maxprice = price

c = Computer()
c.sell()

c.__maxprice = 1000
c.sell()

c.setMaxPrice(1000)
c.sell()

在此範例中,我們定義了一個名為 Computer 的類別,並將一個名為 __maxprice 的變數封裝在類別中。我們還定義了兩個方法:sellsetMaxPrice

當我們創建一個 Computer 物件 c 並嘗試改變 __maxprice 變數時,我們會發現我們無法直接訪問或修改此變數。這是因為我們已將 __maxprice 變數封裝在 Computer 類別中,並將其設為私有。

然而,我們可以使用定義在類別中的 setMaxPrice 方法來更改 __maxprice 變數的值。這就是封裝的概念,我們可以將物件的狀態和行為封裝在一起,並通過提供公共方法來訪問和修改這些私有變數,從而保護數據,並防止外部程式直接訪問或修改物件的狀態。

介面(Interface)

Python並不具有專門的介面概念。但我們可以透過建立一個只包含抽象方法的類別來模擬介面的行為。

抽象類別(Abstract Class)

在Python中,抽象類別是一種只能被繼承,不能被實例化的類別。抽象類別可以定義抽象方法,這些方法必須在子類別中實現。

以下是抽象類別的程式碼範例:

from abc import ABC, abstractmethod

class AbstractClassExample(ABC):

@abstractmethod
def do_something(self):
pass

class AnotherSubclass(AbstractClassExample):

def do_something(self):
super().do_something()
print("The subclass is doing something")

x = AnotherSubclass()
x.do_something()

在這個範例中,AbstractClassExample 是一個抽象類別,它有一個抽象方法 do_something。這個抽象方法在 AbstractClassExample 類別中沒有實現,必須在任何繼承 AbstractClassExample 的子類別中實現。在這個例子中,AnotherSubclass 繼承了 AbstractClassExample 並實現了 do_something 方法。然後我們創建了一個 AnotherSubclass 的實例 x,並呼叫了其 do_something 方法。結果將為 "The subclass is doing something"。

靜態類別(Static Class)

Python並沒有靜態類別的概念。但我們可以透過在類別中只使用靜態方法來模擬靜態類別的行為。

列舉(Enumerations)

Python有一個內建的列舉類型 Enum,我們可以用它來創建具有有限數量的值的類別。

以下是一個列舉的程式碼範例:

from enum import Enum

class Color(Enum):
RED = 1
GREEN = 2
BLUE = 3

print(Color.RED)
print(Color.GREEN)
print(Color.BLUE)

在這個範例中,我們定義了一個名為Color的列舉,並給它指定了三個值:REDGREENBLUE。然後我們可以像使用常數一樣使用這些列舉值。當我們列印出這些值時,我們會得到它們的名稱和對應的數值。

列舉是一種用於定義只有固定數量值的類型的有效方式。在Python中,列舉可以提供更清晰的語義並且易於維護。

委派(Delegation)

Python中的委派通常是通過組合或繼承來實現的。

以下是一個「委派」的程式碼範例:

class Printer:
def print_file(self, file):
print("Printing file: " + file)

class User:
def __init__(self):
self.printer = Printer()

def print(self, file):
self.printer.print_file(file)

user = User()
user.print("file.txt")

在這個範例中,我們定義了兩個類別:PrinterUserPrinter 類別有一個 print_file 方法,用於列印檔案。User 類別有一個 print 方法,但這個方法並不直接列印檔案,而是將這個任務「委派」給 Printer 類別的 print_file 方法。這樣,當我們要列印檔案時,我們只需要調用 User 類別的 print 方法即可,而不需要關心列印的具體實現。這就是「委派」的概念,它允許我們將一些特定的任務分配給其他的類別或者方法來執行,從而簡化程式碼並提高可維護性。

Lambda 表達式

Python支持lambda表達式,也稱為匿名函數,允許我們快速定義單行的小函數。

以下是一個Lambda表達式的程式碼範例:

square = lambda x: x ** 2
print(square(5))

在這個範例中,我們定義了一個Lambda表達式,它接收一個參數x,並返回x的平方。然後,我們呼叫這個Lambda表達式,並且將值5傳入,它將返回25。

Lambda表達式是一種快速定義簡單函數的方式,它們通常在需要短暫使用一次的函數或者將函數作為參數傳遞給其他函數的時候非常有用。雖然Lambda表達式功能強大,但它們的使用應該是有限的,因為使用正規的def定義的函數會更具可讀性。

泛型(Generics)

Python並不直接支持泛型,但可通過使用類型提示來模擬泛型行為。

反射(Reflection)

Python有反射功能,可以允許我們在運行時檢視對象的類型和屬性,並且可以調用其方法或修改其屬性。

下面是反射的程式碼範例:

class Person:
def __init__(self, name, age):
self.name = name
self.age = age

def say_hello(self):
print("Hello, my name is " + self.name)

person = Person("John", 30)

# 使用 type() 函數獲取對象的類型
print(type(person))

# 使用 hasattr() 函數檢查對象是否有特定屬性
print(hasattr(person, 'name'))
print(hasattr(person, 'address'))

# 使用 getattr() 函數獲取對象的屬性值
print(getattr(person, 'name'))

# 使用 setattr() 函數設定對象的屬性值
setattr(person, 'name', 'Bob')
print(getattr(person, 'name'))

# 使用 dir() 函數獲取對象的所有屬性和方法
print(dir(person))

# 使用 callable() 函數檢查對象的方法是否可以調用
print(callable(getattr(person, 'say_hello')))

# 調用對象的方法
getattr(person, 'say_hello')()

在這個範例中,我們定義了一個名為Person的類別,並創建了一個對應的實例person。我們使用了type()hasattr()getattr()setattr()dir()callable()等反射函數來檢視和操作對象。

首先,我們使用type()函數來獲取person對象的類型。然後,我們使用hasattr()函數來檢查person對象是否具有nameaddress兩個屬性。接著,我們使用getattr()函數來獲取name屬性的值,並使用setattr()函數來改變name屬性的值。之後,我們使用dir()函數來列出person對象的所有屬性和方法。最後,我們使用callable()函數來檢查say_hello方法是否可以調用,並調用此方法。

這個範例顯示了Python反射的基本用法,通過反射,我們可以在運行時檢視和操作對象,這對於動態語言來說是非常有用的一種能力。

    4會員
    26內容數
    日後將分享關於我的經驗(日常、工作、技術),並期待未來能創造屬於我的宇宙。
    留言0
    查看全部
    發表第一個留言支持創作者!