Python面向对象中,如何使用无为则无心的魔法方法?

2026-05-22 15:531阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计2920个文字,预计阅读时间需要12分钟。

Python面向对象中,如何使用无为则无心的魔法方法?

目录 + 1、魔法方法 __new__( ) + 2、魔法方法 __init__( ) + 3、魔法方法 __del__( ) + 4、魔法方法 __str__( ) 和 __repr__( ) + 5、魔法方法 __call__( ) + 6、魔法方法 __len__( ) + 7、魔法方法 __getitem__( )、__setitem__( ) 和 __delitem__( )

目录
  • 1、魔法方法__new__()
  • 2、魔法方法__init__()
  • 3、魔法方法__del__()
  • 4、魔法方法__str__()__repr__()
  • 5、魔法方法__call__()
  • 6、魔法方法__len__()
  • 7、魔法方法__getitem__()__setitem__()__delitem__()

在Python语言中,有些方法名比较特别,在名称的前后各有两个下划线,这样的方法往往具有特殊的意义,我们统称为魔法方法,也叫特殊方法。需要注意的是,我们在创建自定义方法时要避免这样的格式,防止造成不必要的冲突。

Python的魔法方法有很多,我们主要介绍常用的几个魔法方法。以后需要用到其他的魔法方法,按照介绍的这几个调用方式,自己尝试一下就可以了,很简单的。

1、魔法方法__new__()

类的实例化时,调用的第一个方法是__new__方法。
官方定义如下,可以看到__new__被定义成静态方法,第一个必须传入的参数是cls,代表需要实例化的类。

class Demo(): def __new__(cls, *args, **kwargs): print('调用__new__方法') def __init__(self): print('调用__init__方法') # 结果:调用__new__方法 d = Demo()

从结果看到,只调用了__new__方法,但奇怪的是并没有调用__init__方法,这是为什么呢?

实际上,__new__是负责对当前类进行实例化,并将实例返回,传给__init__方法。__init__方法中的self就是指代__new__传过来的对象,所以再次强调,__init__是实例化后调用的第一个方法。

只有__new__方法返回创建的实例对象,后边的__init__方法才能执行。

Python面向对象中,如何使用无为则无心的魔法方法?

class Demo: def __new__(cls, *args, **kwargs): print('调用__new__方法') return object.__new__(cls) def __init__(self): print('调用__init__方法') # 创建对象 d = Demo() """ 输出结果: 调用__new__方法 调用__init__方法 """

总结:

__new__()方法是一个魔法方法(同时也是一种静态方法),用于创建一个类的实例,返回一个类的实例对象,用于传入初始化方法__init__()方法中。一般并不需要对其进行声明和重写,若是重写的话,需要注意返回一个有效的类的实例对象,实例通过object父类调用类的实例化方法,用于返回一个对象实例。若是不返回一个类的实例对象,会导致类的__init__()方法不会被调用,当然实例(self为空)也不会被成功创建。

2、魔法方法__init__()

__init__方法是类创建过程中用的比较多的魔法方法,是类对象创建后调用的初始化方法,紧跟者__new__方法后调用,主要用于实例变量的初始化操作。

__init__方法可以理解为一个类的实例的构造器,其方法的特点是不会返回任何对象或者值,若返回则会抛出 TypeError 异常。

(1)体验__init__()

思考:洗衣机的宽度高度是与生俱来的属性,可不可以在生产过程中就赋予这些属性呢?

答:理应如此。

__init__()方法的作用:初始化对象。

示例:

""" 目标: 定义init方法设置初始化属性并访问调用 1. 定义类 init方法: width 和 height 添加实例方法:访问实例属性 2. 创建对象 3. 验证成果 调用实例方法 """ # 1.定义类 class Washer(): # 定义初始化功能的函数 def __init__(self): # 添加实例属性 self.width = 500 self.height = 800 def print_info(self): # 类里面调用实例属性 print(f'洗衣机的宽度是{self.width}, 高度是{self.height}') # 2. 创建对象 haier1 = Washer() # 3. 调用实例方法 haier1.print_info()

注意:

  • __init__()方法,在创建一个对象时默认被调用,不需要手动调用。
  • __init__(self)中的self参数,不需要开发者传递,Python解释器会自动把当前的对象引用传递过去。

(2)带参数的__init__()

思考:一个类可以创建多个对象,如何对不同的对象设置不同的初始化属性呢?

答:传参数。

# 定义类 class Washer(): # 定义带参数的init方法 def __init__(self, width, height): self.width = width self.height = height # 定义实例方法 def print_info(self): # 调用实例属性 print(f'洗衣机的宽度是{self.width}') print(f'洗衣机的高度是{self.height}') haier1 = Washer(10, 20) haier1.print_info() # 如果创建对象的时候不传递参数,会报错。 # haier2 = Washer() haier2 = Washer(100, 200) haier2.print_info()

图解如下:

3、魔法方法__del__()

当删除对象时,Python解释器也会默认调用__del__()方法。__del__()方法属于析构函数。

__del__()方法不会被主动调用,只有当类的实例对象的引用计数为0时,才会被调用,一般不建议重写__del__()方法。

示例

class Washer(): def __init__(self, width, height): self.width = width self.height = height def __del__(self): print(f'{self}对象已经被删除') haier1 = Washer(10, 20) # <__main__.Washer object at 0x0000026118223278>对象已经被删除 del haier1

即便不手动删除对象,也能调用到__del__()方法,也就上面示例中,不编写最后del haier1语句,当Python程序执行完成后,也会打印一样的结果,是Python解释器自动调用的。

4、魔法方法__str__()__repr__()
  • Python 定义了__str__()__repr__()两种方法,__str__()用于显示给用户,而__repr__()用于显示给开发人员。

  • __str__方法默认情况下,它会返回当前对象的类名+object at+内存地址
    如下:

    <__main__.Students object at 0x0000000002443808>

  • 有时候想让屏幕打印的结果不是对象的内存地址,而是它的形式的字符串,以便更直观地显示对象内容,可以通过在该对象的类中重写__str__()__repr__()方法来实现。

  • 注意:__str__()方法和__repr__()方法的返回值只能是字符串!

(1)关于调用两种方法的时机

以下三种场景中,会优先调用对象的__str__()方法。若没有,就调用__repr__()方法。若再没有,则显示其内存地址。

  • 使用print()时。
  • 使用%sf'{}'拼接对象时。
  • 使用str(x)转换对象x时。

对于下面两种场景:

  • %r进行字符串拼接时。
  • repr(x)转换对象x时。

则会调用这个对象的__repr__()方法。若没有,则不再看其是否有__str__()方法。若再没有,则显示其内存地址。

(2)示例

__str__方法一般放置的是一些解释说明的文字。

示例:

class Washer(): def __init__(self, width, height): self.width = width self.height = height def __str__(self): # return repr('这是海尔洗衣机的说明书') return '这是海尔洗衣机的说明书' # __repr__方法在实际工作总一般如下使用 __repr__ = __str__ haier1 = Washer(10, 20) # 结果:这是海尔洗衣机的说明书 print(haier1) 5、魔法方法__call__()

对象后面加括号,触发执行。

提示:

  • __init__方法的执行是由创建对象触发的,即:对象 = 类名()
  • 而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

示例:

class Person(object): def __init__(self): print("__init__方法执行了") def __call__(self, *args, **kwargs): print("__call__方法中执行了") # 1.对象 = 类名() p = Person() # 执行__init__ # 2.对象() 调用__call__方法 p() # 3.类()() 调用__call__方法 Person()() # 执行__call__

提示:这个方法在工作中的应用自己以后总结,先知道怎么用就好。

6、魔法方法__len__()

__len__()方法在listdictsettuplestr等序列中都存在,而在intfloat类中是不存在的。

print('__len__' in dir(int)) # False print('__len__' in dir(float)) # False print('__len__' in dir(str)) # True print('__len__' in dir(list)) # True print('__len__' in dir(tuple)) # True print('__len__' in dir(dict)) # True print('__len__' in dir(set)) # True

如果一个类要表现得像一个list一样,有需求要获取有多少个元素,就得用 len() 函数。

要让 len() 函数工作正常,类中就必须提供一个魔法方法__len__()方法,它的作用是返回元素的个数。

示例:

# 定义一个类,接收同学名的名字 class Students(object): def __init__(self, *args): self.names = args def __len__(self): return len(self.names) stu = Students('唐僧', '孙悟空', '猪八戒', '沙和尚') print(len(stu)) # 4 print(stu.__len__()) # 4

提示:只要在类中正确实现了__len__()方法,就可以用len()函数。

7、魔法方法__getitem__()__setitem__()__delitem__()

在Python中,如果我们想实现创建类似于序列和映射的类,可以通过重写魔法方法__getitem__()方法、__setitem__()方法、__delitem__()方法去模拟。

示例:

class MyDict(object): def __init__(self): self.item = {} # 获取成员 def __getitem__(self, key): return self.item.get(key) # 添加成员 def __setitem__(self, key, value): self.item[key] = value # 删除成员 def __delitem__(self, key): del self.item[key] # 获取人员数量 def __len__(self): return len(self.item) if __name__ == "__main__": # 创建序列对象 myDict = MyDict() # 添加元素 myDict.__setitem__('师傅', '唐憎') myDict.__setitem__('大师兄', '孙悟空') # 查看刚添加的成员 print(myDict.__getitem__('大师兄')) print(f"现在成员{len(myDict)}人", ) # 2 # 修改成员 myDict.__setitem__('大师兄', '齐天大圣') print(myDict.__getitem__('大师兄')) print(f"现在成员{len(myDict)}人", ) # 2 # 删除元素 myDict.__delitem__('师傅') print(f"现在成员{len(myDict)}人", ) # 1 """ 输出结果: 孙悟空 现在成员2人 齐天大圣 现在成员2人 现在成员1人 """

参考:

  • www.cnblogs.com/woniuxy/p/11507648.html
  • blog.csdn.net/chf1142152101/java/article/details/78715296
  • www.cnblogs.com/oddgod/p/10992366.html

本文共计2920个文字,预计阅读时间需要12分钟。

Python面向对象中,如何使用无为则无心的魔法方法?

目录 + 1、魔法方法 __new__( ) + 2、魔法方法 __init__( ) + 3、魔法方法 __del__( ) + 4、魔法方法 __str__( ) 和 __repr__( ) + 5、魔法方法 __call__( ) + 6、魔法方法 __len__( ) + 7、魔法方法 __getitem__( )、__setitem__( ) 和 __delitem__( )

目录
  • 1、魔法方法__new__()
  • 2、魔法方法__init__()
  • 3、魔法方法__del__()
  • 4、魔法方法__str__()__repr__()
  • 5、魔法方法__call__()
  • 6、魔法方法__len__()
  • 7、魔法方法__getitem__()__setitem__()__delitem__()

在Python语言中,有些方法名比较特别,在名称的前后各有两个下划线,这样的方法往往具有特殊的意义,我们统称为魔法方法,也叫特殊方法。需要注意的是,我们在创建自定义方法时要避免这样的格式,防止造成不必要的冲突。

Python的魔法方法有很多,我们主要介绍常用的几个魔法方法。以后需要用到其他的魔法方法,按照介绍的这几个调用方式,自己尝试一下就可以了,很简单的。

1、魔法方法__new__()

类的实例化时,调用的第一个方法是__new__方法。
官方定义如下,可以看到__new__被定义成静态方法,第一个必须传入的参数是cls,代表需要实例化的类。

class Demo(): def __new__(cls, *args, **kwargs): print('调用__new__方法') def __init__(self): print('调用__init__方法') # 结果:调用__new__方法 d = Demo()

从结果看到,只调用了__new__方法,但奇怪的是并没有调用__init__方法,这是为什么呢?

实际上,__new__是负责对当前类进行实例化,并将实例返回,传给__init__方法。__init__方法中的self就是指代__new__传过来的对象,所以再次强调,__init__是实例化后调用的第一个方法。

只有__new__方法返回创建的实例对象,后边的__init__方法才能执行。

Python面向对象中,如何使用无为则无心的魔法方法?

class Demo: def __new__(cls, *args, **kwargs): print('调用__new__方法') return object.__new__(cls) def __init__(self): print('调用__init__方法') # 创建对象 d = Demo() """ 输出结果: 调用__new__方法 调用__init__方法 """

总结:

__new__()方法是一个魔法方法(同时也是一种静态方法),用于创建一个类的实例,返回一个类的实例对象,用于传入初始化方法__init__()方法中。一般并不需要对其进行声明和重写,若是重写的话,需要注意返回一个有效的类的实例对象,实例通过object父类调用类的实例化方法,用于返回一个对象实例。若是不返回一个类的实例对象,会导致类的__init__()方法不会被调用,当然实例(self为空)也不会被成功创建。

2、魔法方法__init__()

__init__方法是类创建过程中用的比较多的魔法方法,是类对象创建后调用的初始化方法,紧跟者__new__方法后调用,主要用于实例变量的初始化操作。

__init__方法可以理解为一个类的实例的构造器,其方法的特点是不会返回任何对象或者值,若返回则会抛出 TypeError 异常。

(1)体验__init__()

思考:洗衣机的宽度高度是与生俱来的属性,可不可以在生产过程中就赋予这些属性呢?

答:理应如此。

__init__()方法的作用:初始化对象。

示例:

""" 目标: 定义init方法设置初始化属性并访问调用 1. 定义类 init方法: width 和 height 添加实例方法:访问实例属性 2. 创建对象 3. 验证成果 调用实例方法 """ # 1.定义类 class Washer(): # 定义初始化功能的函数 def __init__(self): # 添加实例属性 self.width = 500 self.height = 800 def print_info(self): # 类里面调用实例属性 print(f'洗衣机的宽度是{self.width}, 高度是{self.height}') # 2. 创建对象 haier1 = Washer() # 3. 调用实例方法 haier1.print_info()

注意:

  • __init__()方法,在创建一个对象时默认被调用,不需要手动调用。
  • __init__(self)中的self参数,不需要开发者传递,Python解释器会自动把当前的对象引用传递过去。

(2)带参数的__init__()

思考:一个类可以创建多个对象,如何对不同的对象设置不同的初始化属性呢?

答:传参数。

# 定义类 class Washer(): # 定义带参数的init方法 def __init__(self, width, height): self.width = width self.height = height # 定义实例方法 def print_info(self): # 调用实例属性 print(f'洗衣机的宽度是{self.width}') print(f'洗衣机的高度是{self.height}') haier1 = Washer(10, 20) haier1.print_info() # 如果创建对象的时候不传递参数,会报错。 # haier2 = Washer() haier2 = Washer(100, 200) haier2.print_info()

图解如下:

3、魔法方法__del__()

当删除对象时,Python解释器也会默认调用__del__()方法。__del__()方法属于析构函数。

__del__()方法不会被主动调用,只有当类的实例对象的引用计数为0时,才会被调用,一般不建议重写__del__()方法。

示例

class Washer(): def __init__(self, width, height): self.width = width self.height = height def __del__(self): print(f'{self}对象已经被删除') haier1 = Washer(10, 20) # <__main__.Washer object at 0x0000026118223278>对象已经被删除 del haier1

即便不手动删除对象,也能调用到__del__()方法,也就上面示例中,不编写最后del haier1语句,当Python程序执行完成后,也会打印一样的结果,是Python解释器自动调用的。

4、魔法方法__str__()__repr__()
  • Python 定义了__str__()__repr__()两种方法,__str__()用于显示给用户,而__repr__()用于显示给开发人员。

  • __str__方法默认情况下,它会返回当前对象的类名+object at+内存地址
    如下:

    <__main__.Students object at 0x0000000002443808>

  • 有时候想让屏幕打印的结果不是对象的内存地址,而是它的形式的字符串,以便更直观地显示对象内容,可以通过在该对象的类中重写__str__()__repr__()方法来实现。

  • 注意:__str__()方法和__repr__()方法的返回值只能是字符串!

(1)关于调用两种方法的时机

以下三种场景中,会优先调用对象的__str__()方法。若没有,就调用__repr__()方法。若再没有,则显示其内存地址。

  • 使用print()时。
  • 使用%sf'{}'拼接对象时。
  • 使用str(x)转换对象x时。

对于下面两种场景:

  • %r进行字符串拼接时。
  • repr(x)转换对象x时。

则会调用这个对象的__repr__()方法。若没有,则不再看其是否有__str__()方法。若再没有,则显示其内存地址。

(2)示例

__str__方法一般放置的是一些解释说明的文字。

示例:

class Washer(): def __init__(self, width, height): self.width = width self.height = height def __str__(self): # return repr('这是海尔洗衣机的说明书') return '这是海尔洗衣机的说明书' # __repr__方法在实际工作总一般如下使用 __repr__ = __str__ haier1 = Washer(10, 20) # 结果:这是海尔洗衣机的说明书 print(haier1) 5、魔法方法__call__()

对象后面加括号,触发执行。

提示:

  • __init__方法的执行是由创建对象触发的,即:对象 = 类名()
  • 而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

示例:

class Person(object): def __init__(self): print("__init__方法执行了") def __call__(self, *args, **kwargs): print("__call__方法中执行了") # 1.对象 = 类名() p = Person() # 执行__init__ # 2.对象() 调用__call__方法 p() # 3.类()() 调用__call__方法 Person()() # 执行__call__

提示:这个方法在工作中的应用自己以后总结,先知道怎么用就好。

6、魔法方法__len__()

__len__()方法在listdictsettuplestr等序列中都存在,而在intfloat类中是不存在的。

print('__len__' in dir(int)) # False print('__len__' in dir(float)) # False print('__len__' in dir(str)) # True print('__len__' in dir(list)) # True print('__len__' in dir(tuple)) # True print('__len__' in dir(dict)) # True print('__len__' in dir(set)) # True

如果一个类要表现得像一个list一样,有需求要获取有多少个元素,就得用 len() 函数。

要让 len() 函数工作正常,类中就必须提供一个魔法方法__len__()方法,它的作用是返回元素的个数。

示例:

# 定义一个类,接收同学名的名字 class Students(object): def __init__(self, *args): self.names = args def __len__(self): return len(self.names) stu = Students('唐僧', '孙悟空', '猪八戒', '沙和尚') print(len(stu)) # 4 print(stu.__len__()) # 4

提示:只要在类中正确实现了__len__()方法,就可以用len()函数。

7、魔法方法__getitem__()__setitem__()__delitem__()

在Python中,如果我们想实现创建类似于序列和映射的类,可以通过重写魔法方法__getitem__()方法、__setitem__()方法、__delitem__()方法去模拟。

示例:

class MyDict(object): def __init__(self): self.item = {} # 获取成员 def __getitem__(self, key): return self.item.get(key) # 添加成员 def __setitem__(self, key, value): self.item[key] = value # 删除成员 def __delitem__(self, key): del self.item[key] # 获取人员数量 def __len__(self): return len(self.item) if __name__ == "__main__": # 创建序列对象 myDict = MyDict() # 添加元素 myDict.__setitem__('师傅', '唐憎') myDict.__setitem__('大师兄', '孙悟空') # 查看刚添加的成员 print(myDict.__getitem__('大师兄')) print(f"现在成员{len(myDict)}人", ) # 2 # 修改成员 myDict.__setitem__('大师兄', '齐天大圣') print(myDict.__getitem__('大师兄')) print(f"现在成员{len(myDict)}人", ) # 2 # 删除元素 myDict.__delitem__('师傅') print(f"现在成员{len(myDict)}人", ) # 1 """ 输出结果: 孙悟空 现在成员2人 齐天大圣 现在成员2人 现在成员1人 """

参考:

  • www.cnblogs.com/woniuxy/p/11507648.html
  • blog.csdn.net/chf1142152101/java/article/details/78715296
  • www.cnblogs.com/oddgod/p/10992366.html