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

  • 5
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值