程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python從門到精通(二):包裝-03-對象處理

編輯:Python

本章算是為下面的類的內容打了點提前量。

對象概念

所有Python的對象都是擴展的PyObject,python的垃圾回收機制是計算引用,這個對象中定義了py_ssize就是用來做這個事的。類型對象可以理解為就是自定義的class。在Python中函數間傳遞的是都是泛型指針,所以可以通過PyObject的ob_type屬性來判斷實際的類型,這也是多態的一種表現。

在Python中的垃圾回收機制比較特殊,它采用了內存對象池技術,對象釋放的空間歸還給內存池,如果再使用可以從內存池中獲取如果確實不再使用時再回收,與java比較相似。所有的內置對象都有自己所特有的對象緩沖池機制。這種緩沖池中的對象都是不可變對象,池中的對象是共享的,但也不會引起多並發的問題。

一、基礎

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.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

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是一個鉤子函數


curr_data = Date( 2020, 5, 6)
#這處其實調用的format是一個類庫中的方法,然後反向調用了自定義覆寫的format方法
print( f'default format: { format( curr_data)} ') #2020-5-6
print( f"use mdy format: { format( curr_data, 'mdy')} ") #5/6/2020
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.

1.3、創建大對象

用slots創建的對象,其內存占用會減少2/3左右。但缺點是不能再給對象添加新的屬性了,也不能實現繼承,所以一般時候只把他做為內存優化工具,用於存儲大量的數據使用。

class
Date:

__slots__ = [ 'year', 'month', 'day']
def __init__( self, year, month, day):
self. year = year
self. month = month
self. day = day
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

二、高級用法

2.1、通過字符串式調用函數

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)

#用相同的參數多次調用某個方法時
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
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.

2.2、上下文管理器

需要自定義實現enter和exit方法。一般用於網絡連接等工具類中,代碼放在with語句中執行,當出現with時enter方法被調用,返回的值賦值給as後的變量。然後with中的語句開始執行。最後exit被執行進行一些清理工作。在exit方法中自帶了異常處理,如果忽略異常可返回None,如果返回True那麼異常會被清空。下面是兩個實現:一個是工具類,另一個是允許嵌套的工廠類:

簡單實現

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''))
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved