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.mzph.cn/news/790181.shtml

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

相关文章

Redis高可用与持久化

目录 一、Redis高可用 二、Redis持久化 1、持久化的功能&#xff1a; 2、Redis 提供两种方式进行持久化&#xff1a; 三、RDB持久化 1、触发条件 1.手动触发 2.自动触发 3.其他自动触发机制 2、执行流程 3、启动时加载 四、AOF持久化 1、开启AOF 2、执行流程 1.…

vue3+elementPlus:实现数字滚动效果(用于大屏可视化)

自行封装注册一个公共组件 案例一&#xff1a; //成功案例&#xff1a; //NumberScroll.vue /* 数字滚动特效组件 NumberScroll */<template><span class"number-scroll-grow"><spanref"numberScroll":data-time"time"class&qu…

构建知识图谱的基石:理解本体和数据模型

构建知识图谱的基石&#xff1a;理解本体和数据模型 一、本体的基本概念 1. 定义与重要性 本体&#xff08;Ontology&#xff09;在计算机科学和信息科学中&#xff0c;尤其是在知识图谱领域&#xff0c;扮演着重要的角色。它提供了一种形式化的描述知识领域的方法&#xff0…

【SpringCloud】Config配置中心

Spring Cloud Config是一个集中的外部配置管理服务器&#xff0c;它支持从各种来源读取配置数据&#xff0c;如Git仓库、本地文件系统、数据库等&#xff0c;并为微服务应用提供统一的配置管理。通过使用Spring Cloud Config&#xff0c;你可以将应用程序的配置信息集中管理&am…

金融案例:构建高效统一的需求登记与管理方案

在金融行业数字化转型背景下&#xff0c;银行等金融机构面临着业务模式创新与数据应用的深度融合。业务上所需要的不再是单纯的数据&#xff0c;而是数据背后映射的业务趋势洞察&#xff0c;只有和业务相结合转化为业务度量指标&#xff0c;经过数据分析处理呈现为报表进行展示…

【零基础C语言】编译和链接

1.翻译环境和运行环境 翻译环境&#xff1a;将源代码转化为可执行的机器指令 运行环境&#xff1a;用于执行机器指令 1.1 翻译环境 翻译环境由编译和链接两大过程构建&#xff0c;编译又可以分为三大过程&#xff1a; 【1】预处理(预编译) 【2】编译 【3】汇编 不同的.c文件经…

力扣(数组)找到所有数组中消失的数字

给你一个含 n 个整数的数组 nums &#xff0c;其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字&#xff0c;并以数组的形式返回结果。 示例 1&#xff1a; 输入&#xff1a;nums [4,3,2,7,8,2,3,1] 输出&#xff1a;[5,6]示例 2&am…

03 cookie session

文章目录 Cookie01.javaCookie02.javaCookieTestServletSessionServlet.java Cookie01.java package com.aistart.cookie;import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.…

力扣 392. 判断子序列

题目来源&#xff1a;https://leetcode.cn/problems/is-subsequence/description/ C题解1&#xff1a;在t中按顺序一个一个寻找s的元素。 class Solution { public:bool isSubsequence(string s, string t) {bool flg false;int m s.size(), n t.size();if(m 0) return tr…

简化Java开发:深入理解Lombok注解

Lombok是一个Java库&#xff0c;它通过注解的方式自动化生成繁琐的Java代码&#xff0c;如getters、setters、构造函数等。这大大减少了样板代码&#xff0c;使代码更加简洁易读。本文将详细介绍Lombok中几个常用注解的使用方法和它们的作用。 引入Lombok 要在Java项目中使用…

离散数学【详解】-自学考试湖北,争取做到识字都能看懂。

回顾8年前&#xff0c;我记得我大学高数没复习&#xff0c;考了23分。 今天公司代码写完了&#xff0c;明天清明节&#xff0c;写篇文章磨磨时间。 我的文章&#xff0c;没有一篇不是磨时间能好好写出来的。 ----我 先列标题&#xff0c;比如h1,h2,这些内容。然后往里面填字&a…

面试题:RabbitMQ 消息队列中间件

1. 确保消息不丢失 生产者确认机制 确保生产者的消息能到达队列&#xff0c;如果报错可以先记录到日志中&#xff0c;再去修复数据持久化功能 确保消息未消费前在队列中不会丢失&#xff0c;其中的交换机、队列、和消息都要做持久化消费者确认机制 由spring确认消息处理成功后…

C语言终篇--基于epoll ET模式 的 非阻塞IO服务器模型

使用技术: 1 epoll事件驱动机制&#xff1a;使用epoll作为IO多路复用的技术&#xff0c;以高效地管理多个socket上的事件。 2 边缘触发&#xff08;Edge Triggered, ET&#xff09;模式&#xff1a;epoll事件以边缘触发模式运行&#xff0c;这要求代码必须负责消费所有可用的…

信奥赛一本通 【例4.2】天安门广场的面积

1.说明 天安门广场在北京市中心&#xff0c;它南北长880米&#xff0c;东西宽500米&#xff0c;试编一程序&#xff0c;计算天安门广场面积是多少平方米。 2.输入格式 无 3.输出格式 输出天安门广场面积。 4.输入数据 无5.输出数据 4400006.题目说明 本题主要考察c语言入门的…

HarmonyOS 应用开发之非线性容器

非线性容器实现能快速查找的数据结构&#xff0c;其底层通过hash或者红黑树实现&#xff0c;包括HashMap、HashSet、TreeMap、TreeSet、LightWeightMap、LightWeightSet、PlainArray七种。非线性容器中的key及value的类型均满足ECMA标准。 HashMap HashMap 可用来存储具有关联…

非线性SVM模型

通过5个条件判定一件事情是否会发生&#xff0c;5个条件对这件事情是否发生的影响力不同&#xff0c;计算每个条件对这件事情发生的影响力多大&#xff0c;写一个非线性SVM模型程序,最后打印5个条件分别的影响力。 示例一 在非线性支持向量机&#xff08;SVM&#xff09;模型中…

Vue3从入门到实战:路由的query和params参数

在Vue 3中&#xff0c;我们可以通过路由的查询参数来传递数据。这意味着我们可以在不同的页面之间传递一些信息&#xff0c;以便页面可以根据这些信息来显示不同的内容或执行不同的操作。 查询参数的使用方式类似于在URL中添加附加信息&#xff0c;以便页面之间可以根据这些信息…

【GlobalMapper精品教程】073:像素到点(Pixels-to-Points)从无人机图像轻松生成点云

文章目录 一、工具介绍二、生成点云三、生成正射四、生成3D模型五、注意事项一、工具介绍 Global Mapper v19引入的新的像素到点工具使用摄影测量原理,从重叠图像生成高密度点云、正射影像及三维模型。它使LiDAR模块成为已经功能很强大的的必备Global Mapper扩展功能。 打开…

JavaScript高级 —— 学习(三)

目录 一、深入面向对象 &#xff08;一&#xff09;面向对象介绍 &#xff08;二&#xff09;面向对象编程 &#xff08;oop&#xff09; 1.面向对象编程介绍 2.面向对象编程优点 3.面向对象的特征 4.和面向过程编程对比 二、构造函数 &#xff08;一&#xff09;介绍…

【HTB】Trick 靶场

Trick靶场 地址&#xff1a;https://app.hackthebox.com/machines/477 打靶过程 靶机IP:10.129.227.180 1.信息收集 1.1 nmap 端口扫描 ┌──(root㉿kali)-[~/Desktop] └─# nmap -Pn -sC -sV -p- 10.129.227.180 --min-rate5000 Starting Nmap 7.94SVN ( https://nmap…