class 類別

建立類別

在類別中的「變數」,稱為「屬性」或「成員變數」。

語法:

class 類別名:
	變數
	函式
1
2
3
4
class Cat:
    name = None
    age = None
    color = None

None是沒有值。
None介紹:https://docs.python.org/zh-tw/3.12/library/constants.html#None
None相當於Java null, C++ nullptr 或是 0

建立物件

物件變數 = 類別()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Cat:
    name = None
    age = None
    color = None

cat1 = Cat()
cat1.name = "小白"
cat1.age = 1
cat1.color = "while"
print(f"cat1 name: {cat1.name}, age: {cat1.age}, color: {cat1.color}")
cat2 = Cat()
cat2.name = "小黑"
cat2.age = 5
cat2.color = "black"
print(f"cat2 name: {cat2.name}, age: {cat2.age}, color: {cat2.color}")
cat1 name: 小白, age: 1, color: while
cat2 name: 小黑, age: 2, color: black

方法

在類別中的「函式」,稱為「方法」。

  • 方法的第一個參數要寫上self。
  • 呼叫方法時,不用傳第一個參數self。
  • 呼叫方法時,底層會偷偷把「呼叫方法的物件」傳入第一個參數self。
  • 在方法內部,需要使用self.成員變數,才能存取成員變數。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Cat:
    name = None
    age = None
    color = None
    # 方法的第一個參數要寫上self
    def getInfo(self):
        # 在方法內部,需要使用self.成員變數,才能存取成員變數
        print(f"name = {self.name}, age = {self.age}, color = {self.color}")

cat1 = Cat()
cat1.name = "小白"
cat1.age = 1
cat1.color = "while"
# 呼叫方法時,不用傳第一個參數self。
# 底層會偷偷把「呼叫方法的物件」傳入第一個參數self
cat1.getInfo()

cat2 = Cat()
cat2.name = "小黑"
cat2.age = 5
cat2.color = "black"
cat2.getInfo()
name = 小白, age = 1, color = while
name = 小黑, age = 5, color = black

動態增加屬性

以下程式碼,只有針對cat1才新增owner屬性,不是每個Cat物件都有owner,只特定針對cat1物件才有。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Cat:
    name = None
    age = None
    color = None
    def getInfo(self):
        print(f"name = {self.name}, age = {self.age}, color = {self.color}")

cat1 = Cat()
cat1.name = "小白"
cat1.age = 1
cat1.color = "while"
cat1.getInfo()
# 動態增加owner屬性
cat1.owner = "Mary"
print("cat1 owner =", cat1.owner)
name = 小白, age = 1, color = while
cat1 owner = Mary

cat2試圖取出owner屬性,會產生AttributeError

1
2
3
4
5
6
cat2 = Cat()
cat2.name = "小黑"
cat2.age = 5
cat2.color = "black"
cat2.getInfo()
print("cat2 owner =", cat2.owner)
    print("cat2 owner =", cat2.owner)
                          ^^^^^^^^^^
AttributeError: 'Cat' object has no attribute 'owner'
name = 小黑, age = 5, color = black

動態增加方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Cat:
    name = None
    age = None
    color = None
    def getInfo(self):
        print(f"name = {self.name}, age = {self.age}, color = {self.color}")

# jump()函式 準備給cat1動態增加方法
def jump():
    print("jump")

cat1 = Cat()
cat1.name = "小白"
cat1.age = 1
cat1.color = "while"
cat1.getInfo()
cat1.owner = "Mary"
print("cat1 owner =", cat1.owner)
# 動態增加method1()方法,指派jump給method1,注意,不用有圓括號在函式名後面
cat1.method1 = jump
# 呼叫動態增加method1方法
cat1.method1()
name = 小白, age = 1, color = while
cat1 owner = Mary
jump

method1()方法只針對cat1物件才有,cat2沒有method1()方法。

1
2
cat2 = Cat()
cat2.method1()
    cat2.method1()
    ^^^^^^^^^^^^
AttributeError: 'Cat' object has no attribute 'method1'

動態增加方法類型

動態增加方法的類型為 function ,Cat 類別中的 getInfo() 方法的類型為 method

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Cat:
    name = None
    age = None
    color = None
    def getInfo(self):
        print(f"name = {self.name}, age = {self.age}, color = {self.color}")

def jump():
    print("jump")

cat1 = Cat()
cat1.name = "小白"
cat1.age = 1
cat1.color = "while"
cat1.method1 = jump
print("type(jump) = ", type(jump))
print("type(cat1.method1) = ", type(cat1.method1))
print("type(cat1.getInfo) = ", type(cat1.getInfo))
type(jump) =  <class 'function'>
type(cat1.method1) =  <class 'function'>
type(cat1.getInfo) =  <class 'method'>

方法參數

getInfo()方法參數 name ,是區域變數。
類別中的name是成員變數,二者是不同。
方法參數 name 與 成員變數 name 相同名字,但方法參數 name 不會「自動」覆蓋成員變數 name。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Cat:
    name = None
    age = None
    color = None

    def getInfo(self, name):
        print("name = ", name)
        print("self.name = ", self.name)

cat1 = Cat()
cat1.name = "小白"
cat1.age = 1
cat1.color = "while"
cat1.getInfo("小黃")
name =  小黃
self.name =  小白

需要使用self.成員變數 = 方法參數,才會修改成員變數的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Cat:
    name = None
    age = None
    color = None
    def getInfo(self, name):
        self.name = name

cat1 = Cat()
cat1.name = "小白"
cat1.age = 1
cat1.color = "while"
cat1.getInfo("小黃")
print(f"name = {cat1.name}")
name = 小黃

self

是誰呼叫方法,那個「誰」,就是self。
以下程式碼,cat1 呼叫 getInfo() 方法,self就是cat1。
id(cat1) 的記憶體位址與 id(self)的記憶體位址一模一樣。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Cat:
    name = None
    age = None

    def getInfo(self):
        print("getInfo: id =", id(self))


cat1 = Cat()
print("cat1 id = ", id(cat1))
cat1.getInfo()

cat2 = Cat()
print("cat2 id = ", id(cat2))
cat2.getInfo()
cat1 id =  4501008608
getInfo: id = 4501008608
cat2 id =  4501008656
getInfo: id = 4501008656

呼叫成員方法與成員變數

在類別內呼叫成員變數與成員方法:。

self.成員變數
self.成員方法()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Cat:
    name = None
    age = None

    def getInfo(self):
        print(f" {self.eat()} age = {self.age}")

    def eat(self):
        return f"{self.name} eat"


cat1 = Cat()
cat1.name = "小白"
cat1.age = 5
cat1.getInfo()
 小白 eat age = 5

若前面沒有self,會編譯錯誤。

1
2
3
4
5
6
7
8
9
10
class Cat:
    name = None
    age = None

    def getInfo(self):
        # eat() age 前面都沒有self
        print(f" {eat()} age = {age}")

    def eat(self):
        return f"{self.name} eat"

compare_to

可以根據self的特性,寫一個compare_to的方法。
self就是呼叫compare_to()方法的物件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Cat:
    name = None
    age = None

    def compare_to(self, other):
        return self.name == other.name and self.age == other.age

cat1 = Cat()
cat1.name = "小白"
cat1.age = 5

cat2 = Cat()
cat2.name = "小黑"
cat2.age = 5

print(cat1.compare_to(cat2))
False

類別中的區域變數與全域變數

方法的參數以及方法宣告的變數,都是區域變數,區域變數有效範圍只有在方法之中,離開方法就無效。
成員變數就是全域變數,在整個類別的所有方法都可以訪問。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Cat:
    # name 與 age 是全域變數,所有方法都可以訪問
    name = None
    age = None

    # param1, param2 為區域變數,只限定在func1()方法可以使用
    def func1(self, param1, param2):
        # 可以使用name age
        print(param1, param2, self.name, self.age)

    def func2(self):
        # 無法讀取param1、param2
        print(param1, param2)
        # 可以使用name age
        print(self.name, self.age)

在類別中,使用self.成員變數是全域變數,沒有self,就是區域變數。

靜態方法

靜態方法宣告:

    @staticmethod
    def 靜態方法名(參數1, 參數2, 參數3):
        程式碼
  • 靜態方法上面加上@staticmethod
  • 靜態方法的第一個參數不用有self
  • 參數可以有0至多個。

呼叫方式:

類別名.靜態方法()
物件.靜態方法()
1
2
3
4
5
6
7
8
9
10
class Cat:
    name = None
    age = None
    @staticmethod
    def hi(param1,param2):
        print(param1,param2)

Cat.hi("Hello","World")
cat1 = Cat()
cat1.hi("Hi","Thank")
Hello World
Hi Thank

靜態方法無法使用成員變數,以下程式碼編譯錯誤。

1
2
3
4
5
6
7
class Cat:
    name = None
    age = None
    @staticmethod
    def hi():
        # 無法使用self.name成員變數
        print(self.name)

results matching ""

    No results matching ""