Python包裝之對象處理
概念
所有Python的對象都是擴展的PyObject,python的垃圾回收機制是計算引用,這個對象中定義了py_ssize就是用來做這個事的。類型對象可以理解為就是自定義的class。在Python中函數(shù)間傳遞的是都是泛型指針,所以可以通過PyObject的ob_type屬性來判斷實際的類型,這也是多態(tài)的一種表現(xiàn)。
在Python中的垃圾回收機制比較特殊,它采用了內(nèi)存對象池技術,對象釋放的空間歸還給內(nèi)存池,如果再使用可以從內(nèi)存池中獲取如果確實不再使用時再回收,與java比較相似。所有的內(nèi)置對象都有自己所特有的對象緩沖池機制。這種緩沖池中的對象都是不可變對象,池中的對象是共享的,但也不會引起多并發(fā)的問題。
一、基礎
1.1、toString方法
class FormatChange: def __init__(self, x, y): self.x = x self.y = y def __repr__(self): return f'use repr method: ({self.x}, {self.y})' def __str__(self): return f'use str method: ({self.x}, {self.y})' fc = FormatChange(5, 7) print(fc.__repr__()) # use repr method: (5, 7) print(fc) # use str method: (5, 7) print(f'fc is {fc!r}') #!r表示用repr方法代替str方法輸出
1.2、格式化輸出
format_dict = { 'ymd': '{d.year}-{d.month}-{d.day}', 'mdy': '{d.month}/{d.day}/{d.year}', 'dmy': '{d.day}/{d.month}/{d.year}' } class Date: def __init__(self, year, month, day): self.year = year self.month = month self.day = day def __format__(self, format_type='ymd'): #format_type: 格式化類型,默認使用 ymd 方式 if not format_type: format_type = 'ymd' fmt = format_dict[format_type] return fmt.format(d=self)#這里的format是一個鉤子函數(shù) curr_data = Date(2020, 5, 6) #這處其實調(diào)用的format是一個類庫中的方法,然后反向調(diào)用了自定義覆寫的format方法 print(f'default format: {format(curr_data)}') #2020-5-6 print(f"use mdy format: {format(curr_data, 'mdy')}") #5/6/2020
1.3、創(chuàng)建大對象
用slots創(chuàng)建的對象,其內(nèi)存占用會減少2/3左右。但缺點是不能再給對象添加新的屬性了,也不能實現(xiàn)繼承,所以一般時候只把他做為內(nèi)存優(yōu)化工具,用于存儲大量的數(shù)據(jù)使用。
class Date: __slots__ = ['year', 'month', 'day'] def __init__(self, year, month, day): self.year = year self.month = month self.day = day
二、高級用法
2.1、通過字符串式調(diào)用函數(shù)
import math class Point: def __init__(self, x, y): self.x = x self.y = y def __repr__(self): return f'Point({self.x!r:},{self.y!r:})' def distance(self, x, y): return math.hypot(self.x - x, self.y - y) #第一種方式:這種方式感覺用處不是太大,前面還是得new一個對象 p = Point(2, 3) d = getattr(p, 'distance')(0, 0) import operator operator.methodcaller('distance', 0, 0)(p) #用相同的參數(shù)多次調(diào)用某個方法時 points = [ Point(1, 2), Point(3, 0), Point(10, -3), Point(-5, -7), Point(-1, 8), Point(3, 2) ] #第二種使用方法: Sort by distance from origin (0, 0) points.sort(key=operator.methodcaller('distance', 0, 0)) p = Point(3, 4) d = operator.methodcaller('distance', 0, 0) print(f'd(p) = {d(p)}')#5.0
2.2、上下文管理器
需要自定義實現(xiàn)enter和exit方法。一般用于網(wǎng)絡連接等工具類中,代碼放在with語句中執(zhí)行,當出現(xiàn)with時enter方法被調(diào)用,返回的值賦值給as后的變量。然后with中的語句開始執(zhí)行。最后exit被執(zhí)行進行一些清理工作。在exit方法中自帶了異常處理,如果忽略異??煞祷豊one,如果返回True那么異常會被清空。下面是兩個實現(xiàn):一個是工具類,另一個是允許嵌套的工廠類:
簡單實現(xiàn):
from socket import socket, AF_INET, SOCK_STREAM class LazyConnection: def __init__(self, address, family=AF_INET, type=SOCK_STREAM): self.address = address self.family = family self.type = type self.sock = None def __enter__(self): if self.sock is not None: raise RuntimeError('Already connected') self.sock = socket(self.family, self.type) self.sock.connect(self.address) return self.sock def __exit__(self, exc_ty, exc_val, tb): self.sock.close() self.sock = None from functools import partial conn = LazyConnection(('www.python.org', 80)) # Connection closed with conn as s: # conn.__enter__() executes: connection open s.send(b'GET /index.html HTTP/1.0\r\n') s.send(b'Host: www.python.org\r\n') s.send(b'\r\n') resp = b''.join(iter(partial(s.recv, 8192), b''))
到此這篇關于Python包裝之對象處理的文章就介紹到這了,更多相關Python 對象處理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
解讀MaxPooling1D和GlobalMaxPooling1D的區(qū)別
這篇文章主要介紹了MaxPooling1D和GlobalMaxPooling1D的區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-12-12解決PyCharm不在run輸出運行結果而不是再Console里輸出的問題
這篇文章主要介紹了解決PyCharm不在run輸出運行結果而不是再Console里輸出的問題,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-09-09解決Python3錯誤:SyntaxError: unexpected EOF while
這篇文章主要介紹了解決Python3錯誤:SyntaxError: unexpected EOF while parsin問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07