首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 更多程式設計知識

Python 面向物件:屬性與方法完整教學(公有、私有、類別、靜態)

     編輯:更多程式設計知識

Python 物件導向的核心在於**屬性**(資料)與**方法**(行為)的封裝。本文系統整理:公有/私有屬性、名稱修飾機制、四種方法型別(實例、類別、靜態、私有)、裝飾器語法、存取控制最佳實務與繼承場景應用。

屬性:公有與私有


class People:
    def __init__(self):
        self.name = '張珊'      # 公有屬性
        self.__age = 23         # 私有屬性(雙下劃線開頭)

p = People()
print(p.name)      # 張珊
# print(p.__age)   # AttributeError: 'People' object has no attribute '__age'

# 實際儲存名稱(名稱修飾 Name Mangling)
print(p._People__age)  # 23(_ClassName__attr)
print(p.__dict__)      # {'name': '張珊', '_People__age': 23}

名稱修飾機制

  • 雙下劃線開頭、非雙下劃線結尾的屬性/方法:__attr → _ClassName__attr
  • 單下劃線 _attr:慣例內部使用,不修飾
  • 雙下劃線開頭結尾 __attr__:特殊方法,不修飾
  • 目的:避免子類別意外覆寫,非絕對封裝

私有屬性存取模式


class People:
    def __init__(self, name, age):
        self.name = name
        self.__age = age
    
    # 公有方法存取私有屬性
    def get_age(self):
        return self.__age
    
    def set_age(self, age):
        if 0 < age < 150:
            self.__age = age
        else:
            raise ValueError("Invalid age")
    
    # 唯讀屬性(Pythonic 方式)
    @property
    def age(self):
        return self.__age

p = People("Alice", 25)
print(p.get_age())   # 25
print(p.age)         # 25(屬性存取,無括號)
# p.age = 30         # AttributeError: can't set attribute(無 setter)

四大方法型別完整對照


class People:
    def __init__(self, name):
        self.name = name
        self.__secret = "hidden"
    
    # 1. 實例方法:存取 self(實例屬性)
    def instance_method(self):
        print(f"Instance: {self.name}, secret: {self.__secret}")
    
    # 2. 私有方法:內部使用,名稱修飾
    def __private_method(self):
        print("Private method called")
    
    def public_caller(self):
        self.__private_method()  # 內部可呼叫
    
    # 3. 類別方法:存取 cls(類別屬性)、可被繼承覆寫
    @classmethod
    def class_method(cls):
        print(f"Class method of {cls.__name__}")
    
    # 4. 靜態方法:無 self/cls,邏輯歸屬類別
    @staticmethod
    def static_method():
        print("Static method: utility function")

# 使用
p = People("Bob")
p.instance_method()      # Instance: Bob, secret: hidden
p.public_caller()        # Private method called
People.class_method()    # Class method of People
People.static_method()   # Static method: utility function

# 實例也可呼叫類別/靜態方法
p.class_method()
p.static_method()

方法型別詳細對照表

型別裝飾器第一參數存取呼叫方式典型用途
實例方法無self實例/類別屬性obj.method()操作實例狀態
私有方法無(命名__)self實例/類別屬性self.__method()內部實現細節
類別方法@classmethodcls類別屬性Class.method() / obj.method()替代建構子、類別狀態
靜態方法@staticmethod無無(傳入參數)Class.method() / obj.method()工具函式、邏輯分組

類別方法實戰:替代建構子


class Date:
    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day
    
    @classmethod
    def from_string(cls, date_str):
        """從 'YYYY-MM-DD' 建立實例"""
        year, month, day = map(int, date_str.split('-'))
        return cls(year, month, day)
    
    @classmethod
    def today(cls):
        """建立今天日期實例"""
        import datetime
        today = datetime.date.today()
        return cls(today.year, today.month, today.day)
    
    def __str__(self):
        return f"{self.year}-{self.month:02d}-{self.day:02d}"

d1 = Date(2024, 1, 15)
d2 = Date.from_string("2024-12-25")
d3 = Date.today()
print(d1, d2, d3)

靜態方法實戰:工具函式分組


class MathUtils:
    @staticmethod
    def is_prime(n):
        if n < 2:
            return False
        for i in range(2, int(n**0.5)+1):
            if n % i == 0:
                return False
        return True
    
    @staticmethod
    def gcd(a, b):
        while b:
            a, b = b, a % b
        return a

print(MathUtils.is_prime(17))  # True
print(MathUtils.gcd(48, 18))   # 6

繼承與方法覆寫


class Animal:
    def __init__(self, name):
        self.name = name
    
    def speak(self):
        print(f"{self.name} makes a sound")
    
    @classmethod
    def species(cls):
        return cls.__name__

class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name)  # 呼叫父類別 __init__
        self.breed = breed
    
    def speak(self):  # 覆寫
        print(f"{self.name} barks!")

class Cat(Animal):
    def speak(self):
        print(f"{self.name} meows~")

animals = [Dog("Buddy", "Golden"), Cat("Whiskers")]
for a in animals:
    a.speak()  # 多態:Buddy barks! / Whiskers meows~
    print(f"Species: {a.species()}")  # 類別方法繼承

super() 進階用法


class Base:
    def __init__(self, x):
        self.x = x
        print(f"Base init: {x}")

class Derived(Base):
    def __init__(self, x, y):
        super().__init__(x)  # Python 3 簡潔語法
        self.y = y
        print(f"Derived init: {y}")

# 多重繼承 MRO
class A:
    def method(self):
        print("A")

class B(A):
    def method(self):
        super().method()
        print("B")

class C(A):
    def method(self):
        super().method()
        print("C")

class D(B, C):
    def method(self):
        super().method()
        print("D")

D().method()
# A -> C -> B -> D (MRO 順序)
print(D.__mro__)

最佳實務總結

  1. 預設公有:Python 以慣例而非強制封裝,`_attr 表內部使用。
  2. 私有屬性用 `@property`**:提供受控存取,比 getter/setter 更 Pythonic。
  3. 類別方法用於替代建構子:from_string、today 等。
  4. 靜態方法用於無狀態工具函式:邏輯歸屬類別命名空間。
  5. 繼承必呼叫 super().__init__()**:確保父類別正確初始化。
  6. 避免濫用私有雙下劃線:增加測試、序列化、子類別擴充困難。

總結

Python 屬性與方法機制靈活強大:**公有預設、私有慣例/名稱修飾、四種方法型別分工明確**。掌握 @property 封裝存取、@classmethod 替代建構子、@staticmethod 工具分組、super() 協同初始化,能寫出清晰、可擴充、符合 Python 慣用語的物件導向代碼。記住:**Python 信任開發者,封裝靠慣例與文件,而非語法強制**。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved