python進階(7):面向對象進階

来源:http://www.cnblogs.com/liluning/archive/2017/08/16/7374971.html
-Advertisement-
Play Games

學了面向對象三大特性繼承,多態,封裝。今天我們看看面向對象的一些進階內容,反射和一些類的內置函數。 ...


學了面向對象三大特性繼承,多態,封裝。今天我們看看面向對象的一些進階內容,反射和一些類的內置函數。

 

一、isinstance和issubclass

class Foo:
    pass

class Son(Foo):
    pass

s = Son()
#判斷一個對象是不是這個類的對象,傳兩個參數(對象,類)
print(isinstance(s,Son))
print(isinstance(s,Foo))
#type更精準
print(type(s) is Son)
print(type(s) is Foo)

#判斷一個類是不是另一類的子類,傳兩個參數(子類,父類)
print(issubclass(Son,Foo))
print(issubclass(Son,object))
print(issubclass(Foo,object))
print(issubclass(int,object))

 

二、反射

反射的概念是由Smith在1982年首次提出的,主要是指程式可以訪問、檢測和修改它本身狀態或行為的一種能力(自省)。這一概念的提出很快引發了電腦科學領域關於應用反射性的研究。它首先被程式語言的設計領域所採用,併在Lisp和麵向對象方面取得了成績。

python面向對象中的反射:通過字元串的形式操作對象相關的屬性。python中的一切事物都是對象(都可以使用反射)

四個可以實現反射的函數:hasattr,getattr,setattr,delattr

下列方法適用於類和對象(一切皆對象,類本身也是一個對象)

class Foo:
    def __init__(self):
        self.name = 'egon'
        self.age = 73

    def func(self):
        print(123)

egg = Foo()
#常用:
#hasattr
#getattr
# print(hasattr(egg,'name'))
print(getattr(egg,'name'))
if hasattr(egg,'func'):   #返回bool
    Foo_func = getattr(egg,'func')  #如果存在這個方法或者屬性,就返回屬性值或者方法的記憶體地址
                                 #如果不存在,報錯,因此要配合hasattr使用
    Foo_func()
#不常用:
#setattr
# setattr(egg,'sex','屬性值')
# print(egg.sex)
# def show_name(self):
#     print(self.name + ' sb')
# setattr(egg,'sh_name',show_name)
# egg.sh_name(egg)
# show_name(egg)
# egg.sh_name()

#delattr
# delattr(egg,'name')
# print(egg.name)


# print(egg.name)
# egg.func()
# print(egg.__dict__)


#反射
#可以用字元串的方式去訪問對象的屬性、調用對象的方法
反射舉例1
class Foo:
    f = 123 #類變數
    @classmethod
    def class_method_demo(cls):
        print('class_method_demo')
    @staticmethod
    def static_method_demo():
        print('static_method_demo')
# if hasattr(Foo,'f'):
#     print(getattr(Foo,'f'))
print(hasattr(Foo,'class_method_demo'))
method = getattr(Foo,'class_method_demo')
method()
print(hasattr(Foo,'static_method_demo'))
method2 = getattr(Foo,'static_method_demo')
method2()
#類也是對象
反射舉例2
import my_module
# print(hasattr(my_module,'test'))
# # func_test = getattr(my_module,'test')
# # func_test()
# getattr(my_module,'test')()
#import其他模塊應用反射

from my_module import test


def demo1():
    print('demo1')

import sys
print(__name__)  #'__main__'
print(sys.modules)
#'__main__': <module '__main__' from 'D:/Python代碼文件存放目錄/S6/day26/6反射3.py'>
module_obj =sys.modules[__name__]  #sys.modules['__main__']
# module_obj : <module '__main__' from 'D:/Python代碼文件存放目錄/S6/day26/6反射3.py'>
print(module_obj)
print(hasattr(module_obj,'demo1'))
getattr(module_obj,'demo1')()
#在本模塊中應用反射
反射舉例3
#對象
#
#模塊 : 本模塊和導入的模塊

def register():
    print('register')

def login():
    pass

def show_shoppinglst():
    pass
#
print('註冊,登錄')
ret = input('歡迎,請輸入您要做的操作: ')
import sys
print(sys.modules)
# my_module = sys.modules[__name__]
# if hasattr(my_module,ret):
#     getattr(my_module,ret)()
if ret == '註冊':
    register()
elif ret == '登錄':
    login()
elif ret == 'shopping':
    show_shoppinglst()
反射舉例4
def test():
    print('test')
my_module(第三個例子用到的模塊)

 

三、類的內置函數

1、__str__和__repr__

class Foo:
    def __init__(self,name):
        self.name = name
    def __str__(self):
        return '%s obj info in str'%self.name
    def __repr__(self):
        return 'obj info in repr'

f = Foo('egon')
# print(f)
print('%s'%f)
print('%r'%f)
print(repr(f))  # f.__repr__()
print(str(f))
#當列印一個對象的時候,如果實現了str,列印中的返回值
#當str沒有被實現的時候,就會調用repr方法
#但是當你用字元串格式化的時候 %s和%r會分別去調用__str__和__repr__
#不管是在字元串格式化的時候還是在列印對象的時候,repr方法都可以作為str方法的替補
#但反之不行
#用於友好的表示對象。如果str和repr方法你只能實現一個:先實現repr

2、__del__

class Foo:
    def __del__(self):
        print('執行我啦')

f = Foo()
print(123)
print(123)
print(123)
#析構方法,當對象在記憶體中被釋放時,自動觸發執行。
#註:此方法一般無須定義,因為Python是一門高級語言,程式員在使用時無需關心記憶體的分配和釋放,因為此工作都是交給Python解釋器來執行,所以,析構函數的調用是由解釋器在進行垃圾回收時自動觸發執行的。

3、item系列

__getitem__\__setitem__\__delitem__

class Foo:
    def __init__(self):
        self.name = 'egon'
        self.age = 73
        
    def __getitem__(self, item):
        return self.__dict__[item]

    def __setitem__(self, key, value):
        # print(key,value)
        self.__dict__[key] = value

    def __delitem__(self, key):
        del self.__dict__[key]
f = Foo()
print(f['name'])
print(f['age'])
f['name'] = 'alex'
# del f['name']
print(f.name)
f1 = Foo()
print(f == f1)

4、__new__

# class A:
#     def __init__(self):  #有一個方法在幫你創造self
#         print('in init function')
#         self.x = 1
#
#     def __new__(cls, *args, **kwargs):
#         print('in new function')
#         return object.__new__(A, *args, **kwargs)
# a = A()
# b = A()
# c = A()
# d = A()
# print(a,b,c,d)

#單例模式
class Singleton:
    def __new__(cls, *args, **kw):
        if not hasattr(cls, '_instance'):
            cls._instance = object.__new__(cls, *args, **kw)
        return cls._instance

one = Singleton()
two = Singleton()
three = Singleton()
go = Singleton()
print(one,two)

one.name = 'alex'
print(two.name)

5、__call__

class Foo:
    def __init__(self):
        pass
    def __call__(self, *args, **kwargs):
        print('__call__')

obj = Foo()  # 執行 __init__
obj()  # 執行 __call__
Foo()()  # 執行 __init__和執行 __call__
#構造方法的執行是由創建對象觸發的,即:對象 = 類名() ;而對於 __call__ 方法的執行是由對象後加括弧觸發的,即:對象() 或者 類()()

6、__len__,__hash__

class Foo:
    def __len__(self):
        return len(self.__dict__)
    def __hash__(self):
        print('my hash func')
        return hash(self.name)
f = Foo()
print(len(f))
f.name = 'egon'
print(len(f))
print(hash(f))

7、__eq__

class A:
    def __init__(self):
        self.a = 1
        self.b = 2

    def __eq__(self,obj):
        if  self.a == obj.a and self.b == obj.b:
            return True
a = A()
b = A()
print(a == b)

#__eq__控制著==的結果

 

8、內置函數實例 

class FranchDeck:
    ranks = [str(n) for n in range(2,11)] + list('JQKA')
    suits = ['紅心','方板','梅花','黑桃']

    def __init__(self):
        self._cards = [Card(rank,suit) for rank in FranchDeck.ranks
                                        for suit in FranchDeck.suits]

    def __len__(self):
        return len(self._cards)

    def __getitem__(self, item):
        return self._cards[item]

deck = FranchDeck()
print(deck[0])
from random import choice
print(choice(deck))
print(choice(deck))
紙牌游戲
class FranchDeck:
    ranks = [str(n) for n in range(2,11)] + list('JQKA')
    suits = ['紅心','方板','梅花','黑桃']

    def __init__(self):
        self._cards = [Card(rank,suit) for rank in FranchDeck.ranks
                                        for suit in FranchDeck.suits]

    def __len__(self):
        return len(self._cards)

    def __getitem__(self, item):
        return self._cards[item]

    def __setitem__(self, key, value):
        self._cards[key] = value

deck = FranchDeck()
print(deck[0])
from random import choice
print(choice(deck))
print(choice(deck))

from random import shuffle
shuffle(deck)
print(deck[:5])
紙牌游戲2
class Person:
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex

    def __hash__(self):
        return hash(self.name+self.sex)

    def __eq__(self, other):
        if self.name == other.name and other.sex == other.sex:return True


p_lst = []
for i in range(84):
    p_lst.append(Person('egon',i,'male'))

print(p_lst)
print(set(p_lst))

#只要姓名和年齡相同就預設為一人去重
去重

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 使用過SpringMVC的都知道DispatcherServlet,下麵介紹下該Servlet的啟動與初始化。作為Servlet,DispatcherServlet的啟動與Serlvet的啟動過程是相聯繫的。在Serlvet的初始化過程程中,Serlvet的init方法會被調用,以進行初始化。Dis ...
  • 首先,整個頁麵包括:列表數據、數據總數、當前頁數、每頁顯示數據個數、列表總頁數、當前索引數 新建Page類,包含以上6個屬性。其中 總頁數 和 當前索引值 可以通過計算得出,所以可以註釋掉 計算總頁數: 計算當前索引值: 在後臺代碼中設置當前頁面pageNo、每頁多少數據pageSize 在serv ...
  • Java類中對象的序列化工作是通過ObjectOutputStream和ObjectInputStream來完成的。 寫入: 讀取: 註意: 對於任何需要被序列化的對象,都必須要實現介面Serializable,它只是一個標識介面,本身沒有任何成員,只是用來標識說明當前的實現類的對象可以被序列化。 ...
  • 隨著業務變遷/需求變更,JavaEE 應用中會被迫連接多個數據源進行業務處理。 怎樣在不影響原有項目結構的情況下,已最優雅/最簡潔的方式動態切換數據源呢? 本文已一次添加數據源後動態切換實踐為例,描述整個思考和實踐過程,文中如有紕漏,還望指正。 1. 依賴 Spring 動態數據源實現 Spring ...
  • 同一個表單中的內容多次提交到伺服器中。 第一種情況: 提交完表單以後,不做其他操作,直接刷新頁面,表單會提交多次。 - 這種情況產生的根本原因是,Servlet處理完請求以後,直接轉發到目標頁面。 - 這樣整一個業務,只發送了一次請求,那麼當你在瀏覽器中點擊刷新按鈕或者狂按f5會一直都會刷新之前的請 ...
  • python的應用範圍和優勢、變數、數據類型、if、while ...
  • 寫文件與讀文件類似,可以是以位元組為單位寫入,可以是以字元為單位寫入。 對應讀操作FileOutputStream是以位元組為單位進行寫入的: 這裡只是簡單替換,如果想實現追加的話只需要這樣寫FileOutputStream(aFile,true);把第二個參數寫為true就可以了。 FileWrite ...
  • 1.Caesar Shift Cipher(密碼) 說明:密碼學是編程中最有趣的分支之一。研究它的演算法通常以一種簡單的方法開始,這個方法是以著名的羅馬皇帝凱撒大帝命名的,他用這個方法來傳達他的軍事秘密。 我們將在這個問題中練習解密加密消息。這個演算法的想法很簡單。原文的每一個字母都被另一個字母替換。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...