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批量修改文件名的实现代码
Sep 01 Python
Python打印scrapy蜘蛛抓取树结构的方法
Apr 08 Python
python实现bucket排序算法实例分析
May 04 Python
利用python求解物理学中的双弹簧质能系统详解
Sep 29 Python
详解如何用OpenCV + Python 实现人脸识别
Oct 20 Python
python xlsxwriter库生成图表的应用示例
Mar 16 Python
Python设计模式之建造者模式实例详解
Jan 17 Python
python通过paramiko复制远程文件及文件目录到本地
Apr 30 Python
pandas计算最大连续间隔的方法
Jul 04 Python
python中pandas库中DataFrame对行和列的操作使用方法示例
Jun 14 Python
python操作链表的示例代码
Sep 27 Python
python Django框架快速入门教程(后台管理)
Jul 21 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新手NOTICE错误常见解决方法
2011/12/07 PHP
PHP英文字母大小写转换函数小结
2014/05/03 PHP
php 数据结构之链表队列
2017/10/17 PHP
复制本贴标题和地址的js代码
2008/07/01 Javascript
JS 实现Json查询的方法实例
2013/04/12 Javascript
框架页面高度自动刷新的Javascript脚本
2013/11/01 Javascript
基于jQuery 实现bootstrapValidator下的全局验证
2015/12/07 Javascript
详解js图片轮播效果实现原理
2015/12/17 Javascript
jquery+json实现分页效果
2016/03/07 Javascript
jquery.cookie.js实现用户登录保存密码功能的方法
2016/04/15 Javascript
第一次接触神奇的Bootstrap菜单和导航
2016/08/01 Javascript
js判断手机号是否正确并返回的实现代码
2017/01/17 Javascript
vue中的计算属性的使用和vue实例的方法示例
2017/12/04 Javascript
Vue替代marquee标签超出宽度文字横向滚动效果
2019/12/09 Javascript
原生JavaScript实现刮刮乐
2020/09/29 Javascript
JavaScript实现滑块验证解锁
2021/01/07 Javascript
深入理解 Python 中的多线程 新手必看
2016/11/20 Python
Python爬取qq music中的音乐url及批量下载
2017/03/23 Python
Python实现的读取电脑硬件信息功能示例
2018/05/30 Python
python打包生成的exe文件运行时提示缺少模块的解决方法
2018/10/31 Python
python 顺时针打印矩阵的超简洁代码
2018/11/14 Python
python中pygame安装过程(超级详细)
2019/08/04 Python
win10系统Anaconda和Pycharm的Tensorflow2.0之CPU和GPU版本安装教程
2019/12/03 Python
pytorch中nn.Conv1d的用法详解
2019/12/31 Python
2020最新pycharm汉化安装(python工程狮亲测有效)
2020/04/26 Python
keras.utils.to_categorical和one hot格式解析
2020/07/02 Python
Numpy实现卷积神经网络(CNN)的示例
2020/10/09 Python
pytorch学习教程之自定义数据集
2020/11/10 Python
博柏利美国官方网站:Burberry美国
2020/11/19 全球购物
两道JAVA笔试题
2016/09/14 面试题
单位消防安全责任书
2014/07/23 职场文书
幼儿园教师自荐书
2015/03/06 职场文书
审查起诉阶段律师意见书
2015/05/19 职场文书
2019年鼓励无偿献血倡议书
2019/09/17 职场文书
经典人生语录分享:不畏将来,不念过去,笑对当下
2019/12/12 职场文书
SQL Server表分区降低运维和维护成本
2022/04/08 SQL Server