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

文章目录

  • 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 = nameself.age = ageself.id = iddef 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 instancedef __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 instancedef __init__(self,name,age,id) -> None:self.name = nameself.age = ageself.id = idprint("__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 = nameself.age = ageself.id = iddef __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 = nameself.age = ageself.id = idstu = 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 = nameself.age = ageself.id = iddef __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 = nameself.age = ageself.id = iddef __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 = nameself.age = ageself.id = iddef __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] = valuedef __str__(self) -> str:obj_str = str()# 遍历字典中的键值对for key, value in self.my_dict.items():obj_str = obj_str + f"{key} = {value} "return obj_strstu = 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 = nameself.age = ageself.id = iddef __lt__(self, other: object) -> bool:# 使用对象中的age属性来比较大小return self.age < other.agedef __eq__(self, other: object) -> bool:# 使用对象中的age属性来比较大小return self.age == other.agestu1 = 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 = 0def __iter__(self):print("__iter__被执行了...")return selfdef __next__(self):print("__next__被执行了...")if self.start >= len(self.data):# raise StopIteration用于提前终止一个迭代器中的循环raise StopIterationitem = self.data[self.start]self.start += 1return itemobj_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 = nameself.age = ageself.id = iddef __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 = _agedef __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 = _agedef __setattr__(self,key, value):self.key = valuestu = Student(16)

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

class Student:def __init__(self,name,age,id) -> None:self.name = nameself.age = ageself.id = iddef __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 selfdef 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 selfdef 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 computeprint(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.rhkb.cn/news/393282.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux用户-普通用户

作者介绍&#xff1a;简历上没有一个精通的运维工程师。希望大家多多关注我&#xff0c;我尽量把自己会的都分享给大家&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 Linux是一个多用户多任务操作系统,这意味着它可以同时支持多个用户登录并使用系统。…

微信小程序实现上传照片功能

案例&#xff1a; html: <view class"zhengjianCont fontSize30" style"margin-bottom: 40rpx;"><view class"kuai"><image binderror"imageOnloadError" bind:tap"upladPhoto" data-params"business…

杂谈c语言——3.内存对齐

先看两个例子&#xff1a; typedef struct S {int a;double b;char c; }S;typedef struct B {int a;char b;double c; }B;int main() {printf("S : %d\n", sizeof(S));printf("B : %d\n", sizeof(B));return 0; } 结果为&#xff1a; S:24; B:16&#xff…

常用在线 Webshell 查杀工具推荐

一、简介 这篇文章将介绍几款常用的在线 Webshell 查杀工具&#xff0c;包括长亭牧云、微步在线云沙箱、河马和VirusTotal。每个工具都有其独特的特点和优势&#xff0c;用于帮助用户有效检测和清除各类恶意 Webshell&#xff0c;保障网站和服务器的安全。文章将深入探讨它们的…

【Redis】String字符串

目录 String字符串 常见命令 SET GET MSET MGET SETNX 计数命令 INCR INCRBY DECY DECYBY INCRBYFLOAT 其他命令 APPEND GETRANGE SETRANGE STRLEN 内部编码 String类型的典型使用场景 缓存(Cache)功能 计数功能 共享会话(Session) String字符串 字符…

类和对象(下)C++

1.初始化列表 1.为什么有初始化列表&#xff0c;它的作用&#xff1f; ->初始化列表&#xff0c;是构造函数初始化的另一种形式。 ->在语法上面理解&#xff0c;初始化列表可以认定为是每个成员变量定义初始化的地方. ->引用成员变量&#xff0c;const成员变量&am…

Qt实现简易CAD软件的开发:技术解析与实现

文章目录 简易CAD软件的开发&#xff1a;技术解析与实现引言项目概述程序入口主窗口的实现主窗口类定义&#xff08;mainwindow.h&#xff09;主窗口类实现&#xff08;mainwindow.cpp&#xff09; 自定义绘图视图自定义绘图视图类定义&#xff08;myqgraphicsview.h&#xff0…

亚信安全获国家信息安全服务(风险评估和安全工程类)二级资质

近日&#xff0c;亚信安全荣获由中国信息安全测评中心颁发的《国家信息安全测评信息安全服务资质证书—风险评估二级》和《国家信息安全测评信息安全服务资质证书—安全工程类二级》资质。亚信安全凭借综合实力和优秀的技术能力&#xff0c;成为为数不多的获得国家信息安全服务…

嵌入式C编程常用的异常错误处理

嵌入式C编程中&#xff0c;异常错误处理是确保系统稳定性和可靠性的重要部分。以下是一些常见的异常错误处理方法及其详细说明和示例&#xff1a; 1. 断言 (Assertions) 断言用于在开发阶段捕获程序中的逻辑错误。通过assert宏&#xff0c;可以在条件不满足时终止程序并输出错…

前端常用的【设计模式】和使用场景

设计原则 最重要的&#xff1a;开放封闭原则 对扩展开放对修改封闭 工厂模式 用一个工厂函数&#xff0c;来创建实例&#xff0c;隐藏 new 如 jQuery 的 $ 函数&#xff0c;React 的 createElement 函数 单例模式 全局唯一的实例(无法生成第二个) 如 Vuex 和 Redux 的 store…

鸿蒙AI功能开发【人脸活体验证控件】 机器学习-场景化视觉服务

人脸活体验证控件 介绍 本示例展示了使用视觉类AI能力中的人脸活体验证能力。 本示例模拟了在应用里&#xff0c;跳转人脸活体验证控件&#xff0c;获取到验证结果并展示出来。 需要使用hiai引擎框架人脸活体验证接口kit.VisionKit.d.ts。 效果预览 使用说明&#xff1a; …

Web性能监测的利器Performance Observer!!

前言 前段时间在研究前端异常监控平台&#xff0c;在思考性能监控时&#xff0c;想到了浏览器自带的观察者以及页面生命周期API 。于是在翻查资料时发现了&#xff0c;Performance ObserverAPI。正好趁着这个机会给大家好好讲讲Performance Observer API Performance Observe…

【python】Scrapy中常见的“Response Not Ready”或“Response Not 200”错误分析及解决

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

吴恩达机器学习笔记

1.机器学习定义&#xff1a; 机器学习就是让机器从大量的数据集中学习&#xff0c;进而得到一个更加符合现实规律的模型&#xff0c;通过对模型的使用使得机器比以往表现的更好 2.监督学习&#xff1a; 从给定的训练数据集中学习出一个函数&#xff08;模型参数&#xff09;…

【Jenkins未授权访问漏洞 】

默认情况下 Jenkins面板中用户可以选择执行脚本界面来操作一些系统层命令&#xff0c;攻击者可通过未授权访问漏洞或者暴力破解用户密码等进入后台管理服务&#xff0c;通过脚本执行界面从而获取服务器权限。 第一步&#xff1a;使用fofa语句搜索 搜索语句&#xff1a; port&…

【八股文】Redis

1.Redis有哪些数据类型 常用的数据类型&#xff0c;String&#xff0c;List&#xff0c;Set&#xff0c;Hash和ZSet&#xff08;有序&#xff09; String&#xff1a;Session&#xff0c;Token&#xff0c;序列化后的对象存储&#xff0c;BitMap也是用的String类型&#xff0c;…

CCRC-CISAW信息安全保障人员证书含金量

在数字化时代背景下&#xff0c;CISAW认证受到越来越多个人的青睐。 特别是在互联网技术高速发展的今天&#xff0c;随着5G技术的广泛应用&#xff0c;市场对CISAW专业人才的需求急剧增加。 这种职业不仅地位显著&#xff0c;而且职业生涯相对较长。 目前市场上&#xff0c;…

【leetcode详解】覆盖所有点的最少矩形数目(C++思路详解)

思路详解&#xff1a; 0. 题目情境并未限制矩形高度&#xff0c;故矩形数目的判断只和点的横坐标有关 1. 为了不重不漏地考虑到所有点&#xff0c;故笔者选择首先将二维数组中的点按横坐标的大小排序 //说明&#xff1a;本来笔者以为需要自定义sort排序&#xff0c;后来发现…

《嵌入式 - 嵌入式大杂烩》ARM Cortex-M寄存器详解

1 ARM Cortex-M寄存器概述 ARM Cortex-M提供了 16 个 32 位的通用寄存器(R0 - R15),如下图所示。前15个(R0 - R14)可以用作通用的数据存储,R15 是程序计数器 PC,用来保存将要执行的指令。除了通用寄存器,还有一些特殊功能寄存器。特殊功能寄存器有预定义的功能,而且必须通…

GPU 片上调度系统

这篇文章分析和说明GPU 片上的kernel 通过stream 作为载体是如何分发到SM 处理器上&#xff0c;同时CUDA 所抽象的grid/block/thread 在GPU 设备层面是如何调度的。调度器通常是被忽略的一个部分&#xff0c;但对CUDA kernel 的编写和后期系统性能分析很有帮助&#xff0c;也可…