天天看點

Python面向對象程式設計02:深度認識類class總結

前篇學委展示分享了面向對象程式設計的概念,相信讀者們對這個類和對象比較熟悉了。

我們在深入看一下類的結構。

類中的其他内置函數/屬性

前文代碼展示了‘__init__'函數,這個是類的内置函數,預設不寫就沒有執行多餘操作。

在Python中類這種結構還包含了下面的一些内置函數屬性:

__name__ 類名字

__dict__ 類的命名空間字典(這裡先不做多解釋,其實這個解釋雖然抽象但是準确的,下面看代碼就能秒懂)

__doc__ 類的文檔說明

__module__ 類的文檔說明

__bases__ 類的文檔說明

看起來比較枯燥無味的樣子,除了類的名字,我們看起來好像應該是類的名字(好像廢話)

我們還是看一下代碼感受一下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2021/11/15 11:58 下午
# @Author : LeiXueWei
# @CSDN/Juejin/Wechat: 雷學委
# @XueWeiTag: CodingDemo
# @File : __init__.py.py
# @Project : hello

"""
下面是一個學生類定義
"""


class student(object):
    """這裡是一個學生類定義"""

    def __init__(self, name):
        self.name = name

    def get_name(self):
        return self.name

    def set_name(self, name):
        self.name = name

    def study(self):
        print(f"{self.name} : 好好學習,天天向上!")


stu01 = student("學委粉絲【小白】")
print(stu01)
print(stu01.get_name())
print(stu01.study())

print("類名:", student.__name__)
print("類文檔:", student.__doc__)
print("類的命名空間:", student.__dict__)
print("類的基類:", student.__bases__)
print("類所在的子產品:", student.__module__)
      

下面是運作效果:

Python面向對象程式設計02:深度認識類class總結

好了,我們看到類的命名空間列印出來dict字典,内放置的内容的key都是類的成員(函數,屬性)。

這下子清楚了:Python用一個dict來說描述類的結構!(這就是學委前篇提到的一張網,它把單一的函數,資料屬性,挂到這個網上,組成了類的結構)。

其他幾個内置類函數非常好了解。

另一個地方是’__bases__'函數,它告訴我們student類是在‘object’這個類的基礎上建立的。(确實如此!)

内置函數擷取其對象屬性

python提供了下面的一些函數:

getattr(對象,屬性名,[可選預設值]) : 擷取對象的某個屬性,如果沒有找到傳回預設值

setattr(對象,屬性,屬性值): 設定對象的,添加/覆寫某個屬性為屬性值。

hasattr(對象,屬性): 判斷對象是否包含某個屬性

這個非常直白。

Java同學都知道反射,比較繁瑣的。但是在Python中這塊做的非常簡潔,這個跟__dict__的設計很精巧.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2021/11/15 11:58 下午
# @Author : LeiXueWei
# @CSDN/Juejin/Wechat: 雷學委
# @XueWeiTag: CodingDemo
# @File : student4_1.py
# @Project : hello

"""
下面是一個學生類定義
"""


class Student(object):
    """這裡是一個學生類定義"""

    def __init__(self, name):
        self.name = name

    def get_name(self):
        return self.name

    def set_name(self, name):
        self.name = name

    def study(self):
        print(f"{self.name} : 好好學習,天天向上!")


stu01 = Student("學委粉絲【小白】")
print("student :", stu01)
print("student name:", stu01.get_name())
print("student study:", stu01.study())

stu02 = Student("學委粉絲【小花】")
print("student2 name:", stu02.get_name())

print("-" * 16)
print("getattr student name: ", getattr(stu01, 'name'))
# print("getattr: ", getattr(stu01, 'name2')) # AttributeError: 'Student' object has no attribute 'name2'
if hasattr(stu01, 'name2'):
    print("student %s has attribute name1 " % stu01.name)
else:
    print("student %s do not have attribute name2 " % stu01.name)
    print("getattr name2: ", getattr(stu01, 'name2', 'defaultName'))  # 沒有但是我們可以給一個default
    # print(stu01.name1) # getattr并沒有辦法把屬性設定到stu01對象

setattr(stu01, 'name2', '小白别名')
print("student name2", stu01.name2)

# 學委溫馨提示,setattr很強大可以覆寫原來的對象屬性
setattr(stu01, 'study', '小白躺平了,今天休息')
print("student study:", stu01.study)
      

上面的代碼學委展示了擷取修改屬性。以及根據對象是否包含屬性,進行setattr。

下面是運作結果:

Python面向對象程式設計02:深度認識類class總結

讀者多看一看,特别是代碼附加的注釋,加深對類和對象的了解。

既然說到了base類,再談談類的繼承

上面的bases函數傳回值的解釋,換一句話說:

除了object類,其他所有類預設的都是直接或者間接的繼承于object類的;

也就是說,object類是所有的類的根,源頭類。

A類繼承于B類,那麼,我們會使用下面的描述來表示它們:

A類是B類的子類

B類是A類的父類

這個就跟家族族譜一樣,最頂上那個第一代元祖父,這就是類和object的關系。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2021/11/15 11:58 下午
# @Author : LeiXueWei
# @CSDN/Juejin/Wechat: 雷學委
# @XueWeiTag: CodingDemo
# @File : __init__.py.py
# @Project : hello

"""
下面是一個學生類定義
"""


class Programmer():
    pass


print("programmer類的命名空間:", Programmer.__dict__)
print("programmer類的命名空間:", Programmer.__bases__)


class Student(object):
    """這裡是一個學生類定義"""

    def __init__(self, name):
        self.name = name

    def get_name(self):
        return self.name

    def set_name(self, name):
        self.name = name

    def study(self):
        print(f"{self.name} : 好好學習,天天向上!")


s1 = Student("學委粉絲【小白】")
print(s1)
print(s1.get_name())
print(s1.study())

print("類名:", Student.__name__)
print("類文檔:", Student.__doc__)
print("類的命名空間:", Student.__dict__)
print("類的基類:", Student.__bases__)
print("類所在的子產品:", Student.__module__)




class PrimarySchoolStudent(Student):
    pass


print("*" * 16)
print("PrimarySchoolStudent類的命名空間:", PrimarySchoolStudent.__dict__)
print("PrimarySchoolStudent類的基類:", PrimarySchoolStudent.__bases__)
print("PrimarySchoolStudent類所在的子產品:", PrimarySchoolStudent.__module__)
PrimarySchoolStudent("主要學生").study()
      

這段代碼想要展示的資訊很多。

首先是在前面第一段代碼後多加了一個Developer類(沒有寫繼承)。

輸出我們看到他說繼承object類的(是以寫跟不寫沒有差别,這裡要注意python版本,學委用的是3.8)

其次,我們看到PirimarySchoolStudent的bases函數的輸出是Student,沒錯,繼承某個類之後的base值就為該類,也就是Student

再次,繼承讓子類直接擁有了父類的函數和資料屬性,可以直接通路拿來用。

好了,請仔細看看下面的運作結果:

Python面向對象程式設計02:深度認識類class總結

總結

這次把類和對象的知識補充了一些(但是還有Python支援多繼承,這跟Java是很大的差別!),有過半不是常見的。

但是在寫架構或者深度分析的時候,非常有用,務必過一過熟悉一下。

可以看看下圖,回想一下上面的代碼,這就是類命名空間,資料屬性,函數屬性,子產品之間的關系:

Python面向對象程式設計02:深度認識類class總結

我們可以通過命名空間找到函數屬性,它們有關聯。

此外,擷取資料屬性隻能通過對象應用getattr來擷取。

學委寫了十幾年的Java了,但是寫的這套Python教程非常務實,對基礎程式設計有任何問題請檢視相關文章。