• python中class使用总结


    一 内部调用和__call__()

    详细说明参考:https://blog.csdn.net/weixin_43593330/article/details/108174666
    注意:双前导和双末尾下划线__var__在python中用于特殊用途,具体参考:https://www.runoob.com/w3cnote/python-5-underline.html,但是不是所有的此类都可以使得一个对象可以被调用,python中默认实现了__call__,pytorch的torch.utils.data.Dataset 中实现了__getitem__,keras的keras.utils.Sequence中实现了__getitem__。

    Python 中下划线的 5 种含义:单前导下划线_var,单末尾下划线var_,双前导下划线__var,双前导和末尾下划线__var__,单下划线_ 参考:https://www.runoob.com/w3cnote/python-5-underline.html。

    Python中的双下划线__xxx__(魔术方法) 参考:https://www.cnblogs.com/bigtreei/p/7930511.html

    call()是一种magic method,在类中实现这一方法可以使该类的实例(对象)像函数一样被调用。默认情况下该方法在类中是没有被实现的。

    call()方法的作用其实是把一个类的实例化对象变成了可调用对象,只要类里实现了__call__()方法就行。如当类里没有实现__call__()时,此时的对象p 只是个类的实例,不是一个可调用的对象,当调用它时会报错:‘Person’ object is not callable.

    class People(object):
        def __init__(self, name):
            self.name = name
    
        def my_friend(self):
            print("hello "+self.name)
    
        def train(self,location):
            print("name"+location)
    
        def __call__(self):
            return self.my_friend()
            # return self.train(location)
    
        def update(self, newname):
            self.name = newname
    
    a = People('无忌!')
    a.__call__()       # 调用方法一
    a()                # 调用方法二   调用就会直接激活__call__(),调用时必须加上括号
    
    # 调用类中其他对象
    a.update("赵敏")  # 更新类中变量,更新了类中的全局变量,调用时a后面不加括号
    a()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    在这里插入图片描述

    class People(object):
        def __init__(self, name):
            self.name = name
    
        def add_interest(self, interest): # 定义类中新的全局变量,也就是在类中的初始化函数中没有定义的变量。
        # 不能直接给定,必须通过这种函数方法来传入
            self.interest = interest
    
        def change_interest(self):  # 前面定义好新的变量后,在这里更改
            self.interest = "play guitar"
    
        def speak(self):  # 不需要传入参数的对象
            print("come here please")
    
        def train(self, location):  # 初始化时传入的参数这里不能用,需要在这个对象中传入参数,只对这个函数起作用
            print("name"+" "+location)
    
        def my_friend(self, location):  # 调用类中的其他对象。如果被调用函数需要参数,则传入参数
            self.change_interest()  # 不需要参数的调用
            self.speak()  # 不需要参数的调用
            self.train(location)  # 需要参数的调用
            print("hello "+" "+self.name)
            print("I like"+" "+self.interest)
    
        def __call__(self, location):  # __call__()方法的作用其实是把一个类的实例化对象变成了可调用对象,
        # 只要类里实现了__call__()方法就行,即实例化类后,直接调用类就会调用__call__
            return self.my_friend(location)
            # return self.train(location)
    
        def update(self, newname):  # 更新类中全局变量的函数
            self.name = newname
    
        def play(self, ball):  # 跟类中其他对象没有关系的独立对象
            print("play"+ball)
    
    a = People('无忌!')
    a.add_interest("sing song")
    a.__call__("北京")  # 调用方法一
    print("---------------------")
    a("北京")           # 调用方法二
    print("---------------------")
    # 调用类中其他对象
    a.update("赵敏")  # 更新类中变量
    a("北京")
    print("---------------------")
    # 调用类中独立对象
    a.play("football")
    print("---------------------")
    # 打印类中的全局变量
    print(a.name)
    print(a.interest)
    
    • 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
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    在这里插入图片描述

    二 在循环遍历中更新类中的全局变量

    如果想要在循环中自动更新类中的全局变量,则必须将类的初始化写到循环外面。

    # 定义一个类
    class step_batch():
        def __init__(self, lr=10):
            self.lr = lr
    
        def run(self):
            print(self.lr)
    
        def update(self):
            self.lr = self.lr / 2
    
    # 类的初始化在循环里面,意味着每次循环都需要重新初始化,那么循环中的更新变量的操作就会被类的重新初始化给更改掉
    def train_model(init_lr=10):
        for i in tqdm(range(10)):
            a = step_batch(lr=init_lr)  # 类的初始化
            a.run()
            if i % 2 == 0:
                a.update()
    
    # 类的初始化在循环外面,意味着在进入循环之前只进行了一次初始化;在循环体内部,更新变量的操作就会将更新后的变量保存下来
    def test_model(init_lr=10):
        a = step_batch(lr=init_lr)  # 类的初始化
        for i in tqdm(range(10)):
            a.run()
            if i % 2 == 0:
                a.update()
    
    
    • 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
    # 结果如下
    类的初始化在循环中
    10
    10
    10
    10
    10
    10
    10
    10
    10
    10
    ---------------------
    类的初始化在循环外面
    10
    5.0
    5.0
    2.5
    2.5
    1.25
    1.25
    0.625
    0.625
    0.3125
    100%|██████████| 10/10 [00:00<?, ?it/s]
    100%|██████████| 10/10 [00:00<?, ?it/s]
    
    • 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

    在这里插入图片描述
    总结:
    实例化 StepRunner() 类,会自动运行 init()进行初始化,给__init__()中定义的变量和函数传参数,赋值。

    注意:实例化类以后,后面就可以去调用类中的对象,更改类中的对象。调用类中的哪一个对象(函数),这个对象(函数)才会受影响,没调用就不受影响,也就是,如果调用的这个对象(函数)不影响 init() 中的变量和函数,那么__init__() 中的变量和函数就不改变。如果调用的对象(函数)和__init__() 中的内容有关系,那么__init__() 中的变量和函数就改变。

    初始化时候定义的那些类中的变量,也可以更改,这样就会永久改变。更改哪一个,哪一个才受影响,不更改就不会受影响。

    这里最有迷惑性的是类中的__call__(), call()的作用就是在实例化后可以通过直接调用类名来调用__call__()中定义的内容,而不需要再写class().step() 类加函数 的形式。只需要关注__call__()中定义了什么就可以。

  • 相关阅读:
    Biotin-PEG-N3 生物素PEG叠氮
    CloudCompare——泊松重建
    el-table合计行合并
    【C# 窗体 超市购物买单系统】简单版和进阶版
    成都优优聚美团代运营:塑造卓越优势,引领电商新时代
    深入浅出WMS之入库流程解析
    来看下这篇文章,教你如何实现一个SpringBoot的Mybatis分库分表组件
    聚磷酸酯-紫杉醇前药(PTX-PEEP)|聚姜黄素-二硫键-聚甲基丙烯酸二乙胺基乙酯-聚磺酸甜菜碱|齐岳生物
    Java 并发编程之CAS 和 Unsafe类本地使用方法
    AlexNet学习笔记
  • 原文地址:https://blog.csdn.net/LIWEI940638093/article/details/126691442