Summary of class usage in python

An internal call and __call__()

Detailed reference: https://blog.csdn.net/weixin_43593330/article/details/108174666
Notice: Double-leading and double-ending underscores __var__ are used for special purposes in python. For details, refer to: https://www.runoob.com/w3cnote/python-5-underline.html, but not all such types can be used An object can be called, __call__ is implemented by default in python, __getitem__ is implemented in torch.utils.data.Dataset of pytorch, and __getitem__ is implemented in keras.utils.Sequence of keras.

Five meanings of underscore in Python: single leading underscore _var, single trailing underscore var_, double leading underscore __var, double leading and trailing underscore __var__, single underscore_Reference: https://www.runoob.com/w3cnote/ python-5-underline.html.

Double underscore __xxx__ (magic method) reference in Python: https://www.cnblogs.com/bigtreei/p/7930511.html

call () is a magic method, implementing this method in a class can make the instance (object) of the class be called like a function. By default this method is not implemented in the class.

The function of the call () method is actually to turn an instantiated object of a class into a callable object, as long as the __call__() method is implemented in the class. For example, when __call__() is not implemented in the class, the object p at this time is just an instance of the class, not a callable object. When calling it, an error will be reported: '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()

insert image description here

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)

insert image description here

2. Update the global variables in the class in the loop traversal

If you want to automatically update the global variables in the class in the loop, you must write the initialization of the class outside the loop.

# 定义一个类
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()

# 结果如下
类的初始化在循环中
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]

insert image description here
Summary:
Instantiating the StepRunner() class will automatically run init () to initialize, pass parameters to the variables and functions defined in __init__(), and assign values.

Note: After instantiating the class, you can later call the objects in the class and change the objects in the class. Which object (function) in the class is called, the object (function) will be affected, and it will not be affected if it is not called, that is, if the called object (function) does not affect the variables and functions in init ( ) , Then the variables and functions in __init__() are not changed. If the called object (function) has a relationship with the content in __init__(), then the variables and functions in __init__() will change.

Variables in those classes that are defined at initialization time can also be changed so that they are permanently changed. Which one is changed, which one is affected, and which one is not affected.

The most confusing thing here is the __call__() in the class. The function of call () is to call the content defined in __call__() by directly calling the class name after instantiation, without needing to write class( ) .step() form of class plus function. Just pay attention to what is defined in __call__().

Guess you like

Origin blog.csdn.net/LIWEI940638093/article/details/126691442