python中的魔术方法(特殊方法)

news2024/11/24 6:58:31

文章目录

  • 1. 前言
  • 2. __init__方法
  • 3. __new__方法
  • 4. __call__方法
  • 5. __str__方法
  • 6. __repr__方法
  • 7. __getitem__方法
  • 8. __setitem__方法
  • 9. __delitem__方法
  • 10. __len__方法
  • 11. 富比较特殊方法
  • 12. __iter__方法和__next__方法
  • 13. __getattr__方法、__setattr__方法、__delattr__方法
  • 14. __enter__方法和__exit__方法

1. 前言

  python的内置方法具有特殊的功能,这些内置方法我们也称之为魔术方法(magic method)或特殊方法(special method)。魔术方法就是前后各有两个下划线__的方法,像__init__方法就是一个魔术方法。python中的类提供了很多双下划线开头和结尾__xxx__的方法,这些方法是Python运行的基础,很多功能的背后都是通过调用这些内置方法来实现的。例如len()函数调用对象的__len__方法;print(obj)函数调用对象的__str__方法;for循环遍历语句for item in iterable_obj调用对象的__next____iter__方法。下面对常见的魔术方法进行介绍。
在这里插入图片描述
上面的图片来自于:【python】魔术方法大全——基础篇

2. __init__方法

  __init__方法是一个构造方法,在创建类对象的时候用于初始化的设置。__init__方法在创建类的实例对象时自动调用

class Student:
    def __init__(self,name,age,id) -> None:
        self.name = name
        self.age = age
        self.id = id

    def show_info(self) -> None:
        print(f"name = {self.name},age = {self.age},id = {self.id}")
    
stu = Student("zhangsan",18,"001")  # 会自动调用__init__方法
stu.show_info() # 输出:name = zhangsan,age = 18,id = 001

3. __new__方法

  记住重要的一点:__new__方法用于创建对象实例,而__init__方法用于实例对象的初始化,且__new__方法在__init__方法之前被调用。也就是说,我们必须先创建对象(先调用__new__方法),然后才可以进行对象的初始化(再调用__init__方法)。
(1)__new__方法负责实例对象的创建,在对象实例化的时候,它是第一个被调用的方法。
(2)__new__是一个类方法(类方法使用​​cls​​作为第一个参数,cls==class(类)),因此在调用__new__方法时使用类本身而不是实例对象。
(3)__new__方法必须返回一个实例对象,这个实例对象通常是由super().__new__(cls)​​​创建的,即调用父类的__new__​​方法。通常情况下,你不需要直接调用__new__方法,因为它在实例化时自动被调用。
(4)当构造方法__init__是一个无参数构造时,在__new__方法中无需传递参数,并使用super().__new__(cls)来创建实例对象。如下所示:​​​

class Student:
    def __new__(cls):
        instance = super().__new__(cls)
        print("__new__被执行了...")
        return instance
    
    def __init__(self) -> None:
        print("__init__被执行了...")
    
stu = Student()

输出结果:
__new__被执行了...
__init__被执行了...

(5)当构造方法__init__是一个有参数构造时,在__new__方法中需要传递相应的参数,并使用super().__new__(cls)来创建实例对象。如下所示:

class Student:
    def __new__(cls,name,age,id):
        # instance = super(Student,cls).__new__(cls,name,age,id) # python2写法,会报错
        # 下面是python3的写法
        instance = super().__new__(cls)
        print("__new__被执行了...")
        return instance
    
    def __init__(self,name,age,id) -> None:
        self.name = name
        self.age = age
        self.id = id
        print("__init__被执行了...")
    
stu = Student("zhangsan",18,"001")

输出结果:
__new__被执行了...
__init__被执行了...

4. __call__方法

  __call__方法的作用是把一个类的实例化对象变成可调用对象。例如:在对象进行调用方法时,实例对象.__call__()等价于实例对象()。我们可以使用内置函数callable(obj)来判断对象obj是否为可调用对象。

class Student:
    def __init__(self,name,age,id) -> None:
        self.name = name
        self.age = age
        self.id = id

    def __call__(self, str1: str, str2: str):
        print(f"str1+str2 = {str1+str2}")
    
stu = Student("zhangsan",18,"001")  # 会自动调用__init__方法
stu.__call__("hello ","world")  # 输出:str1+str2 = hello world
stu("hello ","world")  # 输出:str1+str2 = hello world
print(callable(stu)) # 输出:True

5. __str__方法

  __str__方法的作用是把一个类的实例对象变成字符串(str)。
(1)不使用__str__方法:返回实例对象的内存地址。

class Student:
    def __init__(self,name: str, age: int, id: str) -> None:
        self.name = name
        self.age = age
        self.id = id

stu = Student("zhangsan", 18, "001")
print(stu)  # 输出:<__main__.Student object at 0x0000020E72F6E088>

(2)使用__str__方法:返回一个字符串。

class Student:
    def __init__(self,name: str, age: int, id: str) -> None:
        self.name = name
        self.age = age
        self.id = id

    def __str__(self) -> str:
        return f"name = {self.name}, age = {self.age}, id = {self.id}"

stu = Student("zhangsan", 18, "001")
print(stu)  # 输出:name = zhangsan, age = 18, id = 001

(3)由上面代码可知:当使用__str__方法时,输出实例对象(print(stu))的结果由<__main__.Student object at 0x0000020E72F6E088>变成name = zhangsan, age = 18, id = 001。即:__str__方法的作用是把一个类的实例对象变成字符串(str)。

6. __repr__方法

  __repr__方法用来返回一个实例对象的字符串(str)表示形式。

class Student:
    def __init__(self,name: str, age: int, id: str) -> None:
        self.name = name
        self.age = age
        self.id = id

    def __repr__(self) -> str:
        return f"Student(name='{self.name}',age={self.age},id='{self.id}')"

stu = Student("zhangsan", 18, "001")
#当我们给repr()函数传入对象时,会调用__repr__方法。
print(repr(stu))  # 输出:Student(name='zhangsan',age=18,id='001')

__str__方法和__repr__方法的相同点和不同点

(1)这两个方法都可以用来输出实例对象的字符串表示形式。
(2)当我们打印一个实例对象时,Python会自动调用__str__方法。如果该对象没有实现(或定义)__str__方法,Python会寻找对象的__repr__方法。如果该对象也没有实现__repr__方法,则输出默认的对象表示形式(返回实例对象的内存地址)。如果我们需要显式的指定以何种方式进行实例对象到字符串的转化,可以使用内置的str()repr()函数,它们会调用类中对应的双下划线方法。也就是说str()函数会调用__str__方法,repr()函数调用__repr__方法。参考下面代码:

class Student:
    def __init__(self,name: str, age: int, id: str) -> None:
        self.name = name
        self.age = age
        self.id = id

    def __str__(self) -> str:
        return f"执行__str__..., name = {self.name}"
        
    def __repr__(self) -> str:
        return f"执行__repr__..., name = {self.name}"

stu = Student("zhangsan", 18, "001")
print(stu)  # 输出:执行__str__..., name = zhangsan。自动调用__str__方法
print(str(stu))  # 输出:执行__str__..., name = zhangsan。调用__str__方法
print(repr(stu))  # 输出:执行__repr__..., name = zhangsan。调用__repr__方法

(3)__repr__方法的返回结果更多地用于开发者调试和重新创建对象,并且可以准确地重现该对象的状态和属性。而__str__方法的返回结果对用户更加友好,提供一个易于理解的字符串表示 。参考下面代码:

import datetime
today = datetime.datetime.today()
print(str(today))  # 输出:2024-08-05 11:17:11.422536
print(repr(today))  #输出:datetime.datetime(2024, 8, 5, 11, 17, 11, 422536)

"""
(1)__str__ 的返回结果可读性强。也就是说,__str__ 的意义是得到便于人们阅读的信息,
   就像上面的 "2024-08-05 11:17:11.422536" 一样。
(2)__repr__ 的返回结果应更准确。__repr__ 存在的目的在于调试,便于开发者使用。将__repr__ 返回的结果
  datetime.datetime(2024, 8, 5, 11, 17, 11, 422536) 直接复制到命令行上,是可以直接执行的。
"""

(4)我们在写类的时候,最好至少添加一个__repr__方法来保证实例对象到字符串的转换具有自定义的有效性。__str__是可选的,因为在默认情况下,__str__方法默认调用__repr__方法,所以在实例对象转字符串的时候,找到底层__str__方法之后,会调用重写__repr__方法。

参考文章:浅谈python中__str__和__repr__的区别

7. __getitem__方法

   __getitem__方法,用于索引和切片操作,允许我们通过索引或切片的方式访问对象的元素。__getitem__方法返回所给键对应的值。当对象是序列类型(像列表、元组和字符串)时,键是整数;当对象是映射(字典)时,键是任意值。使用场景是:在定义类时,如果希望能够按照键取类的值,则需要定义__getitem__方法
   在Python中,可使用索引器运算符[]来访问对象元素,例如:我们定义了一个列表mylist = [2,4,6,8],然后可以通过索引器运算符[]来访问列表对象的元素,即my_list[2]。其实,my_list[2]大致等价于my_list.__getitem__(2)。同理,我们定义了一个字典my_dict = {"name": "ZS", "age": 18},那么my_dict['name']大致等价于my_dict.__getitem__("name")。利用索引器运算符[]来访问列表和字典对象元素的代码如下:

my_list = [2,4,6,8]
my_dict = {"name": "ZS", "age": 18}

print(my_list[2])  # 输出:6
print(my_list.__getitem__(2))  # 输出:6
print(my_dict["name"])  # 输出:ZS
print(my_dict.__getitem__("name"))  # 输出:ZS

   当传递给索引器运算符[]的参数不止一个时,那么这些参数会被隐式的转换成元组。例如:列表切片my_list[1:4]等价于my_list[slice(1,4)]my_list[1:4, 0]等价于my_list[ (slice(1,4), 0)]
   (1)当对象是序列类型(像列表、元组和字符串)时,键是整数,使用__getitem__方法来实现一个自定义的可索引对象。

class Student:
    def __init__(self, *args) -> None:
        # args是一个元组类型,它可以接收可变数量的参数。
        print(args)  # 输出:(2, 4, 6, 8, 10)
        print(type(args))  # 输出:<class 'tuple'>
        self.my_list = list(args)

    def __getitem__(self, item):
        print("__getitem__被执行了...")
        print(type(item))
        return self.my_list[item]
        
stu = Student(2,4,6,8,10)
# 通过实现__getitem__方法,我们可以使用索引或切片操作来获取my_list列表中的元素
print(stu[1])  # 输出:"__getitem__被执行了..."、<class 'int'> 和 4
print(stu[1:4]) # 输出:"__getitem__被执行了..."、<class 'slice'> 和 [4, 6, 8]

# stu[1] 等价于 stu.__getitem__(1)
# stu[1:4] 等价于 stu.__getitem__(slice(1,4))

  (2)当对象是映射(字典)时,键是任意值。使用__getitem__方法来实现一个自定义的可索引对象。

class Student:
    def __init__(self, **kwargs) -> None:
        # kwargs是一个字典类型,它可以接收以键-值对形式传递的可变数量的参数。
        print(kwargs)  # 输出:{'name': 'zs', 'age': 18, 'id': '001'}
        print(type(kwargs))  # 输出:<class 'dict'>
        self.my_dict = dict(kwargs)

    def __getitem__(self, item):
        print("__getitem__被执行了...")
        print(type(item))
        if isinstance(item, tuple):
            """判断item是否为元组类型的对象,如果是的话,则通过列表推导式
            将字典中键(key)对应的值(value)存放到列表中,并返回该列表。
            """
            return [self.my_dict[key] for key in item]
        else:
            return self.my_dict[item]
        
stu = Student(name="zs", age = 18, id="001")

print(stu["name"])  # 输出:"__getitem__被执行了..."、<class 'str'>、zs
print(stu["name","age","id"])  # stu["name","age","id"]等价于stu[("name","age","id")],参数被转换成元组。
 # 输出:"__getitem__被执行了..."、<class 'tuple'>、['zs', 18, '001']

参考文章:Python中__getitem__()方法和索引器[]的详细用法

8. __setitem__方法

   __setitem__方法的作用是让类按照一定的方法存储和键(key)映射的值(value),该值可以使用__getitem__方法来获取。使用场景:当期望定义的类具备按照键存储值时,即类能够执行obj[“key”]=value(等价于obj.__setitem__(key,value))。代码示例如下:

class Student:
    def __init__(self, **kwargs) -> None:
        self.my_dict = dict(kwargs)

    def __getitem__(self, item):
        print("__getitem__被执行了...")
        if isinstance(item, tuple):
            return [self.my_dict[key] for key in item]
        else:
            return self.my_dict[item]

    def __setitem__(self, key, value):
        print("__setitem__被执行了...")
        self.my_dict[key] = value

    def __str__(self) -> str:
        obj_str = str()
        # 遍历字典中的键值对
        for key, value in self.my_dict.items():
            obj_str = obj_str + f"{key} = {value} "
        return obj_str

stu = Student(name="zs", age = 18)
print(stu)  # 输出:name = zs age = 18 
# 调用__setitem__方法, stu["id"] = "001"等价于stu.__setitem__("id","001")
stu["id"] = "001" # 输出:"__setitem__被执行了..."
print(stu) # 输出:name = zs age = 18 id = 001 
print(stu["id"])  # 输出:"__getitem__被执行了..."、001

9. __delitem__方法

  __delitem__方法用于删除给定键对应的元素。使用del关键字来删除指定键对应的元素,即del obj[key],等价于obj.__delitem__(key)

class Mylist:
    def __init__(self, *args) -> None:
        self.obj_list = list(args)

    def __delitem__(self, key):
        print("__delitem__被调用...")
        del self.obj_list[key]

obj = Mylist(1,2,3,4,5,6)
print(obj.obj_list) # 输出:[1, 2, 3, 4, 5, 6]
del obj[2] # 输出:__delitem__被调用...
print(obj.obj_list) # 输出:[1, 2, 4, 5, 6]

10. __len__方法

  __len__方法用于返回对象的长度或元素个数。我们可以在类中定义__len__方法来实现对该类的对象使用 len()函数。

class Mylist:
    def __init__(self, *args) -> None:
        self.obj_list = list(args)

    def __len__(self):
        print("__len__被调用...")
        return len(self.obj_list)

obj = Mylist(1,2,3,4,5,6)
print(len(obj))  # 输出:"__len__被调用..."、6
print(obj.__len__())  # 输出:"__len__被调用..."、6
# len(obj)等价于obj.__len__()

11. 富比较特殊方法

  富比较(rich comparison)特殊方法是一组用于实现对象之间比较操作的特殊方法。这些方法使得自定义对象可以支持 <, <=, ==, !=, >=, > 这样的比较操作。
在这里插入图片描述
在这里插入图片描述
参考文章:Python 富比较特殊方法

  下面以__lt__方法和__eq__方法为例,代码如下:

class Student:
    def __init__(self,name,age,id) -> None:
        self.name = name
        self.age = age
        self.id = id

    def __lt__(self, other: object) -> bool:
        # 使用对象中的age属性来比较大小
        return self.age < other.age
    
    def __eq__(self, other: object) -> bool:
        # 使用对象中的age属性来比较大小
        return self.age == other.age

    
stu1 = Student("zhangsan",18,"001")
stu2 = Student("zhangsan",30,"001")
print(stu1<stu2)  # 等价于:stu1.__lt__(stu2)。输出:True
print(stu1 == stu2)  # 等价于:stu1.__eq__(stu2)。输出:False

12. __iter__方法和__next__方法

  在 Python 中,迭代器是一个实现了__iter____next__方法的对象。__iter__方法返回迭代器对象自身,而 __next__方法返回下一个元素。换句话说,迭代器是一个可以逐个返回元素的对象。如果在python的类中定义了__next____iter__方法,生成的实例对象可以通过for循环遍历来取,并且先调用__iter__方法,再调用__next__方法。代码如下:

class MyList:
    def __init__(self,*args) -> None:
        self.data = list(args)
        self.start = 0

    def __iter__(self):
        print("__iter__被执行了...")
        return self
    
    def __next__(self):
        print("__next__被执行了...")
        if self.start >= len(self.data):
        # raise StopIteration用于提前终止一个迭代器中的循环
            raise StopIteration
        item = self.data[self.start]
        self.start += 1
        return item
    
obj_list = MyList(2,4,6)

for i in obj_list:
    print(i)

输出:
__iter__被执行了...
__next__被执行了...
2
__next__被执行了...
4
__next__被执行了...
6
__next__被执行了...

13. __getattr__方法、__setattr__方法、__delattr__方法

  (1)__getattr__方法:当我们访问对象中一个不存在的属性时,会抛出异常,提示我们该对象没有该属性。而这个异常就是__getattr__方法抛出的,其原因在于它是访问一个不存在的属性的最后落脚点。

class Student:
    def __init__(self,name,age,id) -> None:
        self.name = name
        self.age = age
        self.id = id
    def __getattr__(self,item):
        # 这里的item就是那个不存在的属性名
        print("__getattr__被执行...")
        print(item)
        return f"该对象不存在属性:{item}"
    
stu = Student("ZS",16,"001")
print(stu.name)  # name属性存在,可以访问
print(stu.gender)  # gender属性不存在,会调用__getattr__方法。

输出:
ZS
__getattr__被执行...
gender
该对象不存在属性:gender

  (2)__setattr__方法:在对一个属性设置值的时候,会调用到这个方法,每个设置值的方式都会进入这个方法。如下代码所示:在实例化对象的时候,会调用__init__方法进行初始化。在__init__方法中对属性age进行值的设置,此时也会调用__setattr__方法。我们还可以新建一个属性name,并对其赋值,此时会调用__setattr__方法。

class Student:
    def __init__(self,_age) -> None:
        self.age = _age

    def __setattr__(self,key, value):
        # 这里的key为属性名,value是该属性对应的值
        print("__setattr__被执行了...")
        if value == 16:
            print("这里的key和value来自__init__方法")
        object.__setattr__(self, key, value)
# object.__setattr__(self, key, value)、
# self.__dict__[key] = value、
# super().__setattr__(key,value),这三种方法等价,都可以使用
   
stu = Student(16)
print(stu.age)

stu.age = 30
print(stu.age)

stu.name = "ZS"
print(stu.name)

输出:
__setattr__被执行了...
这里的key和value来自__init__方法
16
__setattr__被执行了...
30
__setattr__被执行了...
ZS

注意:在重写__setattr__方法的时候千万不要重复调用,以防造成死循环。下面的代码就是一个死循环,在__init__方法中执行语句self.age = _age的时候会调用__setattr__方法。而__setattr__方法中又存在语句self.key = value,因此会继续调用__setattr__方法,造成死循环。

class Student:
    def __init__(self,_age) -> None:
        self.age = _age

    def __setattr__(self,key, value):
        self.key = value
   
stu = Student(16)

  (3)__delattr__方法:用于删除对象中的某个属性。

class Student:
    def __init__(self,name,age,id) -> None:
        self.name = name
        self.age = age
        self.id = id

    def __getattr__(self,item):
        print("__getattr__被执行了...")
        return f"该对象不存在属性:{item}"
    
    def __delattr__(self, item):
        print("__delattr__被执行了...")
        object.__delattr__(self,item)
    
stu = Student("ZS",16,"001")
del stu.id  # 会调用__delattr__方法
print(stu.id)

输出:
__delattr__被执行了...
__getattr__被执行了...
该对象不存在属性:id

14. __enter__方法和__exit__方法

  (1)with上下文管理器:关键字with使用最多的就是打开文件,然后进行读写操作。如下代码:

with open("data.txt","w+") as f_obj:
    f_obj.write("hello java")
    
# 上面的代码等价于下面的代码
f_obj = open("data.txt","w+")
f_obj.write("hello java)
f_obj.close()

使用with语句的时候不需要显式地去关闭文件资源,因为它会自动关闭。那么这个自动关闭是怎么实现的呢,这其实就是__enter____exit__魔法方法在起作用。
  (2)__enter____exit__方法的工作原理:我们使用with ... as ...来打开文件,首先进入__enter__方法,__enter__方法会返回一个对象,然后将该对象赋给关键字as后面的变量;当with ... as ...语句体结束时,会自动调用__exit__方法。

class OpenFile:
    def __init__(self,file_name="",mode="r"):
        self.__file = open(file_name, mode)

    def __enter__(self):
        print("__enter__被执行...")
        return self

    def write(self,ctx):
        print("writer方法被执行...")
        self.__file.write(ctx)
        print("writer方法执行结束...")

    def __exit__(self,exec_type,exec_value,exec_tb):
        print("__exit__方法被执行...")
        self.__file.close()

with OpenFile("demo.txt","w+") as f:
    f.write("hello world")


输出:
__enter__被执行...
writer方法被执行...
writer方法执行结束...
__exit__方法被执行...

  (3)__exit__方法中的三个参数:exec_type(异常类型),exec_value(异常对象),exec_tb(异常追踪信息),这些参数在异常处理的时候相当有用。如果with代码块正常执行完毕,这些参数都为None。通过下面代码来理解它是怎样工作的。

class Test:
    def __enter__(self):
        print("__enter__被执行...")
        return self

    def compute(self):
        print(1/0)

    def __exit__(self,exec_type,exec_value,exec_tb):
        print("__exit__方法被执行...")
        print(f"exec_type = {exec_type}")
        print(f"exec_value = {exec_value}")
        print(f"exec_tb = {exec_tb}")

with Test() as obj_test:
    obj_test.compute()

输出:
__enter__被执行...
__exit__方法被执行...
exec_type = <class 'ZeroDivisionError'>
exec_value = division by zero
exec_tb = <traceback object at 0x000001F61AB8F388>
Traceback (most recent call last):
  File "d:/code/day2/test.py", line 37, in <module>
    obj_test.compute()
  File "d:/code/day2/test.py", line 28, in compute
    print(1/0)
ZeroDivisionError: division by zero

with后面的代码块抛出任何异常时,__exit__方法都会被执行。与之关联的type,value和stack trace会传给__exit__方法的参数exec_type,exec_value,exec_tb。我们可以在__exit__方法中执行必要的清理操作(如关闭文件或释放资源)。

参考文章:Python----魔法函数__enter__/__exit__的用法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1986571.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深度学习DeepLearning Inference 学习笔记

神经网络预测 术语 隐藏层神经元多层感知器 神经网络概述 应当选择正确的隐藏层数和每层隐藏神经元的数量&#xff0c;以达到这一层的输出是下一层的输入&#xff0c;逐层变得清晰&#xff0c;最终输出数据的目的。 在人脸识别的应用中&#xff0c;我们将图片视作连续的像…

【Java 第九篇章】多线程实际工作中的头大的模块

多线程是一种编程概念&#xff0c;它允许多个执行路径&#xff08;线程&#xff09;在同一进程内并发运行。 一、多线程的概念和作用 1、概念 线程是程序执行的最小单元&#xff0c;一个进程可以包含多个线程。每个线程都有自己的程序计数器、栈和局部变量&#xff0c;但它们…

Motionface ai工具有哪些?

Motionface Android/PC 用一张静态含有人脸相片来生成一个能说会唱的虚拟主播。使用简单便捷&#xff0c;极致的流畅度体验超乎您的想象。 免费下载 Respeak PC电脑软件 任意视频一键生成虚拟主播&#xff0c;匹配音频嘴型同步&#xff0c;保留原视频人物神态和动作&#xff0c…

核显硬刚RTX 4070,AMD全新APU杀疯了

这年头&#xff0c;一台平民玩家低预算主流桌面电脑主机是什么配置&#xff1f; Intel i5 12400F CPU、B760 主板、NVIDIA RTX 4060 显卡、双 8G DDR4 内存、1T 固态硬盘的组合&#xff0c;想必相当具有代表性了吧&#xff01; 但仔细掰开后我们不难发现&#xff0c;这套不到…

生物信息学入门:Linux学习指南

还没有使用过生信云服务器&#xff1f;快来体验一下吧 20核心256G内存最低699元半年。 更多访问 https://ad.tebteb.cc 介绍 大家好&#xff01;作为一名生物信息学的新人&#xff0c;您可能对Linux感到陌生&#xff0c;但别担心&#xff0c;本教程将用简单明了的方式&#xff…

Cache结构

Cache cache的一般设计 超标量处理器每周期需要从Cache中同时读取多条指令&#xff0c;同时每周期也可能有多条load/store指令会访问Cache&#xff0c;因此需要多端口的Cache L1 Cache&#xff1a;最靠近处理器&#xff0c;是流水线的一部分&#xff0c;包含两个物理存在 指…

解决windows安装docker desktop打开报错问题

下载docker windows版本: https://desktop.docker.com/win/main/amd64/Docker%20Desktop%20Installer.exe?utm_sourcedocker&utm_mediumwebreferral&utm_campaigndd-smartbutton&utm_locationmodule 正常安装&#xff0c;然后运行&#xff0c;弹出这个报错: 试了…

力扣 两数之和

致每一个初学算法的你。 题目 时间复杂度&#xff1a;O(N^2)&#xff0c; 空间复杂度&#xff1a;O(1) 。 class Solution {public int[] twoSum(int[] nums, int target) {int n nums.length;for (int i 0; i < n; i) {for (int j i 1; j < n; j) {if (nums[i] …

RK3568平台开发系列讲解(文件系统篇)Linux内核中 文件的三个数据结构

在内核中,与文件描述符相关的三个主要数据结构分别是: 文件描述符表(进程级):这是每个进程所拥有的数据结构,用于维护进程中打开的所有文件描述符。每个 fd 在这个表中都有一个对应的条目,指向更底层的文件表示结构。 打开文件列表(系统级):这是一个全系统范围内的数…

DC-5靶场实战模拟

信息收集 端口和网段信息&#xff1a;使用nmap扫描 //扫描网段中存货的主机 nmap -sP 192.168.10.0/24 //进行对主机进行猜测-》发现接口&#xff1a;80存活 nmap -sV 192.168.10.245 目录信息 &#xff1a;使用dirbuster 指纹信息 找漏洞 发现web 中contact有提交界面进行…

[设备] 关于手机设备中几种传感器的研究

一、手机设备中三位坐标系概念 X轴的方向&#xff1a;沿着屏幕水平方向从左到右&#xff0c;如果手机如果不是是正方形的话&#xff0c;较短的边需要水平 放置&#xff0c;较长的边需要垂直放置。Y轴的方向&#xff1a;从屏幕的左下角开始沿着屏幕的的垂直方向指向屏幕的顶端Z轴…

linux操作——yum、systemctl、firewall、hostname、、、

一、什么是yum yum是一种在Linux操作系统中使用的软件包管理器。它可以用来从软件仓库中下载、安装、更新和删除软件包。yum可以自动解决软件包之间的依赖关系&#xff0c;并且可以方便地查找和安装各种软件。在大多数基于Red Hat的Linux发行版中&#xff0c;如CentOS和Fedora&…

牛客 JZ31.栈的压入,弹出序列 C++写法

牛客 JZ31.栈的压入&#xff0c;弹出序列 C写法 思路&#x1f914;&#xff1a; 创建一个栈&#xff0c;push压入序列&#xff0c;然后用栈顶跟弹出序列比&#xff0c;如果一样就出栈并且继续比较&#xff0c;不一样就再次push入栈&#xff0c;直到压入序列走完&#xff0c;如果…

部署伪分布式 Hadoop集群

部署伪分布式 Hadoop集群 一、JDK安装配置1.1 下载JDK1.2 上传解压1.3 java环境配置 二、伪分布式 Hadoop 安装配置2.1 Hadoop 下载2.2 上传解压2.3 Hadoop 文件目录介绍2.4 Hadoop 配置2.4.1 修改 core-site.xml 配置文件2.4.2 修改 hdfs-site.xml 配置文件2.4.3 修改 hadoop-…

【从零开始一步步学习VSOA开发】URL 资源标识

URL 资源标识 概念 在 VSOA 的世界里&#xff0c;所有的差异化均得到统一&#xff0c;所有的硬件、软件服务均提供统一的资源标签 URL。类似 http://&#xff0c;VSOA 的 URL 以 vsoa:// 开始。下面通过 2 个例子介绍 VSOA 统一资源标识的好处&#xff1a; 匹配规则 URL 标…

Modbus poll和Modbus Mbslave的使用

读取Modbus Mbslave中的数据 首先创建COM1和COM2端口 然后 using System.IO.Ports; ​ namespace 通信 {internal class Program{static void Main(string[] args){Console.WriteLine("Hello, World!");SerialPort serialPort new SerialPort("COM1",960…

前缀和专题

板子&#xff1a; &#xff08;占坑&#xff09; Leetcode 238. 除自身以外数组的乘积 优化前&#xff1a;使用前后缀数组记录 class Solution { public:vector<int> productExceptSelf(vector<int>& nums) {int n nums.size();vector<int> pre(n, 1),…

JMeter 压测Http接口

前言 今天产品在会议上吐槽说我们的服务接口连一点点压力都扛不住&#xff0c;用户稍微用下翻译功能&#xff0c;就报错 429。我一听 429 就觉得不对劲&#xff0c;明明4xx 的错误码应该找前端才对的&#xff0c;怎么能找我这个前端后端运维测试工程师呢&#xff1f; 如果是产…

如何在生成式AI里使用 Ray Data 进行大规模 RAG 应用的 Embedding Inference

检索增强生成 (RAG) 是企业级生成式 AI&#xff08;GenAI&#xff09;应用的热门案例之一。多数 RAG 教程演示了如何利用 OpenAI API 结合 Embedding 模型和大语言模型&#xff08;LLM&#xff09;来进行推理&#xff08;Inference&#xff09;。然而&#xff0c;在开发过程中&…

【第16章】Spring Cloud之Gateway全局过滤器(安全认证)

文章目录 前言一、公共模块1. 引入依赖2. 工具类 二、用户服务1. 新建模块2. 引入依赖3. 启动类4. 基本配置5. 登录接口 三、网关服务1. 引入依赖2. 应用配置3. 自定义过滤器 四、单元测试1.介绍2. 登录接口3. 提供者接口3.1 无token3.2 有token 总结 前言 我们已经接入了网关…