Python魔法方法功能与用法简介


Posted in Python onApril 04, 2019

本文实例讲述了Python魔法方法功能与用法。分享给大家供大家参考,具体如下:

1、什么是魔法方法?

魔法方法就是可以给你的类增加魔力的特殊方法,如果你的对象实现(重载)了这些方法中的某一个,那么这个方法就会在特殊的情况下被 Python 所调用,你可以定义自己想要的行为,而这一切都是自动触发的。它们经常是两个下划线包围来命名的(比如 __init____lt__),Python的魔法方法是非常强大的,所以了解其使用方法也变得尤为重要!

2、__init__(self[, ...]),__new__(cls[, ...]),__del__(self)

1)__init__ 构造器,当一个实例被创建的时候初始化的方法。但是它并不是实例化调用的第一个方法,__new__才是实例化对象调用的第一个方法,它只取下 cls 参数,并把其他参数传给 __init__。 __new__很少使用,但是也有它适合的场景,尤其是当类继承自一个像元组或者字符串这样不经常改变的类型的时候。

2)__new__ 使用时注意以下四点:

  • a) __new__  是在一个对象实例化的时候所调用的第一个方法;
  • b)它的第一个参数是这个类,其他的参数是用来直接传递给 __init__ 方法;
  • c) __new__  返回一个构建的实例;
  • d) __new__  决定是否要使用该 __init__ 方法,因为 __new__ 可以调用其他类的构造方法或者直接返回别的实例对象来作为本类的实例,如果 __new__ 没有返回实例对象,则__init__ 不会被调用;
  • e) __new__  主要是用于继承一个不可变的类型比如一个 tuple 或者 string。

__new__实现单例模式(无论多少次实例化,结果都是同一个实例)

单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。

比如,某个服务器程序的配置信息存放在一个文件中,客户端通过一个 AppConfig 的类来读取配置文件的信息。如果在程序运行期间,有很多地方都需要使用配置文件的内容,也就是说,很多地方都需要创建 AppConfig 对象的实例,这就导致系统中存在多个 AppConfig 的实例对象,而这样会严重浪费内存资源,尤其是在配置文件内容很多的情况下。事实上,类似 AppConfig 这样的类,我们希望在程序运行期间只存在一个实例对象。

举例:

class Person(object):
  def __init__(self, name, age):
    self.name = name
    self.age = age
  def __new__(cls, *args, **kwargs):
    if not hasattr(cls,'instance'):
      cls.instance = super().__new__(cls)
    return cls.instance
a = Person('p1',21)
b = Person('p2',22)
print(a == b, a.name == b.name)    # 这里的打印结果都是True,可见 a 和 b 都是同一个实例(实例 b 覆盖了实例 a)。
# 单例作用:
  #第一、控制资源的使用,通过线程同步来控制资源的并发访问;
  #第二、控制实例产生的数量,达到节约资源的目的;
  #第三、作为通信媒介使用,也就是数据共享。比如,数据库连接池的设计一般采用单例模式,数据库连接是一种数据库资源。
# 应用场景:
  #Python的logger就是一个单例模式,用以日志记录
  #线程池、数据库连接池等资源池一般也用单例模式
  #Windows的资源管理器是一个单例模式
  #网站计数器

3)__del__ 析构器,当实例被销毁时调用。

3、__call__(self[,args ...]),__getitem__(self,key),__setitem__(self,key,value)

1)__call__ 允许一个类的实例像函数一样被调用,如下。

class Person(object):
  def __init__(self, name, age):
    self.name = name
    self.age = age
    self.instance = add
  def __call__(self,*args):
    return self.instance(*args)
def add(args):
  return args[0] + args[1]
a = Person('p1', 20)
print(a([1,2]))
#这里将打印 3
#可见当创建a这个对象之后,如果定义了__call__函数则对象是可以像函数一样调用的。

2)__getitem__ 定义获取容器中指定元素的行为,相当于self[key],如下。

class Person(object):
  def __init__(self, name, age):
    self.name = name
    self.age = age
    self._registry = {
      'name': name,
      'age': age
    }
  def __call__(self, *args):
    return self.instance(*args)
  def __getitem__(self, key):
    if key not in self._registry.keys():
      raise Exception('Please registry the key:%s first !' % (key,))
    return self._registry[key]
a = Person('p1', 20)
print(a['name'],a['age'])
#这里打印的是 'p1' 20
#可见__getitem__使实例可以像字典一样访问

3)__setitem__ 设置容器中指定元素的行为,相当于self[key] = value

4、__getattr__(self,name),__getattribute__(self,name),__setattr__(self,name,value),__delattr__(self,name)

1)__getattr__ ():当用户试图访问一个不存在属性时触发;

2)__getattribute__(): 当一个属性(无论存在与否)被访问时触发;

3)__setattr__ ():当一个属性被设置时触发;

4)__delattr__ ():当一个属性被删除时触发。

class Person(object):
  def __init__(self, name, age):
    self.name = name
    self.age = age
    self._registry = {
      'name': name,
      'age': age
    }
  def __getattribute__(self, item):
    #注意此处不要再访问属性,如self.__dict__[item]
    #因为self.__dict__依然会被__getattribute__拦截,这样就会陷入死循环
    return object.__getattribute__(self,item)
  def __getattr__(self, item):
    print("don't have the attribute ",item)
    return False
  def __setattr__(self, key, value):
    self.__dict__[key] = value
a = Person('p1', 20)
print(a.cs)      #这里会打印 don't have the attribute cs 以及 False
a.cs = '测试'     #这里设置该属性值为'测试'
print(a.cs)      #这里将打印出'测试'

希望本文所述对大家Python程序设计有所帮助。

Python 相关文章推荐
Python中字符串的常见操作技巧总结
Jul 28 Python
Python实现的文本编辑器功能示例
Jun 30 Python
python自动12306抢票软件实现代码
Feb 24 Python
python增加矩阵维度的实例讲解
Apr 04 Python
[原创]windows下Anaconda的安装与配置正解(Anaconda入门教程)
Apr 05 Python
对Python的交互模式和直接运行.py文件的区别详解
Jun 29 Python
python进程的状态、创建及使用方法详解
Dec 06 Python
TensorFlow 读取CSV数据的实例
Feb 05 Python
Win10下安装并使用tensorflow-gpu1.8.0+python3.6全过程分析(显卡MX250+CUDA9.0+cudnn)
Feb 17 Python
Linux安装Python3如何和系统自带的Python2并存
Jul 23 Python
Python编解码问题及文本文件处理方法详解
Jun 20 Python
Python几种酷炫的进度条的方式
Apr 11 Python
详解pandas.DataFrame中删除包涵特定字符串所在的行
Apr 04 #Python
pandas删除指定行详解
Apr 04 #Python
详解python之heapq模块及排序操作
Apr 04 #Python
python实现kmp算法的实例代码
Apr 03 #Python
详解python多线程之间的同步(一)
Apr 03 #Python
Python将列表数据写入文件(txt, csv,excel)
Apr 03 #Python
详解python读取image
Apr 03 #Python
You might like
PHP入门教程之数学运算技巧总结
2016/09/11 PHP
PHP 中魔术常量的实例详解
2017/10/26 PHP
PHP与Web页面的交互示例详解一
2020/08/04 PHP
js jquery做的图片连续滚动代码
2008/01/06 Javascript
JS 巧妙获取剪贴板数据 Excel数据的粘贴
2009/07/09 Javascript
jQuery1.6 使用方法二
2011/11/23 Javascript
javascript中window.open在原来的窗口中打开新的窗口(不同名)
2015/11/15 Javascript
基于JavaScript实现鼠标悬浮弹出跟随鼠标移动的带箭头的信息层
2016/01/18 Javascript
JS中实现函数return多个返回值的实例
2017/02/21 Javascript
AngularJS中filter的使用实例详解
2017/08/25 Javascript
jQuery EasyUI开发技巧总结
2017/09/26 jQuery
使用vue如何构建一个自动建站项目
2018/02/05 Javascript
安装vue-cli的简易过程
2018/05/22 Javascript
mpvue 如何使用腾讯视频插件的方法
2018/07/16 Javascript
vue配置nprogress实现页面顶部进度条
2019/09/21 Javascript
浅析Vue 中的 render 函数
2020/02/28 Javascript
通过vue.extend实现消息提示弹框的方法记录
2021/01/07 Vue.js
[01:20]DOTA2 齐天大圣至宝动态展示
2016/12/13 DOTA
Python自动化测试工具Splinter简介和使用实例
2014/05/13 Python
整理Python 常用string函数(收藏)
2016/05/30 Python
深入浅析ImageMagick命令执行漏洞
2016/10/11 Python
一行代码让 Python 的运行速度提高100倍
2018/10/08 Python
python pyinstaller 加载ui路径方法
2019/06/10 Python
教你如何编写、保存与运行Python程序的方法
2019/07/12 Python
Pycharm连接远程服务器并实现远程调试的实现
2019/08/02 Python
python发qq消息轰炸虐狗好友思路详解(完整代码)
2020/02/15 Python
哪种Python框架适合你?简单介绍几种主流Python框架
2020/08/04 Python
Python爬虫设置Cookie解决网站拦截并爬取蚂蚁短租的问题
2021/02/22 Python
利用CSS3实现平移动画效果示例代码
2016/10/12 HTML / CSS
理肤泉英国官网:La Roche-Posay英国
2019/01/14 全球购物
盖尔斯工厂店:GUESS Factory
2020/01/21 全球购物
彩妆大赛策划方案
2014/05/13 职场文书
六一儿童节主持开场白
2015/05/28 职场文书
golang 实现对Map进行键值自定义排序
2021/04/28 Golang
SpringRetry重试框架的具体使用
2021/07/25 Java/Android
详解Vue项目的打包方式(生成dist文件)
2022/01/18 Vue.js