Python程序设计 魔法函数

1.魔法方法

Python中有一些特殊方法,它们允许我们的类和Python更好地集成。在标准库参考(Standard Library Reference)中,它们被称为魔法方法(Magic Methods),是与Python的其他特性无缝集成的基础。

例如,我们用字符串来表示一个对象的值。Object 基类包含了__repr__() 和__str__() 的默认实现,它们提供了一个对象的字符串描述。遗憾的是,这些默认的实现不够详细。我们几乎总会想重写它们中的一个或两个。我们还会介绍__format__() ,它更加复杂一些,但是和上面两个方法的作用相同。

我们还会介绍其他的转换方法,尤其是__hash__() 、__bool__() 和__bytes__() 。这些方法可以把一个对象转换成一个数字、一个布尔值或者一串字节。例如,当我们实现了__bool__() ,我们就可以像下面这样在if语句中使用我们的对象:if someobject: 。

接下来,我们会介绍实现了比较运算符的几个特殊方法:__lt__() 、__le__() 、__eq__() 、__ne__() 、__gt__() 和__ge__() 。

当我们定义一个类时,几乎总是需要使用这些基本的特殊方法。

我们会在最后介绍__new__() 和__del__() ,因为它们的使用更加复杂,而且相比于其他的特殊方法,我们并不会经常使用它们。

我们会详细地介绍如何用这些特殊方法来扩展一个简单类。我们需要了解从object 继承而来的默认行为,这样,我们才能理解应该在什么时候使用重写,以及如何使用它。

说白了就是对象的 我是谁,我从哪里来,到哪里去

1.1__init__()

所有类的超类object,有一个默认包含pass的__init__()实现,这个函数会在对象初始化的时候调用,我们可以选择实现,也可以选择不实现,一般建议是实现的,不实现对象属性就不会被初始化,虽然我们仍然可以对其进行赋值,但是它已经成了隐式的了,编程时显示远比隐式的更好

1.2__new__()

__new__() 方法作为元类型的一部分,主要是为了控制如何创建一个类。这和之前的如何用 __new__() 控制一个不可变对象是完全不同的。

一个元类型创建一个类。一旦类对象被创建,我们就可以用这个类对象创建不同的实例。所有类的元类型都是type ,type() 函数被用来创建类对象。

另外,type() 函数还可以被用作显示当前对象类型。

下面是一个很简单的例子,直接使用 type() 作为构造器创建了一个新的但是几乎完全没有任何用处的类:

Useless= type("Useless",(),{})

一旦我们创建了这个类,我们就可以开始创建这个类的对象。但是,这些对象什么都做不了,因为我们没有定义任何方法和属性。

为了最大化利用这个类,在下面的例子中,我们使用这个新创建的Useless 类来创建对象。

>>> Useless()
<__main__.Useless object at 0x101001910>
>>> u=_
>>> u.attr= 1 
>>> dir(u)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', 
'__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', 
'__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', 
'__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', 
'__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'attr']

我们可以向这个类的对象中增加属性。至少,作为一个对象,它工作得很好。

这样的类定义与使用types.SimpleNamespace 或者像下面这样定义一个类的方式几乎相同。

class Useless:pass

1.3__repr__()

__repr__() 和 __str__() 方法

对于一个对象,Python提供了两种字符串表示。它们和内建函数repr() 、str() 、print() 及string.format() 的功能是一致的。

  • 通常,str() 方法表示的对象对用户更加友好。这个方法是由对象的__str__ 方法实现的。

  • repr() 方法的表示通常会更加技术化

这个方法是由__repr__() 方法实现的。

  • print() 函数会调用str() 来生成要输出的对象。
  • 字符串的format() 函数也可以使用这些方法。当我们使用{!r} 或者{!s} 格式时,我们实际上分别调用了__repr__() 或者__str__() 方法。

下面我们先来看一下这些方法的默认实现。

直接打印对象的实现方法,__str__ 是被print函数调用的,一般都是return一个什么东西,这个东西应该是以字符串的形式表现的。如果不是要用str()函数转换,我们可以直接print的对象都是实现了`__str__这个方法的,比如dict。看下面的例子。

下面是一个很简单的类。

class RectAngle:def __init__(self, width, height):self.width = widthself.height = heightdef area(self):return self.width * self.heightdef __str__(self):return f'<RectAngle: {self.width}(w) * {self.height}(h)>'

我们定义了两个简单类,每个类包含4个属性。

下面是在命令行中使用RectAngle 类的结果。

>>> rect = RectAngle(4, 5)
>>> print(rect)
<RectAngle: 4(w) * 5(h)>
>>> rect
<__main__.RectAngle object at 0x000002A1547E5A58>

可以看到,__str__() print 方法打印的内容就看起来更加输入,但是在命令行里面里面的调试信息还是现实的为对象,当增加 __repr__() 方法之后,调试信息也会变得更加清楚

def __repr__(self):return f'<RectAngle: w{self.width} h{self.height}>'

在以下两种情况下,我们可以考虑重写__str__() 和__repr__() 。

  • 非集合对象 :一个不包括任何其他集合对象的“简单”对象,这类对象的格式化通常不会特别复杂。
  • 集合对象 :一个包含集合的对象,这类对象的格式化会更为复杂。

1.4__bool__()

Python中有很多关于真假性的定义。参考手册中列举了许多和False 等价的值,包括False 、0 、'' 、() 、[] 和{} 。其他大部分的对象都和True 等价。

通常,我们会用下面的语句来测试一个对象是否“非空”。

if some_object:process( some_object )

默认情况下,这个是内置的bool() 函数的逻辑。这个函数依赖于一个给定对象的__bool__() 方法。

默认的__bool__() 方法返回True 。我们可以通过下面的代码来验证这一点。

>>> x = object()
>>> bool(x)
True

对大多数类来说,这是完全正确的。大多数对象都不应该和False 等价。但是,对于集合,这样的行为并不总是正确的。一个空集合应该和False 等价,而一个非空集合应该返回True 。或许,应该给我们的Deck 集合对象增加一个类似的方法。

如果我们在封装一个列表,我们可能会写下面这样的代码。

    def __bool__(self):return bool(self.area)

这段代码将__bool__() 的计算委托给了内部的函数area 。

现在,我们就可以像下面这样使用Deck 。

r = RectAngle(4, 5)if r:print(r)

2.比较运算符方法

Python有6个比较运算符。这些运算符分别对应一个特殊方法的实现。根据文档,运算符和特殊方法的对应关系如下所示。

  • x > y 调用x.__gt__(y) 。
  • x >= y 调用x.__ge__(y) 。

  • x < y 调用x.__lt__(y) 。

  • x <=y 调用x.__le__(y) 。
  • x == y 调用x.__eq__(y) 。
  • x != y 调用x.__ne__(y) 。

对于实际上使用了哪个比较运算符,还有一条规则。这些规则依赖于作为左操作数的对象定义需要的特殊方法。如果这个对象没有定义,Python会尝试改变运算顺序。

下面是两条基本的规则: 首先,运算符的实现基于左操作数:A < B相当于A.__lt__(B) 。 其次,相反的运算符的实现基于右操作数:A < B相当于B.__gt__(A) 。 如果右操作数是左操作数的一个子类,那这样的比较基本不会有什么异常发生;同时,Python会首先检测右操作数,以确保这个子类可以重载基类。

下面,我们通过一个例子看看这两条规则是如何工作的,我们定义了一个只包含其中一个运算符实现的类,然后把这个类用于另外一种操作。

下面是我们使用类中的一段代码。

class RectAngle:def __init__(self, width, height):self.width = widthself.height = heightdef area(self):return self.width * self.heightdef __gt__(self, other):# other 是另外一个对象return self.area() < self.area()

这段代码基于 RectAngle(矩形) 的比较规则,主要是对比三角形的大小。

我们省略了比较方法,看看当缺少比较运算符时,Python将如何回退。这个类允许我们进行<比较。但是有趣的是,通过改变操作数的顺序,Python也可以使用这个类进行>比较。换句话说,x <y 和y >x 是等价的。这遵从了镜像反射法则;

当我们试图评估不同的比较运算时就会看到这种现象。下面,我们创建两个RectAngle 类,然后用不同的方式比较它们。

>>> r1 = RectAngle(4, 5)
>>> r2 = RectAngle(5, 6)
>>> r1 > r2
True
>>> r1 < r2
False
>>> r1 == r2
False

从代码中,我们可以看到,r1 < r2 调用了r1.__lt__(three) 。

但是,对于r1 > three ,由于没有定义__gt__() ,Python使用r2.__lt__(two) 作为备用的比较方法。

默认情况下,__eq__() 方法从object 继承而来,它比较不同对象的ID值。当我们用于==或!=比较对象时,结果如下。

>>> r1_2 = RectAngle(4, 5)
>>> r1_2 == r1
False

可以看到,结果和我们预期的不同。所以,我们通常都会需要重载默认的__eq__() 实现。

此外,逻辑上,不同的运算符之间是没有联系的。但是从数学的角度来看,我们可以基于两个运算符完成所有必需的比较运算。Python没有实现这种机制。相反,Python默认认为下面的4组比较是等价的。

x < y ≡ y > x

x ≤ y ≡ y ≥ x

x = y ≡ y = x

x ≠ y ≡ y ≠ x

这意味着,我们必须至少提供每组中的一个运算符。例如,我可以提供__eq__() 、__ne__() 、__lt__() 和__le__() 的实现。

2.1比较运算

当设计比较运算符时,要考虑两个因素。

  • 如何比较同一个类的两个对象。
  • 如何比较不同类的对象。

对于一个有许多属性的类,当我们研究它的比较运算符时,通常会觉得有很明显的歧义。或许这些比较运算符的行为和我们的预期不完全相同。

2.2同类比较

下面我们通过一个更完整的RectAngle 类来看一下简单的同类比较。

# encoding:utf-8
class RectAngle:def __init__(self, width, height):self.width = widthself.height = heightdef area(self):return self.width * self.heightdef __lt__(self, other):return self.area() > other.area()def __le__(self, other):return self.area() <= other.area()def __gt__(self, other):# other 是另外一个对象return self.area() < other.area()def __ge__(self, other):return self.area() >= other.area()def __eq__(self, other):return self.area() == other.area()def __ne__(self, other):return self.area() != other.area()r1 = RectAngle(4, 5)
r2 = RectAngle(5, 6)print(r1 > r2)
print(r1 < r2)

现在我们定义了6个比较运算符。

我们也没有给出类内比较的代码,这个我们会在下一个部分中详细讲解。用上面定义的这个类,我们可以成功地比较不同的牌。下面是一个创建并比较3张牌的例子。

>>> r1 = RectAngle(4, 5)
>>> r2 = RectAngle(5, 6)
>>> r3 = RectAngle(4, 6)

用上面定义的RectAngle 类,我们可以进行像下面这样的一系列比较。

>>> r1 == r2
False
>>> r1.width == r3.width
True
>>> r1 < r3
False

这个类的行为与我们预期的一致。

2.3不同类比较

我们会继续以RectAngle 类为例来看看当两个比较运算中的两个操作数属于不同的类时会发生什么。新增一个三角形对象

class Triangle:def __init__(self, width, height):self.width = widthself.height = heightdef area(self):return self.width * self.height / 2def __lt__(self, other):return self.area() > other.area()def __eq__(self, other):return self.area() == other.area()

下面我们将一个RectAngle 实例和一个Triangle 值进行比较。

>>> r1 = RectAngle(4, 5)
>>> t1 = Triangle(4, 5)
>>> r1 == t1
>>> r1 + t1
Traceback (most recent call last):File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'RectAngle' and 'Triangle'
>>>

可以看到,这和我们预期的行为一致,RectAngle 的子类Triangle 没有实现必需的特殊方法,所以产生了一个TypeError 异常。

3.__call__()

该方法的功能类似于在类中重载 () 运算符,使得类实例对象可以像调用普通函数那样,以“对象名()”的形式使用。

class Example:def __call__(self, *args, **kwargs):return "hello world !"e = Example()print(e)
print(e())

4.__del__() 方法

__del__() 方法有一个让人费解的使用场景。

这个方法的目的是在将一个对象从内存中清除之前,可以有机会做一些清理工作。对于Python的垃圾回收机制而言,创建一个上下文比使用 __del__() 更加容易预判。

但是,如果一个Python对象包含了一些操作系统的资源,__del__() 方法是把资源从程序中释放的最后机会。例如,引用了一个打开的文件、安装好的设备或者子进程的对象,如果我们将资源释放作为__del__() 方法的一部分实现,那么我们就可以保证这些资源最后会被释放。

很难预测什么时候 __del__() 方法会被调用。它并不总是在使用del 语句删除对象时被调用,当一个对象因为命名空间被移除而被删除时,它也不一定被调用。Python文档中用不稳定来描述 __del__() 方法的这种行为,并且提供了额外的关于异常处理的注释:运行期的异常会被忽略,相对地,会使用 sys.stderr 打印一个警告。

基于上面的这些原因,通常更倾向于使用上下文管理器,而不是实现 __del__() 。

4.1 引用计数和对象销毁

CPython的实现中,对象会包括一个引用计数器。当对象被赋值给一个变量时,这个计数器会递增;当变量被删除时,这个计数器会递减。当引用计数器的值为0时,表示我们的程序不再需要这个对象并且可以销毁这个对象。对于简单对象,当执行删除对象的操作时会调用 __del__() 方法。

对于包含循环引用的复杂对象,引用计数器有可能永远也不会归零,这样就很难让 __del__() 被调用。

我们用下面的一个类来看看这个过程中到底发生了什么。

class RectAngle:def __init__(self, width, height):self.width = widthself.height = heightdef __del__(self):print("被删除 {0}".format(id(self)))

我们可以像下面这样创建和删除这个对象。

>>> p = RectAngle(4, 5)
>>> del p
被删除 2643407508256

我们先创建,然后删除了Noisy 对象,几乎是立刻就看到了__del__() 方法中输出的消息。这也就是说当变量x 被删除后,引用计数器正确地归零了。一旦变量被删除,就没有任何地方引用Noisy 实例,所以它也可以被清除。

下面是浅复制中一种常见的情形。

>>> ln = [RectAngle(4, 5), RectAngle(4, 6)]
>>> ln2= ln.copy()
>>> del ln
>>>

Python没有响应del 语句。这说明这些Noisy 对象的引用计数器还没有归零,肯定还有其他地方引用了它们,下面的代码验证了这一点。

>>> del ln2
被删除 2643407508592
被删除 2643407508480

4.2 循环引用和垃圾回收

下面是一种常见的循环引用的情形。一个父类包含一个子类的集合,同时集合中的每个子类实例又包含父类的引用。

下面我们用这两个类来看看循环引用。

class Parent:def __init__(self, *children):self.children = list(children)for child in self.children:child.parent = selfdef __del__(self):print("删除 {} {}".format(self.__class__.__name__, id(self)))class Child:def __del__(self):print("删除 {} {}".format(self.__class__.__name__, id(self)))

一个Parent 的instance 包括一个children 的列表。

每一个Child 的实例都有一个指向Parent 类的引用。当向Parent 内部的集合中插入新的Child 实例时,这个引用就会被创建。

我们故意把这两个类写得比较复杂,所以下面让我们看看当试图删除对象时,会发生什么。

>>> p = Parent(Child(), Child())
>>> id(p)
2643407508984
>>> del p
>>>

Parent 和它的两个初始Child 实例都不能被删除,因为它们之间互相引用。

下面,我们创建一个没有Child 集合的Parent 实例。

>>> p= Parent()
>>> id(p)
2643407509096
>>> del p
删除 Parent 2643407509096
>>>

和我们预期的一样,这个Parent 实例成功地被删除了。

许多基本的特殊方法,它们是我们在设计任何类时的基本特性。这些方法已经包含在每个类中,只是它们的默认行为不一定能满足我们的需求。

我们几乎总是需要重载__repr__() 、__str__() 。这些方法的默认实现不是非常有用。

我们几乎不需要重载__bool__() 方法,除非我们想自定义集合。这是第6章“创建容器和集合”的主题。

我们常常需要重载比较运算符。默认的实现只适合于比较简单不可变对象,但是不适用于比较可变对象。我们不一定要重写所有的比较运算符

另外两个较为特殊的方法__new__() 和__del__() 有更特殊的用途。大多数情况下,使用__new__() 来扩展不可变类型。

基本的特殊方法和__init__() 方法几乎会出现在我们定义的所有类中。其他的特殊方法则有更特殊的用途,它们分为6个不同的类别。

  • 属性访问 :这些特殊方法实现的是表达式中object.attribute 的部分,它通常用在一个赋值语句的左操作数以及del 语句中。
  • 可调用对象 :一个实现了将函数作为参数的特殊方法,很像内置的len() 函数。
  • 集合 :这些特殊方法实现了集合的很多特性,包括sequence[index] 、mapping[index] 和set | set 。
  • 数字 :这些特殊方法提供了算术运算符和比较运算符。我们可以用这些方法扩展Python支持的数值类型。
  • 上下文 :有两个特殊方法被我们用来实现可以和with 语句一起使用的上下文管理器。
  • 迭代器 :有一些特殊方法定义了一个迭代器。没有必要一定要使用这些方法,因为生成器函数很好地实现了这种特性。但是,我们可以了解如何实现自定义的迭代器。

5. 重要的魔法方法

下面的表格列出了 Python 3中的重要魔法方法。

初始化和构建描述
__new__(mcs, other)在对象的实例化中被调用
__init__(self, other)使用 __new__ 调用
__del__(self)删除方法
一元运算符和函数描述
__pos__(self)+(正数)
__neg__(self)- (负数)
__abs__(self)abs() 函数
__invert__(self)~ 操作符
__round__(self,n)round() 取整
__floor__(self)math.floor() 函数
__ceil__(self)math.ceil() 函数
__trunc__(self)math.trunc() 函数
增强赋值描述   
__iadd__(self, other)+=
__isub__(self, other)-=
__imul__(self, other)*=
__ifloordiv__(self, other)//=
__idiv__(self, other)a /=b
__itruediv__(self, other)
__imod__(self, other)%=
__ipow__(self, other)**=
__ilshift__(self, other)<<=
__irshift__(self, other)>>=
__iand__(self, other)&=
__ior__(self, other)|=
__ixor__(self, other)^=
类型转化魔法方法描述
__int__(self)int()方法调用来将类型转换为
int__float__(self)float()方法调用以将类型转换为
float__complex__(self)Tcomplex() 方法调用以将类型转换为 complex
__oct__(self)oct() 方法调用以将类型转换为八进制
__hex__(self)hex() 方法调用以将类型转换为十六进制
__index__(self)在切片中自动调用
__trunc__(self)math.trunc ()方法调用
字符串魔法方法         描述
__str__(self)str()方法调用以返回类型的字符串表示形式
__repr__(self)repr()方法调用,以返回类型的机器可读表示形式
__unicode__(self)unicode() 方法调用以返回类型的 unicode 字符串
__format__(self, formatstr)string.format() 方法调用,以返回一个新样式的字符串
__hash__(self)hash() 方法调用以返回整数
__nonzero__(self)bool() 方法调用以返回 True 或 False
__dir__(self)dir() 方法调用以返回类的属性列表
__sizeof__(self)sys.getsizeof()方法调用,以返回对象的大小
属性操作魔法方法描述
__getattr__(self, name)当类的访问属性不存在时调用
__setattr__(self, name, value)在为类的属性赋值时调用
__delattr__(self, name)在删除类的属性时调用
运算魔法方法描述
__add__(self, other)使用 + 运算符在比较时调用
__sub__(self, other)使用 - 运算符在比较时调用
__mul__(self, other)使用 * 运算符在比较时调用
__floordiv__(self, other)使用 // 运算符在比较时调用
__divmod__(self, other)使用 / 运算符在比较时调用
__mod__(self, other)使用 % 运算符在比较时调用
__pow__(self, other[, modulo])使用 ** 运算符在比较时调用
__lt__(self, other)使用 < 运算符在比较时调用
__le__(self, other)使用 <= 运算符在比较时调用
__eq__(self, other)使用 == 运算符在比较时调用
__ne__(self, other)使用 != 运算符在比较时调用
__ge__(self, other)使用 >= 运算符在比较时调用

因此,您可以使用适当的魔法方法在自定义类中添加各种功能。

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

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

相关文章

蓝桥杯备考

目录 P8823 [传智杯 #3 初赛] 期末考试成绩 题目描述 输入格式 输出格式 输入输出样例 说明/提示 代码 P8828 [传智杯 #3 练习赛] 直角三角形 题目描述 输入格式 输出格式 输入输出样例 代码 P8833 [传智杯 #3 决赛] 课程 题目背景 题目描述 输入格式 输出格式…

vivado eFUSE 寄存器访问和编程

eFUSE 寄存器访问和编程 注释 &#xff1a; 在 MPSoC 和 Versal 器件上不支持以下 eFUSE 访问和编程方法。 7 系列、 UltraScale 和 UltraScale 器件具有一次性可编程位用于执行特定功能 &#xff0c; 称为 eFUSE 位。不同 eFUSE 位类型如 下所述&#xff1a; • …

突破校园网限速:使用 iKuai 多拨分流负载均衡 + Clash 代理(内网带宽限制通用)

文章目录 1. 简介2. iKuai 部署2.1 安装 VMware2.2 安装 iKuai(1) 下载固件(2) 安装 iKuai 虚拟机(3) 配置 iKuai 虚拟机(4) 配置 iKuai(5) 配置多拨分流 2.3 测试速度 3. Clash 部署3.1 准备工作(1) 配置磁盘分区(2) 安装 Docker(3) 安装 Clash(4) 设置代理 1. 简介 由于博主…

新质生产力丨zData X 数据库一体机助力财政一体化平台全面升级

在数字化转型的大潮中&#xff0c;某财政局积极响应国家财政管理现代化的战略部署&#xff0c;启动了财政一体化平台升级改造工程。该项目旨在将财政局内部各部门及其各自独立的业务系统进行全面整合&#xff0c;构建起一个集约化的财政管理平台&#xff0c;力求通过技术创新推…

字符分类函数

字符分类函数 C语言中有⼀系列的函数是专门做字符分类的&#xff0c;也就是⼀个字符是属于什么类型的字符的。这些函数的使用都需要包含⼀个头文件是 ctype.h 这些函数的使用方法非常类似&#xff0c;我们就讲解⼀个函数的事情&#xff0c;其他的非常类似&#xff1a; int i…

合同约定的绩效奖金说不给就不给了, 这合法吗?

目录 一、北京海淀法院参考案例 二、关于绩效奖金的性质&#xff1f; 三、绩效奖金应否发放取决于哪些因素&#xff1f; 四、员工如何举证与质证 五、提前离职的员工 是否享受当年度绩效奖金&#xff1f; 一、北京海淀法院参考案例 https://mp.weixin.qq.com/s/sq0mFCC8M…

在哪申请免费IP地址证书

IP证书&#xff0c;也被称为IP SSL证书&#xff0c;是一种特殊的SSL证书&#xff0c;不同于传统的域名验证&#xff08;DV&#xff09;证书&#xff0c;它是通过验证公网IP地址而不是域名来确保安全连接。这种证书是用于保护IP地址&#xff0c;并在安装后起到加密作用。 申请条…

数据结构算法题(力扣)——链表

以下题目建议大家先自己动手练习&#xff0c;再看题解代码。这里只提供一种做法&#xff0c;可能不是最优解。 1. 移除链表元素&#xff08;OJ链接&#xff09; 题目描述&#xff1a;给一个链表的头节点 head 和一个整数 val &#xff0c;删除链表中所有满足值等于 val 的节点…

全面的Docker快速入门教程(详细)

前言&#xff1a; 都2024年了&#xff0c;你还在为了安装一个开发或者部署环境、软件而花费半天的时间吗&#xff1f;你还在解决开发环境能够正常访问&#xff0c;而发布测试环境无法正常访问的问题吗&#xff1f;你还在为持续集成和持续交付&#xff08;CI / CD&#xff09;工…

代码随想录第29天|491.递增子序列 46.全排列 47.全排列 II

目录&#xff1a; 491.递增子序列 46.全排列 47.全排列 II 491.递增子序列 491. 非递减子序列 - 力扣&#xff08;LeetCode&#xff09; 代码随想录 (programmercarl.com) 回溯算法精讲&#xff0c;树层去重与树枝去重 | LeetCode&#xff1a;491.递增子序列_哔哩哔哩_bili…

2023最新汽车网络安全报告汇总

2023最新汽车网络安全报告、安全参考架构及指南汇总&#xff0c;供大家学习参考。https://t.zsxq.com/18RkG260k 汽车信息安全法律法规及标准全景图V3.2.pdf 车载智能计算基础平台参考架构2.0.pdf 车载智能计算芯片白皮书(2023版).pdf 智能驾驶行为安全评价方法发布版.pdf 智能…

超细节小白教学Windows10系统 数据库MYSQL服务安装及验证

超细节小白教学Windows10系统 数据库MYSQL服务安装 一、MySQL下载及安装 官网下载地址&#xff1a;https://dev.mysql.com/downloads/mysql/ 进入官网页面如下图所示&#xff1a; 一般64-bit代表64位系统&#xff0c;如果需要32位系统可以在历史版本中寻找。 等待下载完成&a…

【协议篇:Http与Https】

1. Http 1.1 Http的定义 超文本传输协议&#xff08;Hypertext Transfer Protocol&#xff0c;HTTP&#xff09;是用于分布式、协作式和超媒体信息系统的应用层协议。它是互联网上最广泛应用的数据通信协议之一&#xff0c;尤其对于万维网&#xff08;WWW&#xff09;服务而言…

5.动态规划

1.背包问题 (1)0/1背包问题 01背包问题即每个物品只能选1个 考虑第i件物品&#xff0c;当j<w[i]时&#xff0c;f[i][j]f[i-1][j]&#xff0c;当j>w[i]时&#xff0c;此时有两种选择&#xff0c;选择第i件物品和不选第i件物品。此时f[i][j]max(f[i-1][j],f[i-1][j-w[i]]v…

【QingHub】QingHub Studio企业级应用作业编排

简介 QingHub作业编排中心是一个通过插件化方式&#xff0c;提供数据从采集&#xff0c;转化&#xff0c;计算&#xff0c;存储为一体的全流程数据处理方案&#xff0c;他一方面为前端应用提供数据源&#xff0c;同时也为前端应用与数据源头的通信搭建起桥梁&#xff0c;实现数…

【WebKit架构讲解】

&#x1f308;个人主页:程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

C++:函数重载,引用

文章目录 1. 函数重载1.1 函数重载概念1.2 C支持函数重载的原理--名字修饰1.3 缺省参数与重载 2. 引用2.1引用概念2.2 引用特性2.3 常引用2.4 使用场景2.5 引用和指针的区别 1. 函数重载 1.1 函数重载概念 C允许在同一作用域中声明几个功能类似的同名函数&#xff0c;这些同名…

查看并设定【网络适配器】的优先级(跃点数)

目录 前言&#xff1a; 1.查看所有的适配器 2.修改优先级&#xff08;需要以管理员身份运行&#xff09; 跃点数&#xff08;InterfaceMetric &#xff09; DHCP 3.修改后的效果 pwoerShell 再次运行之前的程序 4.其他 参考 网络适配器1&#xff0c;8相关知识介绍1 …

回溯算法|47.全排列II

力扣题目链接 class Solution { private:vector<vector<int>> result;vector<int> path;void backtracking (vector<int>& nums, vector<bool>& used) {// 此时说明找到了一组if (path.size() nums.size()) {result.push_back(path);r…

【前端】CSS(引入方式+选择器+常用元素属性+盒模型)

文章目录 CSS一、什么是CSS二、语法规范三、引入方式1.内部样式表2.行内样式表3.外部样式 四、选择器1.选择器的种类1.基础选择器&#xff1a;单个选择器构成的1.标签选择器2.类选择器3.id 选择器4.通配符选择器 2.复合选择器1.后代选择器2.子选择器3.并集选择器4.伪类选择器 五…