Python魔术方法

什么是魔术方法?

所有以双下划线__包起来的方法,统称为Magic Method(魔术方法),它是一种的特殊方法,普通方法需要调用,而魔术方法不需要显示调用就可以执行。

魔术方法在类或对象的某些事件出发后会自动执行,让类具有神奇的“魔力”。如果希望根据自己的程序定制自己特殊功能的类,那么就需要对这些方法进行重写。

常见的魔术方法

__init__(self)

初始化方法

触发机制:实例化对象之后立即触发
参数:至少有一个self,接收当前对象,其他参数根据需要进行定义
返回值:无
作用:初始化对象的成员

# __init__示例
class Point:def __init__(self, x, y):self.x = xself.y = yp = Point(1, 2)
print(p.x, p.y)  # 输出: 1 2

 

__new__(cls)

构造方法

触发时机: 实例化对象时自动触发(在__init__之前触发)
参数:至少一个cls 接收当前类,其他参数根据初始化方法参数决定
返回值:必须返回一个对象实例,没有返回值,则实例化对象的结果为None
作用:实例化对象
注意:实例化对象是Object类底层实现,其他类继承了Object的__new__才能够实现实例化对象。

class Person(object):def __init__(self):print('__init__(): 我也被调用啦~')def __new__(cls, *args, **kwargs):  # 重写后,不再创建对象print('__new__(): 哈哈我被调用啦~')>>> per = Person()
__new__(): 哈哈我被调用啦~
>>> print(per)
Noneclass Person(object):def __init__(self):print('__init__(): 我也被调用啦~')def __new__(cls, *args, **kwargs): print('__new__(): 哈哈我被调用啦~')ret = super().__new__(cls)  # 调用父类object的__new__方法创建对象return ret>>> per = Person()
__new__(): 哈哈我被调用啦~
__init__(): 我也被调用啦~
>>> print(per)
<__main__.Person object at 0x0000020FA3892848>
class Test:def __new__(cls, *args, **kwargs):print("我是__new__方法")obj = object.__new__(cls)print(obj)return objdef __init__(self):print(self)print("我是__init__方法")if __name__ == '__main__':a = Test()-------输出结果---------
我是__new__方法
<__main__.Test object at 0x123902f70>
<__main__.Test object at 0x123902f70>
我是__init__方法

上面示例会发现:
1)__new__魔术方法返回的就是self的内存地址;
2)如果不在__new__方法里面调object的__new__方法就不会创建对象,__init__不会被执行;
3)如果不在__new__方法里面return创建好的对象,__init__不会被执行;

事实上,当我们理解了new方法后,我们还可以利用它来做一些其他有趣的事情,比如实现 设计模式中的 单例模式(singleton)

依照Python官方文档的说法,new方法主要是当你继承一些不可变的class时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径。还有就是实现自定义的metaclass

这个方法我们一般很少定义,不过我们在一些开源框架中偶尔会遇到定义这个方法的类。实际上,这才是"真正的构造方法",它会在对象实例化时第一个被调用,然后再调用init,它们的区别主要如下:

  • new的第一个参数是cls,而init的第一个参数是self
  • new返回值是一个实例,而init没有任何返回值,只做初始化操作
  • new由于是返回一个实例对象,所以它可以给所有实例进行统一的初始化操作

由于new优先于init调用,且返回一个实例,所以我们可以利用这种特性,每次返回同一个实例来实现一个单例类:



 

__del__(self)

析构方法

触发时机:当该类对象被销毁时,自动触发
参数:一个self,接受当前对象
返回值:无
作用:关闭或释放对象创建时资源
注意:del不一定会触发当前方法,只有当前对象没有任何变量引用时才会触发

class Cat:def eat(self):print("我嘎嘎能吃")def __del__(self):print("ohohoh,我被销毁了”)print("<=======start======>")
cat1 = Cat()
print("<=======ends======>”)‘’‘
<=======start======>
<=======ends======>
ohohoh,我被销毁了
’‘’

出现上面现象的原因是在没有手动执行del的情况下,程序执行结束后自动触发析构方法。

继续,现在加一个实例化,并且我们delcat1:

cat1 = Cat()
cat2 = cat1
print("<=======start======>")
del cat1
print("<=======ends======>”)‘’’
<=======start======>
<=======ends======>
ohohoh,我被销毁了
’‘’

既然我们在start与end中间删除了cat1,为啥程序还是在执行完后触发析构方法?这主要是因为cat2还在继续占用cat1的内存地址,所以会在cat2执行完毕后触发析构方法。

只要同时删除cat1和cat2,内存地址没有指向的值,这块内存被释放就会触发析构方法:

cat1 = Cat()
cat2 = cat1
print("<=======start======>")
del cat1
del cat2
print("<=======ends======>”)‘’’
<=======start======>
ohohoh,我被销毁了
<=======ends======>
’’’

__call__(self)

可调用对象魔术方法

触发时机:将对象当作函数调用时触发,方式: 对象()
参数:至少一个self接收对象,其余根据调用时参数决定
返回值:根据情况而定
作用:可以将复杂的步骤进行合并操作,减少调用的步骤,方便使用
注意:无

class A(object):def __call__(self, *args, **kwargs):print('call....')a = A()
a()  # 自动调用__call__()class Fibonacci(object):def __call__(self, num):a, b = 1, 1lst = []if num <= 2:lst.append(a)lst.append(b)else:for i in range(num):lst.append(a)a, b = b, a + breturn lst>>> f = Fibonacci()
>>> print(f(5))
[1, 1, 2, 3, 5]

__str__(self)

需要对象转换为string时,python都会默认调用该魔法方法,如print的时候,与字符串进行+运算的时候,凡是需要进行隐示类型转换为字符串的地方,都会自动调用该方法。该方法返回一个字符串:

class Dog(object):def __init__(self,name):#self 是对象#对象.属性名 = 属性值self.name = namedef __str__(self):#必须返回一个字符串return f"小狗的名字是{self.name}"
dog1 = Dog('aha')print(dog1)
#str = 'Hello!' + dog1; #会提示TypeError
str = 'Hello!' + str(dog1);
print(f'{str=}’)‘’'
小狗的名字是aha
str='Hello!小狗的名字是aha’
‘''

__repr__(self)

函数str() 用于将值转化为适于人阅读的形式,而repr() 转化为供解释器读取的形式,某对象没有适于人阅读的解释形式的话,str() 会返回与repr(),所以print展示的都是str的格式。

我们经常会直接输出类的实例化对象.

class Coo:def __init__(self):self.name = ""self.add = "python.org"def __repr__(self):return "[name="+ self.name +",add=" + self.add +"]"
co = Coo()
print(co)‘’'
[name=,add=python.org]
‘''

由此可见,__repr__() 方法是类的实例化对象用来做“自我介绍”的方法,默认情况下,它会返回当前对象的“类名+object at+内存地址”,而如果对该方法进行重写,可以为其制作自定义的自我描述信息。

__repr____str__这两个方法都是用于显示的,__str__是面向用户的,而__repr__面向程序员。

  • 打印操作会首先尝试__str__和str内置函数(print运行的内部等价形式),它通常应该返回一个友好的显示。
  • __repr__用于所有其他的环境中:用于交互模式下提示回应以及repr函数,如果没有使用__str__,会使用print和str。它通常应该返回一个编码字符串,可以用来重新创建对象,或者给开发者详细的显示。

当我们想所有环境下都统一显示的话,可以重构__repr__方法;当我们想在不同环境下支持不同的显示,例如终端用户显示使用__str__,而程序员在开发期间则使用底层的__repr__来显示,实际上__str__只是覆盖了__repr__以得到更友好的用户显示。

# __str__和__repr__示例
class Person:def __init__(self, name, age):self.name = nameself.age = agedef __str__(self):return f"{self.name} is {self.age} years old"def __repr__(self):return f"Person('{self.name}', {self.age})"p = Person("Alice", 25)
print(str(p))  # 输出: Alice is 25 years old
print(repr(p))  # 输出: Person('Alice', 25)

__del__(self)

析构函数,对象在内存中被销毁删除的时候会自动调用__del__ 方法。

会在以下两个场景被调用:

1、程序代码运行结束,在程序运行过程中,创建的所有对象和变量都会被删除销毁

2、使用del变量,将这个对象的引用计数变为0,会自动调用del方法

class Star(object):def __init__(self, name, movie):self.name = name  # 成员属性 明星姓名self.movie = movie  # 成员属性 明星的电影# 成员方法def playing(self):print(f"{self.name} 出演了电影 {self.movie} !")def __str__(self):# 打印对象时显示,return f"{self.name} 是我的偶像,我非常喜欢他的电影 {self.movie}"def __del__(self):# 删除对象时显示print(f"我现在不喜欢 {self.name} 了")s1 = Star('周星驰', '大话西游')
print(s1)
del s1
s2 =Star('周慧敏', '赌圣风云')
print(s2)
print('---game over—')‘’'
周星驰 是我的偶像,我非常喜欢他的电影 大话西游
我现在不喜欢 周星驰 了
周慧敏 是我的偶像,我非常喜欢他的电影 赌圣风云
---game over--
我现在不喜欢 周慧敏 了
‘''

__len__(self)

len(obj)函数调用时,对象会自动调用__len()__方法

import collections
card = collections.namedtuple('card', ["rank", 'suit'])
class FrenchDeck:ranks = [ str(n) for n in range(2, 11)] + list("JQKA")suits = 'spades diamonds clubs hearts'.split()def __init__(self):self._cards = [card(rank, suit) for suit in self.suits for rank in self.ranks]def __len__(self):return len(self._cards)fd = FrenchDeck()
print('len(fd)=', len(fd))   # 可以直接使用len函数查看fd对象的长度 52

__getitem__(self,item)

拥有此方法的对象可以通过的使用列表的形式进行对象操作,如:切片,下标取值.

import collections
card = collections.namedtuple('card', ["rank", 'suit'])
class FrenchDeck:ranks = [ str(n) for n in range(2, 11)] + list("JQKA")suits = 'spades diamonds clubs hearts'.split()def __init__(self):self._cards = [card(rank, suit) for suit in self.suits for rank in self.ranks]def __len__(self):return len(self._cards)def __getitem__(self, item):return self._cards[item]fd = FrenchDeck()
print('fd[0]=', fd[0])  # 可以直接使用下表取值
for i in range(0, len(fd)):print(fd[i])

特别注意,虽然可以通过循环的形式取出对象中值,但并不代表它是一个可迭代对象,即使你在方法中返回的是字符串也可以循环,不过字符串循环会一直无限循环下去,直到你手动停止。主要原因是,因为在使用Obj[key]时,python解释器自动帮你调用了__getitem__(self,item)方法,所以只要不使用item这个参数,无论你传什么参数都不会报错,返回什么值是有你决定的.

>>> isinstance(fd, collections.Iterable)
False

__cmp__(self,other)

用实例自身self和传入的实例other进行比较,如果self应该排在前面,就返回 -1,如果other应该排在前面,就返回1,如果两者相当,返回 0。

最后可以用list.sort函数或者sorted函数来实现排序。

class Student(object):def __init__(self):self.grade = 0def __cmp__(self,other):if self.grade<other.grade:return -1elif self.grade>other.grade:return 1else:return 0

__bool__(self)

触发时机: 使用bool(对象)的时候触发
参数:一个self接收对象
返回值:必须是布尔值
作用:根据实际情况决定,可以作为快捷方式使用
注意:仅适合于返回布尔值的操作

class A:print("__bool__和__len__都未定义,bool调用恒为True")print(bool(A()))
#__bool__和__len__都未定义,bool调用恒为True
#Trueclass B:def __bool__(self):print("__bool__返回False,bool调用恒为False")return Falseprint(bool(B()))
#__bool__返回False,bool调用恒为False
#Falseclass C:def __len__(self):print("__bool__未定义,找到__len__,__len__返回值非0,bool调用恒为True")return 1print(bool(C()))
#__bool__未定义,找到__len__,__len__返回值非0,bool调用恒为True
#True# 定义空字典
a = {}
# 定义空列表
b = []
# 定义空元组
c = ()# 以后判断这个3种数据类型是否有返回值直接通过bool方法来判断
if not bool(a):print("a为空字典")if not bool(b):print("b为空列表")if not bool(c):print("c为空元组")‘’'
a为空字典
b为空列表
c为空元组
‘''

__format__(self)

触发时机:使用字符串.format(对象)时候触发
参数:一个self接收对象,一个参数接收format的{}中的格式,例如:>5
返回值:必须是字符串
作用:设置对象可以作为format的参数,并且自定义对象格式化的规则
注意:无

__hash__(self)

调用hash函数时

class A:def __init__(self):self.a = 'a'self.b = 'b'def __hash__(self):return 1print(hash(A())) #1
print(hash(A())) #1class Person:def __init__(self, name, age):self.name = nameself.age = agedef __hash__(self):return hash((self.name, self.age))def __eq__(self, other):if isinstance(other, Person):return self.name == other.name and self.age == other.agereturn False# 创建对象
person1 = Person("John", 30)
person2 = Person("Alice", 25)# 输出哈希值
print(f"对象person1的hash值 {hash(person1)}”) #对象person1的hash值 2511066681118794660
print(f"对象person2的hash值 {hash(person2)}”) #对象person2的hash值 -7352762741811000521# 比较对象相等性
print(f"person1和person2相等是否成立  {person1 == person2}”) #对象person2的hash值 -7352762741811000521

__add__(self,other)

实例只见的加法运算

class Vector:def __init__(self, a, b):self.a = aself.b = bdef __str__(self):return 'Vector (%d, %d)' % (self.a, self.b)def __add__(self,other):return Vector(self.a + other.a, self.b + other.b)v1 = Vector(2,10)
v2 = Vector(5,-2)
print (v1 + v2)‘’’
Vector(7,8)
’‘’

运算符魔术方法

重载运算魔法函数定义魔法函数说明
__add__(self,other)实例之间的加法运算+
__sub__(self,other)实例之间的减法运算-
__mul__(self,other)实例之间的乘法运算*
__truediv__(self,other)类与类之间的真除。只有from future import division之后它才有效/
__floordiv__(self,other)类与类之间的浮点除法运算//
__mod__(self,other)类与类之间的取余运算%
__pow__(self,other[,module]))类与类之间的指数运算**
__and__(self,other)类与类之间的按位与运算&
__xor__(self,other)类与类之间的按位异或运算^
__or__(self,other)类与类之间的按位或运算|
__lt__(self,other)定义了比较操作符<
__gt__(self,other)定义了比较操作符>
__le__(self,other)定义了比较操作符<=
__ge__(self,other)定义了比较操作符>=
__eq__(self,other)定义了比较操作符==
__ne__(self,other)定义了比较操作符!=
__setitem__(self, key, value)使用self[nkey] = value赋值容器中的一项
__delitem__(self, key)删除self[nkey]。

例子:

class Point:def __init__(self, x, y):self.x = xself.y = ydef __add__(self, other):return Point(self.x + other.x, self.y + other.y)def __sub__(self, other):return Point(self.x - other.x, self.y - other.y)def __mul__(self, scalar):return Point(self.x * scalar, self.y * scalar)def __truediv__(self, scalar):return Point(self.x / scalar, self.y / scalar)def __eq__(self, other):return self.x == other.x and self.y == other.yp1 = Point(1, 2)
p2 = Point(3, 4)# 加法操作
p3 = p1 + p2
print(p3.x, p3.y) # 输出: 4, 6# 减法操作
p4 = p1 - p2
print(p4.x, p4.y) # 输出: -2, -2# 乘法操作
p5 = p1 * 2
print(p5.x, p5.y) # 输出: 2, 4# 除法操作
p6 = p1 / 2
print(p6.x, p6.y) # 输出: 0.5, 1.0# 等值比较操作
print(p1 == p2) # 输出: False
print(p1 == Point(1, 2)) # 输出: True# __lt__和__eq__示例
class Person:def __init__(self, name, age):self.name = nameself.age = agedef __lt__(self, other):return self.age < other.agedef __eq__(self, other):return self.age == other.agep1 = Person("Alice", 25)
p2 = Person("Bob", 30)
p3 = Person("Charlie", 25)
print(p1 < p2)  # 输出: True
print(p1 == p3)  # 输出: True

 

 

反运算魔术方法

反运算魔法方法,与算术运算符保持一一对应,不同之处就是反运算的魔法方法多了一个“r”。当文件左操作不支持相应的操作时被调用。

  • radd(self, other)定义加法的行为:+
  • rsub(self, other)定义减法的行为:-
  • rmul(self, other)定义乘法的行为:*
  • rtruediv(self, other)定义真除法的行为:/
  • rfloordiv(self, other)定义整数除法的行为://
  • rmod(self, other) 定义取模算法的行为:%
  • rdivmod(self, other)定义当被 divmod() 调用时的行为
  • divmod(a, b)把除数和余数运算结果结合起来,返回一个包含商和余数的元组(a // b, a % b)。
  • rpow(self, other[, module])定义当被 power() 调用或 ** 运算时的行为
  • rlshift(self, other)定义按位左移位的行为:<<
  • rrshift(self, other)定义按位右移位的行为:>>
  • rand(self, other)定义按位与操作的行为:&
  • rxor(self, other)定义按位异或操作的行为:^
  • ror(self, other)定义按位或操作的行为:|
    a + b
    这里加数是a,被加数是b,因此是a主动,反运算就是如果a对象的__add__()方法没有实现或者不支持相应的操作,那么 Python 就会调用b的__radd__()方法。
class Nint(int):def __add__(self, other):print('__add()__')return int.__add__(self, other)def __radd__(self, other):print('__radd()__')return int.__sub__(other, self) # 注意 self 在后面a = Nint(5)
b = Nint(3)
print(a + b)  # 8
print('####')
print(1 + b)  # -2‘’'
__add()__
8
####
__radd()__
-2
‘''

赋值运算符魔术方法

  • iadd(self, other)定义赋值加法的行为:+=
  • isub(self, other)定义赋值减法的行为:-=
  • imul(self, other)定义赋值乘法的行为:*=
  • itruediv(self, other)定义赋值真除法的行为:/=
  • ifloordiv(self, other)定义赋值整数除法的行为://=
  • imod(self, other)定义赋值取模算法的行为:%=
  • ipow(self, other[, modulo])定义赋值幂运算的行为:**=
  • ilshift(self, other)定义赋值按位左移位的行为:<<=
  • irshift(self, other)定义赋值按位右移位的行为:>>=
  • iand(self, other)定义赋值按位与操作的行为:&=
  • ior(self, other)定义赋值按位或操作的行为:|=
  • ixor(self, other)定义赋值按位异或操作的行为:^=

一元运算符魔术方法

  • neg(self)定义正号的行为:+x
  • pos(self)定义负号的行为:-x
  • abs(self)定义当被abs()调用时的行为
  • invert(self)定义按位求反的行为:~x

属性访问魔术方法

__getattr__(self, name)

定义当用户试图获取一个不存在的属性时的行为。

触发时机:获取不存在的对象成员时触发
参数:一个是接收当前对象的self,一个是获取成员名称的字符串
返回值:必须有值
作用:为访问不存在的属性设置值
注意:getattribute无论何时都会在getattr之前触发,触发了getattribute就不会在触发getattr了

class Base:n = 0class Point(Base):z = 6def __init__(self, x, y):self.x = xself.y = ydef show(self):print(self.x, self.y)def __getattr__(self, item):return item>>> p1.x
4
>>> p1.z
6
>>> p1.n
0
>>> p1.t
't'

实例属性会按照继承关系寻找,如果找不到,就会执行__getattr__()方法,如果没有这个方法,就会抛出AttributeError异常标识找不到属性。

__getattribute__(self, name)

定义当该类的属性被访问时的行为(先调用该方法,查看是否存在该属性,若不存在,接着去调用__getattr__)

触发时机:使用对象成员时触发,无论成员是否存在
参数:1个接收当前对象self,一个是获取的成员的名称字符串
返回值:必须有
作用:在具有封装操作(私有化时),为程序开部分访问权限使用

class Base:n = 0class Point(Base):z = 6def __init__(self, x, y):self.x = xself.y = ydef __getattr__(self, item):return itemdef __getattribute__(self, item):return item>>> p1 = Point(4, 5)
>>> print(p1.__dict__)
__dict__
>>> print(p1.x)
x
>>> print(p1.z)
z
>>> print(p1.n)
n
>>> print(p1.t)
t
>>> print(Point.__dict__)
{'__module__': '__main__', 'z': 6, '__init__': <function Point.__init__ at 0x000001F5EB7063A8>, '__getattr__': <function Point.__getattr__ at 0x000001F5EB706558>, '__getattribute__': <function Point.__getattribute__ at 0x000001F5EB706168>, '__doc__': None}
>>> print(Point.z)
6

实例的所有的属性访问,第一个都会调用__getattribute__方法,它阻止了属性的查找,该方法应该返回值或者抛出一个AttributeError异常。

该方法的返回值将作为属性查找的结果。
如果抛出AttributeError异常,则会直接调用__getattr__方法,因为属性没有找到,__getattribute__方法中为了避免在该方法中无限递归,它的实现应该永远调用基类的同名方法以访问需要的任何属性。
需要注意的是,除非明确知道__getattrtbute__方法用来做什么,否则不要使用。
 

__setattr__(self, name, value)

定义当一个属性被设置时的行为

触发时机:设置对象成员值的时候触发
参数:1个当前对象的self,一个是要设置的成员名称字符串,一个是要设置的值
返回值:无 过程操作
作用:接管设置操作,可以在设置前之前进行判断验证等行为
注意:在当前方法中无法使用成员=值的方式直接设置成员,否则会无限递归,必须借助object的设置方法来完成

class Base:n = 0class Point(Base):z = 6def __init__(self, x, y):self.x = xself.y = ydef show(self):print(self.x, self.y)def __getattr__(self, item):return itemdef __setattr__(self, key, value):print(key, value)# --------------------------------------------------
>>> p1 = Point(4, 5)
x 4
y 5
>>> print(p1.x)
x
>>> print(p1.z)
6
>>> print(p1.n)
0
>>> print(p1.t)
t
# --------------------------------------------------
>>> p1.x = 50
>>> print(p1.x)
x
>>> print(p1.__dict__)
{}
>>> p1.__dict__['x'] = 60
>>> print(p1.__dict__)
{'x': 60}
>>> p1.x
60

__delattr__(self, name)

定义当一个属性被删除时的行为

触发时机:删除对象成员时触发
参数:一个当前对象的self
返回值:无
作用:可以在删除成员时进行验证。

__dir__(self)

触发时机:dir(对象)的时候触发
参数:1个接收当前对象self
返回值:必须为序列类型(列表,元组,集合等,)
作用:可以自定义成员列表的返回值


例子

class C:def __getattribute__(self, item):print('__getattribute__')return super().__getattribute__(item)def __getattr__(self, item):print('__getattr__')def __setattr__(self, key, value):print('__setattr__')super().__setattr__(key, value)def __delattr__(self, item):print('__delattr__')super().__delattr__(item)c = C()
print('1-----')
c.x
# __getattribute__
# __getattr__
print('2-----')
c.x = 1
# __setattr__
print('3-----')
del c.x
# __delattr__

类型转换魔术方法

  • __complex__ (self)定义当被 complex() 调用时的行为(需要返回恰当的值)
  • __int__(self) 定义当被 int() 调用时的行为(需要返回恰当的值)
  • __float__(self) 定义当被 float() 调用时的行为(需要返回恰当的值)
  • __round__(self[, n]) 定义当被 round() 调用时的行为(需要返回恰当的值)
  • __index(self)__ 1. 当对象是被应用在切片表达式中时,实现整形强制转换
  • 2. 如果你定义了一个可能在切片时用到的定制的数值型,你应该定义 index
  • 3. 如果 index 被定义,则 int 也需要被定义,且返回相同的值

上下文相关的魔术方法

__enter__(self)

1. 定义当使用 with 语句时的初始化行为
2. enter 的返回值被 with 语句的目标或者 as 后的名字绑定

__exit__(self, exctype, excvalue, traceback)

1. 定义当一个代码块被执行或者终止后上下文管理器应该做什么
2. 一般被用来处理异常,清除工作或者做一些代码块执行完毕之后的日常工作

# __enter__和__exit__示例
class DatabaseConnection:def __init__(self, db_url):self.db_url = db_urldef __enter__(self):self.connection = open(self.db_url)return self.connectiondef __exit__(self, exc_type, exc_val, exc_tb):self.connection.close()# 使用 with 语句打开数据库连接,并在结束时自动关闭连接
with DatabaseConnection('example.db') as conn:# 执行一些操作cursor = conn.cursor()cursor.execute('SELECT * FROM users')rows = cursor.fetchall()print(rows)

容器相关的魔术方法

  • __len__(self) 定义当被 len() 调用时的行为(返回容器中元素的个数)
  • __getitem__(self, key) 定义获取容器中指定元素的行为,相当于 self[key]
  • __setitem__(self, key, value) 定义设置容器中指定元素的行为,相当于 self[key] = value
  • __delitem__(self, key) 定义删除容器中指定元素的行为,相当于 del self[key]
  • __iter__(self) 定义当迭代容器中的元素的行为
  • __next__(self)从iterable对象中获取下一个元素
  • __reversed__(self) 定义当被 reversed() 调用时的行为
  • __contains__(self, item) 定义当使用成员测试运算符(in 或 not in)时的行为
  • __missing__字典使用__getitem__()调用时,key不存在执行该方法
# __getitem__和__setitem__示例
class MyList:def __init__(self, items):self.items = itemsdef __getitem__(self, index):return self.items[index]def __setitem__(self, index, value):self.items[index] = valuel = MyList([1, 2, 3, 4])
print(l[2])  # 输出: 3
l[2] = 5
print(l[2])  # 输出: 5# __contains__示例
class MyList:def __init__(self, items):self.items = itemsdef __contains__(self, item):return item in self.itemsl = MyList([1, 2, 3, 4])
print(2 in l)  # 输出: True
print(5 in l)  # 输出: False# __iter__和__next__示例
class MyRange:def __init__(self, start, end):self.start = startself.end = enddef __iter__(self):return selfdef __next__(self):if self.start >= self.end:raise StopIterationvalue = self.startself.start += 1return valuer = MyRange(0, 5)
for i in r:print(i)  # 输出: 0 1 2 3 4

 魔法属性

__doc__

这是一个属性,获取类或对象内部文档。

class MyClass():"""我是一个类,这里说明一些有用的信息"""def __init__(self):passprint(MyClass.__doc__)
#        我是一个类,这里说明一些有用的信息

__name__

这也是一个属性,获取类名或函数名 

class Class1:passclass MyClass:def task1(self, func1):print(func1.__name__)def func():print("我是func1函数")>>> obj = MyClass()
>>> obj.task1(func)
func
>>> obj.task1(Class1)
Class1

__class__

获取当前对象获取的类

class Class1:pass>>> obj = Class1()
>>> print(obj.__class__)
<class '__main__.Class1'>
>>> print(obj.__class__.__name__)
Class1

__base__

获取一个类直接继承的所有父类,返回元组。

class Class1:passclass Class2:passclass MyClass(Class1, Class2):pass>>> print(MyClass.__bases__)
(<class '__main__.Class1'>, <class '__main__.Class2'>)

__dict__

获取类或对象的的内部成员结构。主要用来获取用户自定义的属性,以及这个属性对应的值。返回的是一个字典

class MyClass():name1 = "Lsir"name2 = "Wsir"name3 = "Zsir"def task1(self):print("task1")def task2(self):print("tesk2")def task3(self):print("task3")>>> print(MyClass.__dict__)
{'__module__': '__main__', 'name1': 'Lsir', 'name2': 'Wsir', 'name3': 'Zsir', 'task1': <function MyClass.task1 at 0x0000020C16385558>, 'task2': <function MyClass.task2 at 0x0000020C16385D38>, 'task3': <function MyClass.task3 at 0x0000020C16385708>, '__dict__': <attribute '__dict__' of 'MyClass' objects>, '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, '__doc__': None}

dir函数做一个区分。dir函数返回的是这个对象上拥有的所有属性,包括Python内置的属性和用户自己添加的,并且只是获取属性名字,不会获取这个属性对应的值。

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

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

相关文章

wow.js使用和动画只执行一次问题优化

wow.js配合第三方动画库可以让元素出现在屏幕时执行相关的动画 wow.js依赖于animate.css&#xff0c;首先在头部引用animate.css或者animate.min.css。在最底部或引入的css下面引用wow.js或者wow.min.js使用规则直接查看官网&#xff1a;wow.js — Reveal Animations When Scro…

【校招VIP】前端算法考察之排序

考点介绍&#xff1a; 不同的场景中&#xff0c;不同的排序算法执行效率不同。 稳定&#xff1a;冒泡、插入、归并 不稳定&#xff1a;选择、快速、堆排序、希尔排序 『前端算法考察之排序』相关题目及解析内容可点击文章末尾链接查看&#xff01; 一、考点题目 1、使用js实…

EOCR-SE2/EOCRSE2在数控技术行业的应用

EOCR-SE2电动机保护器是施耐德EOCR系列中一款以低成本、高性能著称的产品&#xff0c;其广泛应用于各种机床设备中。 EOCRSE2-05RS品牌&#xff1a;施耐德&#xff0c;产地&#xff1a;韩国益山工厂&#xff0c;型号&#xff1a;EOCR-SE2,电流范围&#xff1a;3-30A&#xff0…

DQL语句的执行顺序

DQL语句的通用结构如下所示 Select 子段列表 From 表名列表 Where 条件列表 Group By 分组子段列表 Having 分组后条件列表 Order By 排序子段列表 Limit 分页参数在执行DQL语句时会有一定的执行顺序&#xff1a; 首先执行From 表名列表操作然后执行where 条件列表来指定查询…

541. 反转字符串 II

541. 反转字符串 II 给定一个字符串 s 和一个整数 k&#xff0c;从字符串开头算起&#xff0c;每计数至 2k 个字符&#xff0c;就反转这 2k 字符中的前 k 个字符。 如果剩余字符少于 k 个&#xff0c;则将剩余字符全部反转。 如果剩余字符小于 2k 但大于或等于 k 个&#xff…

工服穿戴检测算法 工装穿戴识别算法

工服穿戴检测算法 工装穿戴识别算法利用yolo网络模型图像识别技术&#xff0c;工服穿戴检测算法 工装穿戴识别算法可以准确地识别现场人员是否穿戴了正确的工装&#xff0c;包括工作服、安全帽等。一旦检测到未穿戴的情况&#xff0c;将立即发出警报并提示相关人员进行整改。Yo…

SpringBoot工具类—基于定时器完成文件清理功能

直接复制粘贴既可&#xff01;&#xff01; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.io.File; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneOff…

浏览器调起摄像头

浏览器调起摄像头 <template><div class"body">这里什么都没有<video id"videoCamera" class"video"></video><button click"getCompetence" class"btn">打开摄像头</button><butt…

vue管理系统常用命令记录

保留几位小数 //正则let numF (this.countData.hkje * 100) / 1000000sums[index] Number(numF.toString().match(/^\d(?:\.\d{0,4})?/)) 万元; //更正上面的只可以是正数不可以负数&#xff0c;下面的可以是正说或者负数都可以sums[index] Number(numF.toString().matc…

基于jenkins自动化部署PHP环境

实验环境 操作系统 IP地址 主机名 角色 CentOS7.5 192.168.147.141 git git服务器 CentOS7.5 192.168.147.142 Jenkins git客户端 jenkins服务器 CentOS7.5 192.168.147.143 web web服务器 具体环境配置见上一篇&#xff01; 准备git仓库 [rootgit ~]# su -…

Leetcode.100 相同的树

给你两棵二叉树的根节点 p 和 q &#xff0c;编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同&#xff0c;并且节点具有相同的值&#xff0c;则认为它们是相同的。 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 代码如下&#xff1a;…

深圳IT行业供需:蓬勃发展的科技中心

深圳作为中国的科技中心之一&#xff0c;IT行业在这座城市蓬勃发展。本文将探讨深圳IT行业的供需状况&#xff0c;包括就业机会、技能需求以及行业前景展望。 近年来&#xff0c;深圳IT行业迅速发展&#xff0c;成为全球科技创新的重要枢纽之一。随着大量的科技企业和初创公司在…

DNS原理

文章目录 一、域名产生背景域名的树形层次化结构 二、定义三、DNS查询模式递归查询迭代查询 四、主机域名解析工作流程五、H3C配置DNS代理 首先可以看下思维导图&#xff0c;以便更好的理解接下来的内容。 一、域名 产生背景 在互联网中&#xff0c;通过IP地址访问目标主机…

固定资产管理措施怎么写

固定资产管理措施是指企业在进行固定资产管理时所采取的各种措施和方法。以下是一些常见的固定资产管理措施&#xff1a;  建立完善的固定资产管理制度。制定明确的资产采购、使用、维护、报废等流程和标准&#xff0c;确保资产管理的规范性和透明度。  采用先进的资产管理…

35 - 个人博客项目-06-首页

1. 自定义html中的过滤器:apps / user / views.py # 自定义过滤器,将二进制内容转成utf-8格式 user_bp.app_template_filter("cdecode") def content_decode(content):content content.decode("utf-8")return content[:200]user_bp.app_template_filter(…

Redis 10 大数据类型

1. which 10 1. redis字符串 2. redis 列表 3. redis哈希表 4. redis集合 5. redis有序集合 6. redis地理空间 7. redis基数统计 8. redis位图 9. redis位域 10. redis流 2. 获取redis常见操作指令 官网英文&#xff1a;https://redis.io/commands 官网中文&#xff1a;https:/…

git difftool对比差异,避免推送不相关内容

问题 在利用git进行版本管理的时候&#xff0c;经常会由于对其他不相关的代码&#xff0c;做了一些小改动&#xff0c;例如删除了一个空行&#xff0c;多了一个缩进等。 为避免将这些不相关的改动也提交到远程&#xff0c;对PR造成不必要的影响&#xff0c;可以利用git diff命…

DolphinDB 携手白鲸开源 WhaleStudio 打造高效敏捷的 DataOps 解决方案

浙江智臾科技有限公司&#xff08;简称&#xff1a;DolphinDB&#xff09;和北京白鲸开源科技有限公司&#xff08;简称&#xff1a;白鲸开源&#xff09;是在大数据技术领域活跃的两支专业团队。 DolphinDB 专注于为用户提供集高性能存储、复杂分析能力和流处理于一体的实时计…

【区块链 | IPFS】浅谈 | IPFS数据存储原理

IPFS在数据存储方面采用的是分散式的文件存储,区别于HTTP协议的位置寻址,IPFS是基于内容寻址,当文件上传到IPFS节点存储时,节点会对文件进行Merkle DAG(默克尔有向无环图)的格式组织分块存储,在存储完毕后,文件将以Merkle DAG的根哈希数来表示该文件,用户可以从IPFS构…

在腾讯云服务器OpenCLoudOS系统中安装svn(有图详解)

1. 安装svn yum -y install subversion 安装成功&#xff1a; 2. 创建数据根目录及仓库 mkdir -p /usr/local/svn/svnrepository 创建test仓库&#xff1a; svnadmin create /usr/local/svn/test test仓库创建成功&#xff1a; 3. 修改配置test仓库 cd /usr/local/svn/te…