日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

Python类与对象技巧(1):字符串格式化、封装属性名、可管理的属性、调用父类方法

發布時間:2025/3/15 python 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python类与对象技巧(1):字符串格式化、封装属性名、可管理的属性、调用父类方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. 自定義字符串的格式化

_formats = {'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 = yearself.month = monthself.day = daydef __format__(self, code):if code == '':code = 'ymd'fmt = _formats[code]return fmt.format(d=self)d = Date(2018, 11, 4) print(d.year, d.month, d.day) # >>> 2018 11 4 print(format(d)) # >>> 2018-11-4 print('This day is {:mdy}'.format(d)) # >>> This day is 11/4/2018

__format__()方法給Python的字符串格式化功能提供了一個鉤子。 這里需要強調的是格式化代碼的解析工作由類決定。

2. 在類中封裝屬性名

如果想封裝類的實例上面的“私有”數據,但是Python語言并沒有訪問控制。Python不依賴語言特性去封裝數據,而是通過遵循一定的屬性和方法命名約定來達到這個效果。

  • 任何以單下劃線_開頭的名字都應該是內部實現
class A:def __init__(self):self._internal = 0 # 內部屬性self.public = 1 # 共有屬性def public_method(self):passdef _internal_method(self):pass

Python并不會真的阻止訪問內部名稱。但是這么做肯定是不好的,可能會導致脆弱的代碼(所以說對于初級程序員而言,python的嚴密性與可靠性都是遠不如C++的)。 同時注意到,使用下劃線開頭的約定同樣適用于模塊名和模塊級別函數。 例如,以單下劃線開頭(比如_socket)的模塊,就是內部實現。 類似的,模塊級別函數比如 sys._getframe() 在使用的時候就得加倍小心了(因為內部方法的調用,原則上外部不應該隨意使用)。

  • 任何以雙下劃線__開頭的名字會導致訪問名稱變成其他形式
class B:def __init__(self):self.__private = 0 # 訪問名稱會發生變化def __private_method(self):passdef public_method(self):passself.__private_method()

使用雙下劃線開始會導致訪問名稱變成其他形式。 比如,在類B中,私有屬性會被分別重命名為 _B__private _B__private_method 。 這樣重命名的目的就是繼承——這種屬性通過繼承是無法被覆蓋的。例如:

class C(B):def __init__(self):super().__init__()self.__private = 1 # 沒有覆蓋B.__private# 沒有覆蓋B.__private__method()def __private_method(self):pass

這里,私有名稱 __private 和 __private_method 被重命名為 _C__private 和 _C__private_method ,這個跟父類B中的名稱是完全不同的。

Note:提到單下劃線和雙下劃線來命名私有屬性,到底哪種方式好呢? 大多數而言,應該讓非公共名稱以單下劃線開頭。但是,如果代碼涉及到子類, 并且有些內部屬性應該在子類中隱藏起來,那么才考慮使用雙下劃線方案。

3. 創建可以管理的屬性

如果想給某個實例attribute增加除訪問與修改之外的其他處理邏輯,比如類型檢查或合法性驗證。自定義某個屬性的一種簡單方法是將它定義為一個property。property的一個關鍵特征是它看上去跟普通的attribute沒什么兩樣, 但是訪問它的時候會自動觸發?getter?、setter?和?deleter?方法。下面增加對一個屬性簡單的類型檢查:

class Person:def __init__(self, first_name):self.first_name = first_name# Getter function : 使得first_name成為一個屬性@propertydef first_name(self):return self._first_name# setter function : 關聯屬性的裝飾器@first_name.setterdef first_name(self, value):if not isinstance(value, str):raise TypeError('Expected a string')self._first_name = value# deleter function (optional) : 關聯屬性的裝飾器@first_name.deleterdef first_name(self):raise AttributeError("Can't delete attribute")p = Person('ziheng') print(p.first_name) # calls the getter # >>> ziheng p.first_name = 'xiaohe' # calls the setter 必須是字符串才會收集 print(p.first_name) # >>> xiaohe del p.first_name # >>> AttributeError: Can't delete attribute

在實現一個property的時候,底層數據需要存儲在某個地方。 因此,在get和set方法中,會看到對 _first_name 屬性的操作,這也是實際數據保存的地方。

4. 調用父類方法

為了調用父類(超類)的一個已經覆蓋的方法,使用 super() 函數。super() 函數的一個常見用法是在 __init__() 方法中確保父類被正確的初始化。

class A:def __init__(self, x):self.x = xclass B(A):def __init__(self, x, y):super().__init__(x)self.y = yobj = B(2017, 2018) print(obj.x) # 2017 print(obj.y) # 2018

實際上,如何正確使用 super() 函數還需要知道更多,比如說在復雜的多繼承中直接調用父類使用super()存在很大差別。

class Base:def __init__(self):print('Base.__init__')class A(Base):def __init__(self):Base.__init__(self)print('A._init__')class B(Base):def __init__(self):Base.__init__(self)print('B.__init__')class C(A,B):def __init__(self):A.__init__(self)B.__init__(self)print('C.__init__')obj = C()

執行結果:

Base.__init__
A._init__
Base.__init__
B.__init__
C.__init__

Comment:Base.__init__調用了兩次!!!

class Base:def __init__(self):print('Base.__init__')class A(Base):def __init__(self):super().__init__()print('A._init__')class B(Base):def __init__(self):super().__init__()print('B.__init__')class C(A,B):def __init__(self):super().__init__()print('C.__init__')obj = C()

執行結果:

Base.__init__
B.__init__
A._init__
C.__init__

為了弄清原理,需要解釋Python是如何實現繼承的。 對于定義的每一個類,Python會計算出一個方法解析順序(MRO)列表。 這個MRO列表就是一個簡單的所有基類的線性順序表。例如:

>>> C.__mro__
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>)

當使用 super() 函數時,Python會在MRO列表上搜索下一個類。 只要每個重定義的方法統一使用 super() 并只調用它一次, 那么控制流最終會遍歷完整個MRO列表,每個方法也只會被調用一次。

文章參考《python3-cookbook》

總結

以上是生活随笔為你收集整理的Python类与对象技巧(1):字符串格式化、封装属性名、可管理的属性、调用父类方法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。