Python 物件導向程式設計

Hans_Wang 發表於 2021-12-04
Python 物件導向

Python 物件導向程式設計

image

1 程式導向程式設計

程式導向——Procedure Oriented,是一種以過程為中心的程式設計思想,它首先分析出解決問題所需要的步驟,然後用函式把這些步驟一步一步實現,在使用時依次呼叫,是一種基礎的順序的思維方式。程式導向開發方式是對計算機底層結構的一層抽象,它將程式分為資料和操縱資料的操作兩部分,其核心問題是資料結構和演算法的開發和優化。

最典型的就是流水線,上一道工序完成後,後面的流程才能進行。

  • 面過程程式設計的特點:

    功能模組化,程式碼流程化

  • 優點:

    效能高,適合資源緊張、實時性強的場合

  • 缺點:

    不易複用和不易擴充套件

2 物件導向程式設計

物件導向程式設計——Object Oriented Programming,簡稱OOP,是一種程式設計思想。OOP把物件作為程式的基本單元,一個物件包含了資料和運算元據的函式。

物件導向的程式設計把計算機程式視為一組物件的集合,而每個物件都可以接收其他物件發過來的訊息,並處理這些訊息,計算機程式的執行就是一系列訊息在各個物件之間傳遞。

在Python中,所有資料型別都可以視為物件,當然也可以自定義物件。自定義的物件資料型別就是物件導向中的類(Class)的概念。

3. 程式導向和麵向物件的優缺點

物件導向 程式導向
特性 抽象、繼承、封裝、多型 功能模組化,程式碼流程化
優點 易維護、易複用、易擴充套件、低耦合 效能高,適合資源緊張、實時性強的場合
缺點 效能比程式導向低 沒有物件導向易維護、易複用、易擴充套件

4. 由淺入深瞭解物件導向

4.1 學生選課為例

"""
1, 要定義學生的資訊: 姓名,性別,年齡,學校,所選課程
"""
# 學生的特徵:
student_name = 'Hans'
student_gender = 'M'
student_age = 20
shool = '社會大學'
student_course = []

# 學生的功能:選課
def course_selection_system(name, gender, age, shool, course):
    student_course.append(course)
    print("學生:%s 性別:%s 年齡:%s 在%s 期間所選課程:%s" % (name, gender, age, shool, student_course))
# 執行結果:
course_selection_system(student_name, student_gender, student_age, shool, "如何接受社會的毒打")
學生:Hans 性別:M 年齡:20 在社會大學 期間所選課程:['如何接受社會的毒打']


"""
2, 把學生的資訊定義成一個字典
"""
student1 = {
    'student_name': 'Hans',
    'student_gender': 'M',
    'student_age': 20,
    'shool':'社會大學',
    'student_course':[]
}

def course_selection_system(student, course):
    student1['student_course'].append(course)
    print("學生:%s 性別:%s 年齡:%s 在%s 期間所選課程:%s" % (student['student_name'], student['student_gender'], \
                                               student['student_age'], student['shool'], student['student_course']))
#執行結果:
course_selection_system(student1, "如何接受社會的毒打")
學生:Hans 性別:M 年齡:20 在社會大學 期間所選課程:['如何接受社會的毒打']

"""
3, 把選課的函式放到字典裡, 某個學生要選課成功,裡面要包括他的特徵和技能,
這樣一個學生他的特徵和功能都有了
"""

def course_selection_system(student, course):
    student1['student_course'].append(course)
    print("學生:%s 性別:%s 年齡:%s 在%s 期間所選課程:%s" % (student['student_name'], student['student_gender'], \
                                               student['student_age'], student['shool'], student['student_course']))

student1 = {
    'student_name': 'Hans',
    'student_gender': 'M',
    'student_age': 20,
    'shool':'社會大學',
    'student_course':[],
    'course_select':course_selection_system
}

student2 = {
    'student_name': 'Jack',
    'student_gender': 'M',
    'student_age': 20,
    'shool':'社會大學',
    'student_course':[],
    'course_select':course_selection_system
}
student1['course_select'](student1, "五塊錢如何花一星期")
student2['course_select'](student2, "如何接受社會的毒打")
#執行結果:
學生:Hans 性別:M 年齡:20 在社會大學 期間所選課程:['五塊錢如何花一星期']
學生:Jack 性別:M 年齡:20 在社會大學 期間所選課程:['如何接受社會的毒打'
                
# 這是一兩個學生,如果是十個,百個或更多都要手寫一遍???
# 這時就需要物件導向了。
"""
物件是什麼
	1. 程式中:
        	函式:盛放資料的容器
            物件:盛放資料和函式的容器
	2. 現實生活中:
        	一切皆物件
            物件:特徵與技能的結合體
"""

4.2 類和物件

"""
物件: 特徵與技能的結合體
類:一系列物件相似的特徵與相似的技能的結合體

站在不同的分類,劃分的分類不一定一樣

在程式中先有類再有物件。現實中先有物件,再有類
"""
# 把上面的程式 相同的部分拿出來,
student1 = {
    'student_name': 'Hans',
    'student_gender': 'M',
    'student_age': 20,
    'shool':'社會大學',
    'student_course':[],
    'course_select':course_selection_system
}

student2 = {
    'student_name': 'Jack',
    'student_gender': 'M',
    'student_age': 20,
    'shool':'社會大學',
    'student_course':[],
    'course_select':course_selection_system
}
"""
這個程式中有哪些是相同的:
學校(shool)和選課功能(course_selection_system)
可以把這兩個功能提取出來
"""

student_public = {
    'shool':'社會大學',
    'course_select':course_selection_system
}
# 這個提取出來的公共的功能就是類,但在python中寫有專業的寫法:
class 類名():
    pass

# class為關鍵字 
# 類名一般首字母大寫
# 程式碼:
class student_public():
    shool =  '社會大學'

    def course_selection_system(student, course):
        student1['student_course'].append(course)
        print("學生:%s 性別:%s 年齡:%s 在%s 期間所選課程:%s" % (student['student_name'], student['student_gender'], \
                                                   student['student_age'], student['shool'], student['student_course']))

# 類在定義的時候會執行,這是與函式不同的地方(函式在定義時不會執行,只有在呼叫時執行)
# 檢視類的名稱空間:
print(student_public.__dict__)
{'__module__': '__main__', 'shool': '社會大學', 'course_selection_system': <function student_public.course_selection_system at 0x000002ADBB6AA5F0>, '__dict__': <attribute '__dict__' of 'student_public' objects>, '__weakref__': <attribute '__weakref__' of 'student_public' objects>, '__doc__': None}

# 類的底層為字典
"""
類在定義時做了哪些:
	1. 類在定義時會立即執行
	2. 產生一個類的名稱空間,然後把類體裡執行的資料都放到名稱空間裡(__dict__返回的字典裡)
	3. 把類的名稱空間繫結給__dict__
	
變數放到類裡面叫屬性
函式放到類裡面叫方法
"""

# 呼叫類
stu = student_public()
# 呼叫類從而產生物件。
# 呼叫類從而產生物件的過程,叫類的初始化

#檢視物件的名稱空間
print(stu.__dict__)
# 執行結果:
{}  # 一個空字典

# 現在用Python的語法把類定義出來了。
# 但是學生自己獨有的特徵還沒有(自己的名字,自己的年齡等等),剛才看到了為空
# 給物件新增自己獨有的特徵
stu.__dict__['name'] = 'Hans'
stu.__dict__['gender'] = 'M'
stu.__dict__['age'] = 20
stu.__dict__['course'] = ['五塊錢如何花一星期','如何接受社會毒打']

print(stu.__dict__)
# 執行結果:
{'name': 'Hans', 'gender': 'M', 'age': 20, 'course': ['五塊錢如何花一星期', '如何接受社會毒打']}
# 物件的名稱空間為一個空字典,現在新增了一些key,所以也可以對它進行取值
print(stu.__dict__['name'])
Hans

#在Python中一般不使用這種方法賦值和取值,Python中的方法
# 新增
stu.name = 'Hans'
stu.gender = 'M'
stu.age = 20
stu.course = ['五塊錢如何花一星期','如何接受社會毒打']
# 取值
print(stu.__dict__)
print(stu.name)
# 執行結果:
{'name': 'Hans', 'gender': 'M', 'age': 20, 'course': ['五塊錢如何花一星期', '如何接受社會毒打']}
Hans
# 這種方法只能在物件種使用


# 上面的方法依然是很個學生物件都要寫一遍,所以這個方法也可以做成函式形式。
# 1. 定義一個類
class student_public():
    shool =  '社會大學'

    def course_selection_system(student, course):
        student['student_course'].append(course)
        print("學生:%s 性別:%s 年齡:%s 在%s 期間所選課程:%s" % (student['student_name'], student['student_gender'], \
                                                   student['student_age'], student['shool'], student['student_course']))
#
# 例項化物件
stu1 = student_public()
# 定義函式
def init(name,gender,age,course):
    stu1.name = name
    stu1.gender = gender
    stu1.age = age
    stu1.course = course


init('hans', 'M',20,['五塊錢如何花一星期','如何接受社會毒打'])
print(stu1.__dict__)
# 執行結果:
{'name': 'hans', 'gender': 'M', 'age': 20, 'course': ['五塊錢如何花一星期', '如何接受社會毒打']}

# init()函式中stu1為固定值,如果初始化一個學生,這個函式就不滿足了,所以stu1的位置也要傳參獲得
def init(student,name,gender,age,course):
    student.name = name
    student.gender = gender
    student.age = age
    student.course = course

stu1 = student_public()
stu2 = student_public()

init(stu1,'hans', 'M',20,['五塊錢如何花一星期','如何接受社會毒打'])
init(stu2,'jack', 'M',18,['五塊錢如何花一星期','如何接受社會毒打'])
print(stu1.__dict__)
print(stu2.__dict__)
# 執行結果:
{'name': 'hans', 'gender': 'M', 'age': 20, 'course': ['五塊錢如何花一星期', '如何接受社會毒打']}
{'name': 'jack', 'gender': 'M', 'age': 18, 'course': ['五塊錢如何花一星期', '如何接受社會毒打']}
# 這樣比較相對比較完美了,但是每次都要手動呼叫init()這個方法,有沒有什麼方法可以自動執行init()
# 可以把它寫入到類裡面,不過要變形
class student_public():
    def __init__(student, name, gender, age, course):
        student.name = name
        student.gender = gender
        student.age = age
        student.course = course

    shool = '社會大學'

    def course_selection_system(student, course):
        student['student_course'].append(course)
        print("學生:%s 性別:%s 年齡:%s 在%s 期間所選課程:%s" % (student['student_name'], student['student_gender'], \
                                                   student['student_age'], student['shool'], student['student_course']))

print(student_public.__dict__)
stu1 = student_public()
# 執行結果:
TypeError: student_public.__init__() missing 4 required positional arguments: 'name', 'gender', 'age', and 'course'
# 提示要四個引數,現在給它傳四個引數:
stu1 = student_public('hans', 'M',20,['五塊錢如何花一星期','如何接受社會毒打'])
print(stu1.__dict__)
# 現在執行不會報錯
{'name': 'hans', 'gender': 'M', 'age': 20, 'course': ['五塊錢如何花一星期', '如何接受社會毒打']}

#  __init__()上面寫了五個引數,但是物件在呼叫的時候只讓寫四個,因為使用物件呼叫它會把自己當成第一個引數傳遞給函式。
# 在類中的方法,類和物件都可以呼叫,但是類在呼叫的時候,裡面寫了幾個引數就要傳幾個引數,但是使用物件時它把自己當成第一個引數傳過去,所以推薦使用物件呼叫

# Python中,因為方法中第一個引數為自己,所以把這個寫成self
class student_public():
    def __init__(self, name, gender, age, course):
        self.name = name
        self.gender = gender
        self.age = age
        self.course = course

    shool = '社會大學'

    def course_selection_system(self, course):
        self['student_course'].append(course)
        print("學生:%s 性別:%s 年齡:%s 在%s 期間所選課程:%s" % (self['student_name'], self['student_gender'], \
                                                   self['student_age'], self['shool'], self['student_course']))

# 執行:
stu1 = student_public('hans', 'M', 20, '五塊錢如何花一星期')   # 例項化物件
print(stu1.__dict__)
{'name': 'hans', 'gender': 'M', 'age': 20, 'course': '五塊錢如何花一星期'}

# 判斷一個
print(isinstance(stu1, student_public))
True

"""
呼叫類:
	1. 呼叫類(stu1 = student_public())會得到一個空物件,把這個空物件傳給student_public.__dict__
	2. 呼叫student_public.__dict__(空物件,'hans', 'M',20,'五塊錢如何花一星期')
	3. 得到一個初始化結果
	4. 在__init__裡不能使用return 返回值,如果真要使用也只能返回None
"""

4.3 屬性的查詢順序

類屬性(在類中定義的):

# 1, 檢視類屬性
class student_public():
    def __init__(student, name, gender, age, course):
        student.name = name
        student.gender = gender
        student.age = age
        student.course = course

    shool = '社會大學'
stu1 = student_public('hans', 'M',20,'五塊錢如何花一星期')
print(stu1.shool)

# 2, 增加一個類屬性
stu1.country = 'CN'
print(stu1.__dict__)
{'name': 'hans', 'gender': 'M', 'age': 20, 'course': '五塊錢如何花一星期', 'country': 'CN'}

# 3, 修改類屬性
stu1.shool = '清華大學'
print(stu1.shool)
清華大學

# 4, 修改類屬性
del stu1.shool

物件屬性

class student_public():
    def __init__(student, name, gender, age, course):
        student.name = name
        student.gender = gender
        student.age = age
        student.course = course

    shool = '社會大學'
stu1 = student_public('hans', 'M',20,'五塊錢如何花一星期')

# 1, 檢視
print(stu1.name)
print(stu1.gender)
print(stu1.age)
hans
M
20

# 2, 修改
stu1.age = 18
print(stu1.age)
18

# 3,增加
stu1.result = '優'
print(stu1.__dict__)
{'name': 'hans', 'gender': 'M', 'age': 18, 'course': '五塊錢如何花一星期', 'country': 'CN', 'result': '優'}

# 4, 刪除
del stu1.result
print(stu1.__dict__)
{'name': 'hans', 'gender': 'M', 'age': 18, 'course': '五塊錢如何花一星期', 'country': 'CN'}

屬性查詢順序

1. 先在物件中查詢,如果物件中沒有則去類中查詢
class student_public():
    def __init__(self, name, gender, age, course):
        self.name = name
        self.gender = gender
        self.age = age
        self.course = course

    shool = '社會大學'
    
print(stu1.shool)  # 這個shool為類中定義的
社會大學
print(stu1.__dict__['shool']) # 這個會報錯,因為在物件stu1中根本沒有shool這個屬性,shool這個是類的屬性,直接這麼取是拿不到的,因為指定從物件stu1中的名稱空間中取,物件stu1中的名稱空間中根本沒有。
#所以使用點(.)的方式,如果物件中的名稱空間中沒有,它會去類的名稱空間中找。

class student_public():
    def __init__(self, name, gender, age, course):
        self.name = name
        self.gender = gender
        self.age = age
        self.shool = "清華大學"
        self.course = course

    shool = '社會大學'
    
print(stu1.shool)  # 這個shool為物件中定義的
清華大學



5. 物件導向繫結方法

5.1 小案例:計算一共產生了多少個物件

class Count():
    count = 0

    def __init__(self, name):
        self.name = name
        Count.count +=1  # 統計次數

s1 = Count('Hello')
s2 = Count('World')
print(Count.count)
# 執行結果:
2

# 類屬性修改,所有物件都改。

# 還有一種寫法:
class Count():
    count = 0

    def __init__(self, name):
        self.name = name
        self.__class__.count +=1	# 統計次數 和Count.count +=1 一樣

s1 = Count('Hello')
s2 = Count('World')
print(Count.count)

5.2 繫結方法

繫結方法有兩種:

  • 繫結給物件

    class Students():
        def __init__(self,name, age, gender):
            self.name = name
            self.age = age
            self.gender = gender
    
        def printInfo(self):
            print("%s %s %s" % (self.name, self.age, self.gender))
    
    stu = Students("Hans", 18, 'M')
    stu.printInfo()
    
    # 把printInfo方法繫結給物件stu
    
  • 繫結給類

    IP = '192.168.1.123'
    PORT = 3306
    
    class Mysql():
        def __init__(self, ip, port):
            self.ip = ip
            self.port = port
    
    mysql = Mysql(IP, PORT)
    print(mysql.ip,mysql.port)
    # 執行結果:
    192.168.1.123 3306
    
    # 如果有多個需要寫多次。能不能把Mysql(IP, PORT)這個只寫一次
    # 可以把這個放到一個函式裡
    
    IP = '192.168.1.123'
    PORT = 3306
    
    class Mysql():
        def __init__(self, ip, port):
            self.ip = ip
            self.port = port
    
        def tell(self):
            mysql = Mysql(IP, PORT)
            return mysql
    
    obj  = Mysql(IP, PORT)
    obj1 = obj.tell()
    print(obj1.ip,obj1.port)
    
    # 寫到函式裡後,又有一個問題,mysql = Mysql(IP, PORT)現在是寫的MySQL的,如果換別的資料庫如redis,pg等是不是就不那麼靈活了。
    
    class Database():
        def __init__(self, ip, port):
            self.ip = ip
            self.port = port
    
        @classmethod
        def tell(cls):
            obj = cls(IP, PORT)
            return obj
    
    
    mysql  = Database.tell()
    print(mysql.ip, mysql.port)
    # 換個IP和埠
    IP = '192.168.1.111'
    PORT = 6379
    redis  = Database.tell()
    print(redis.ip, redis.port)
    # 執行結果:
    192.168.1.123 3306
    192.168.1.111 6379
    
    
    # @classmethod 這個裝飾器繫結給了類,以後類來呼叫,會自動把類名當成第一個引數傳過來(cls)
    # 這時呼叫的時候,使用類名呼叫
    # 如果即用到繫結物件,又用到繫結類,推薦使用繫結物件,因為在物件中可以使用__class__拿到類
    

5.3 靜態方法(非繫結方法)

import random
class Students():
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def randnum(self):
        print(random.randint(1, 10))

info = Students("Hans", 18)
info.randnum()
info.randnum()
# 執行結果:
1
4

# 在 def randnum(self) 中根本沒有用到self,是不是可以不傳?
# 現在在類中如果不傳就會報錯(TypeError: Students.randnum() takes 0 positional arguments but 1 was given),所以可以使用 @staticmethod

import random
class Students():
    def __init__(self,name,age):
        self.name = name
        self.age = age
    @staticmethod
    def randnum():
        print(random.randint(1, 10))

info = Students("Hans", 18)
info.randnum()
info.randnum()
# 執行結果:
4
9

6. 隱藏屬性

為什麼要隱藏屬性?

有些時間有些資料,只想讓內部看到,不想讓外部看到。

如何隱藏屬性

class Students():
    shool = '社會大學'
    def __init__(self,name,age):
        self.name = name
        self.age = age

stu1 = Students("Hans", 18)
print(stu1.shool)  
#shool是可以拿到的,如何把shool屬性隱藏掉

class Students():
    __shool = '社會大學'   # 只需要在屬性前面加兩個下劃線(__),只在前面加
    def __init__(self,name,age):
        self.name = name
        self.age = age

stu1 = Students("Hans", 18)
print(stu1.shool)
# 執行結果:
AttributeError: 'Students' object has no attribute 'shool'
    
print(stu1.__shool)
# 執行結果:
AttributeError: 'Students' object has no attribute '__shool'
# 就會發現shool這個不管用什麼方法都訪問不到了。
# 可以看一下它變成了什麼?
print(Students.__dict__)
{'__module__': '__main__', '_Students__shool': '社會大學', '__init__': <function Students.__init__ at 0x000001E5EC31A0E0>, '__dict__': <attribute '__dict__' of 'Students' objects>, '__weakref__': <attribute '__weakref__' of 'Students' objects>, '__doc__': None}
# 可以看到shool前面加了雙下劃線(__)後就變成: _Students__shool(_類名__屬性名)

# 現在在外面拿不到了,在內部是否可以拿到?
class Students():
    __shool = '社會大學'
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def get_shool(self):
        return self.__shool

stu1 = Students("Hans", 18)
print(stu1.get_shool())
# 執行結果:
社會大學
# 可以看到在內部可以拿到

# 其實如果外部要拿也能拿到:
stu1 = Students("Hans", 18)
print(stu1._Students__shool)  # 因為在類的名稱空間為_Students__shool,所以直接取這個就可以拿到
print(Students._Students__shool)
# 不但可以隱藏類中的屬性也可以隱藏方法和物件中的屬性,寫法都一樣,使用雙下劃線
# 物件屬性:
self.__name
#類中的方法:
def __get_shool(self):
#
# 在外部有方法拿到隱藏的屬性,是不是也可以修改? 正常的方法是改不了,可以在類中定義一個專門修改的函式
class Students():
    __shool = '社會大學'
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def get_shool(self):
        return self.__shool
    def set_shool(self):
        self.__shool = "清華大學"
stu1 = Students("Hans", 18)
stu1.set_shool()
print(stu1.get_shool())

# 執行結果:
清華大學

# 更好的方法是給set_shool傳值
class Students():
    __shool = '社會大學'
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def get_shool(self):
        return self.__shool
    def set_shool(self,shoolname):
        self.__shool = shoolname

stu1 = Students("Hans", 18)
stu1.set_shool("北京大學")
print(stu1.get_shool())
# 執行結果:
北京大學

# 還可以對修改的內容進行判斷,現在要修改的是學校名字,按目前寫的傳什麼值都可以,但有些型別不合適用在這個地方比如int型別,所以可以判斷一下。
class Students():
    __shool = '社會大學'
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def get_shool(self):
        return self.__shool
    def set_shool(self,shoolname):
        # if type(shoolname) is not str: return 
        if not isinstance(shoolname, str): return
        self.__shool = shoolname

stu1 = Students("Hans", 18)
stu1.set_shool(123)  # 123  不是字串,直接return返回,所以shool的值還是原來的
print(stu1.get_shool())
# 執行結果:
社會大學

"""
隱藏屬性發生了什麼?
	1, 在類定義階段發生了變化,如__shool變成了_Students__shool,也只有在定義階段發生變化,其他地方都不會發生變化
	2, 隱藏對外不對內
"""

image

7. property裝飾器

property是python的一種裝飾器,是用來修飾方法的。

上面的例子我們把一些不想對外公開的屬性隱蔽起來,而只是提供方法給使用者操作(檢視get_shool和設定set_shool),在方法裡面,我們可以檢查引數的合理性等。

class Students():
    __shool = '社會大學'
    def __init__(self,name,age):
        self.__name = name
        self.age = age

    def get_name(self):
        return  self.__name
	
    def set_name(self):
        self.__name="ABC"
        
stu = Students("Hans", 18)
print(stu.get_name())
stu.set_name()
print(stu.get_name())
# 執行結果:
Hans
ABC
# 我們要得到name必須要呼叫get_name方法,但正常我們取一個屬性直接使用.加屬性名就可以(stu.name),
# 但現在還要呼叫一個方法,如何實現即要隱藏屬性又要使用.屬性獲得值,就可以使用@property 
class Students():
    __shool = '社會大學'
    def __init__(self,name,age):
        self.__name = name
        self.age = age

    @property
    def name(self):   # 為了更像stu.name這種方法,把方法名直接改為name
        return  self.__name

stu = Students("Hans", 18)
print(stu.name)
# 執行結果:
Hans

# @property 裝飾器會將 name() 方法轉化為一個具有相同名稱的只讀屬性的 "getter"

# 在修改的時候也要像查詢一樣,直接使得.屬性的方式
class Students():
    __shool = '社會大學'
    def __init__(self,name,age):
        self.__name = name
        self.age = age

    @property
    def name(self):
        return  self.__name

    @name.setter
    def name(self,name):
        if not isinstance(name, str):
            print("必須為字串")
            return
        self.__name= name

stu = Students("Hans", 18)
print(stu.name)   # Hans
stu.name = 123	# 必須為字串,執行到了isinstance
print(stu.name) # Hans

# 修改為一個合法型別:
stu = Students("Hans", 18)
print(stu.name)  # Hans
stu.name = "XYZ"
print(stu.name)	# XYZ
# 可以看到已經修改
# 要使用這種方法,在定義時:
"""
	@property
    def name(self):     	1
        return  self.__name

    @name.setter  2
    def name(self,xxx) 3    
    這三個地方的名字一定要一致。
"""

# 刪除一個屬性
class Students():
    __shool = '社會大學'
    def __init__(self,name,age):
        self.__name = name
        self.age = age

    @property
    def name(self):
        return  self.__name

    @name.setter
    def name(self,name):
        if not isinstance(name, str):
            print("必須為字串")
            return
        self.__name= name

    @name.deleter
    def name(self):
        del self.__name
        print("正在刪除%s" % self.__name)
stu = Students("Hans", 18)
del stu.name
print(stu.name)
# 執行結果:
正在刪除Hans

# 還有一種寫法,現在已經不常用了,即定義一個託管屬性

class Students():
    __shool = '社會大學'
    def __init__(self,name,age):
        self.__name = name
        self.age = age


    def get_name(self):
        return  self.__name


    def set_name(self,name):
        if not isinstance(name, str):
            print("必須為字串")
            return
        self.__name= name


    def del_name(self):
        print("正在刪除%s" % self.__name)

    # 定義一個託管屬性 
    name = property(get_name, set_name, del_name) 


stu = Students("Hans", 18)
print(stu.name)   # 呼叫get_name 方法
stu.name = "XYZ"  # 呼叫set_name 方法
print(stu.name)
del stu.name	  # 呼叫del_name 方法

# 執行結果:
Hans
XYZ
正在刪除XYZ

property就是把方法偽裝成屬性

property詳細請看官網:

property

未完待續