pytorch數據預處理——2. Python中的_, __, __xx__ 區別

本專題主要是解決Pytorch框架下項目的數據預處理工作
Table of Contents:
     1. HDF5文件簡介
     2. Python中的_, __, __xx__區別
     3. Dataset類
     4. DataLoader類

1. _xx 單下劃線開頭

Python中沒有真正的私有屬性或方法,可以在你想聲明爲私有的方法和屬性前加上單下劃線,以提示該屬性和方法不應在外部調用。如果真的調用了也不會出錯,但不符合規範。

2. __xx 雙下劃線開頭

雙下劃線開頭,有兩個用處:

  1. 爲了不讓 子類 重寫 父類 的屬性或方法
  2. 不允許外部調用(即a.__method()是錯誤的)
class A:

    def __method(self):
        print('This is a method from class A')

    def method(self):
        return self.__method()

    
class B(A):
    
    def __method(self):
        print('This is a method from calss B')

a = A()
b = B()
a.method()
b.method()

在這裏插入圖片描述
請先獨立思考一下爲什麼會是這樣的輸出?

  1. 由於class B 沒有方法 method(),因此會繼承 class A 中的 method()。
  2. 由於__開頭的方法子類無法重寫,所以子類仍然調用class A 中的 __method()。
    如何實現子類仍然調用class A 中的 __method() 的呢?通過類的實例化時自動轉換,在類中的雙下劃線開頭的屬性方法前加上”_類名”實現。

如果在 class B 中重寫方法 method() 呢?會出現什麼結果?
在這裏插入圖片描述

3. __xx__ 雙下劃線開頭且結尾

__xx__ 經常是操作符或本地函數調用的magic methods(魔法方法),通常提供了一種重寫類的操作符的功能。比如遍歷迭代器對象,得根據數據本身重寫迭代器對象來適配遍歷函數。


在Python中,常見的對象類型有: number,string,tuple,dict,list,set,None。其中 tuple,string 是不可變容器,dict,list 是可變容器。
可變容器和不可變容器的區別在於,不可變容器一旦賦值後,不可對其中的某個元素進行修改。比如定義了 list1 = [1, 2, 3] 和 tuple1 = (1, 2, 3) 後, 執行 list1[0] = 0 是可以的,但執行 tuple1[0] = 0則會報錯。

如果我們要自定義一些數據結構,使之能夠跟以上的容器類型表現一樣,那就需要去實現某些協議。這裏的協議跟其他語言中所謂的"接口"概念很像,一樣的需要你去實現纔行,只不過沒那麼正式而已。

如果要自定義不可變容器類型,只需要定義__len__ 和 __getitem__方法;
如果要自定義可變容器類型,還需要在不可變容器類型的基礎上增加定義__setitem__ 和 __delitem__;
如果你希望你的自定義數據結構還支持"可迭代", 那就還需要定義__iter__。

魔法方法說明:

  1. __len__(self):返回數值類型的結果,以表示容器的長度。該方法在可變容器和不可變容器中必須實現
  2. __getitem__(self, key):當你執行 container[key] 的時候,調用的就是該方法。該方法在可變容器和不可變容器中也都必須實現。調用的時候,如果 key 的類型錯誤,該方法應該拋出TypeError;如果沒法返回 key 對應的數值時,該方法應該拋出ValueError。注:key 可以是索引(index)
  3. __setitem__(self, key, value):當你執行 self[key] = value 時,調用的是該方法。
  4. __delitem__(self, key):當你執行 del self[key] 的時候,調用的是該方法。
  5. __iter__(self):該方法需要返回一個迭代器(iterator)。當你執行 for x in container: 或者使用iter(container) 時,該方法被調用。
  6. __reversed__(self):如果想要該數據結構被內建函數 reversed() 支持,就還需要實現該方法。
  7. __contains__(self, item):如果定義了該方法,那麼在執行 item in container 或者 item not in container 時該方法就會被調用。如果沒有定義,那麼Python會迭代容器中的元素來一個一個比較,從而決定返回True或者False。
  8. __missing__(self, key):dict字典類型會有該方法,它定義了 key 如果在容器中找不到時觸發的行爲。比如d = {‘a’: 1}, 當你執行 d[notexist] 時,d.__missing__(‘notexist’)就會被調用。

現以構造自定義類型對象(即容器container)爲例:
enumerate(container)返回索引與數值, 即 index 與 container[index], 所以你得在你的__getitem__(self, key):中定義好 container[index] 的返回值,其中 key(index) 可以是參數。
在這裏插入圖片描述

class Con:

    def __init__(self, values=None):
        if values is None:
            self.values = []
        else:
            self.values = values

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

    def __getitem__(self, key):
        return self.values[key]

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

    def __delitem__(self, key):
        del self.values[key]

    def __iter__(self):
        return iter(self.values)

c = Con([0, 1, 2, 3,4])
for i, data in enumerate(c):
    print(data)

在這裏插入圖片描述
注:之所以沒實現 __iter__(self):方法是因爲 enumerate( c ) 中的 c 是一個可遍歷對象,如果要想把 c 變成一個可迭代對象,還得實現 __iter__(self):方法。


在特殊的情況下,它只是python調用的hook。例如,__init__()函數是當對象被創建初始化時調用的;__new__()是用來創建實例。



推薦閱讀:

Python中的if name == ‘main

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章