python神秘的魔法函数_python魔法函数

一、参考

二、构造和初始化

2.1 __new__

在对象实例化过程中最先调用的方法是__new__, 该方法接收参数为类,然后将其他参数,传递给__init__, 该魔法函数比较少见,可以使用其,创建单例类; __new__方法是一个类方法,需要携带的第一个参数是类

class T1(object):

_instances = {}

def __new__(class_, *args, **kwargs):

if class_ not in class_._instances:

class_._instances[class_] = super(T1, class_).__new__(class_, *args, **kwargs)

return class_._instances[class_]

def __init__(self, *args, **kwargs):

pass

2.2 __init__

__init__是一个实例方法,用于将构造的实例初始化,在类定义中十分常见

2.3 __del__

类比于C++, __new__和__init__可以当作类的构造函数,__del__充当类的析构函数,该函数在垃圾回收时候调用,而不是在del object时候触发,可以用于添加套接字或者文件的close()逻辑,但是使用需要小心,实际几乎不使用该方法

from os.path import join

class FileObject:

'''Wrapper for file objects to make sure the file gets closed on deletion.'''

def __init__(self, filepath='~', filename='sample.txt'):

# open a file filename in filepath in read and write mode

self.file = open(join(filepath, filename), 'r+')

def __del__(self):

self.file.close()

del self.file

三、重定义运算符

四、获取类表示信息

4.1 __str__

__str__(self)

自定义对类调用str()方法时候的行为

4.2 __repr__

__repr__(self)

定义对类的实例调用repr()时候的行为,str()和repr()的不同之处是:目标受众的不同,repr()的目的是生成主要是机器可读的输出,许多情况下,可能输出为python代码, 而str()一般输出为人类可读的信息

4.3 __unicode__

__unicode__(self)

定义对类实例执行unicode()方法时候的行为,其返回unicode字符串,如果只定义了unicode(),使用str()会报错,所以需要同事定义两个函数

4.4 __format__

__format__(self, formatstr)

定义在新样式字符串格式中使用类实例时候的行为

4.5 __hash__

__hash__(self)

当调用hash()函数时候定义行为,通常用于字典中的key的快速比较是否相同,通常也需要实现__eq__, 遵循下面的规则,

a == b 实际为 hash(a) == hash(b)

4.6 __nonzero__

__nonzero__(self)

定义对类的实例调用bool()时候的行为,返回值为True或者False,取决于具体的类

4.7 __dir__

__dir__(self)

定义对类的实例调用dir()函数时候的行为,返回值是用户的属性列表,通常,实现dir()函数是不必要的,但是,如果重新定义了__getattr__或者__getattribute__或者其他动态生成属性,则其对于交互式使用类非常重要

4.8 __sizeof__

__sizeof__(self)

定义对类实例调用sys.getsizeof()函数时候的行为,返回值为对象的大小(字节为单位),通常对于C扩展实现的Python类有作用

五、控制属性访问

如果与其他语言比较(例如: Java),Python中好像没有真正的封装,例如,没有办法通过公共函数getter和setter定义私有属性,这是事实。

Python通过下列的魔法函数实现属性的封装,而不是使用显式的修饰符

5.1 __getattr__

__getattr__(self, name)

可以定义当用户试图访问一个不存在的属性时候的行为,这对于捕获或者重定向常见的拼写错误、引发警告等非常有用,只有当访问不存在的属性时候才会调用该方法,因此它不是真正的封装解决方案

5.2 __setattr__

__setattr__(self, name, value)

与__getattr__不相同,__setattr__是一种封装解决方案,允许定义分配属性值的行为,如果该属性值已经存在,则会覆盖,由此可以自定义属性值的赋值规则

def __setattr__(self, name, value):

self.name = value

# since every time an attribute is assigned, __setattr__() is called, this

# is recursion.

# so this really means self.__setattr__('name', value). Since the method

# keeps calling itself, the recursion goes on forever causing a crash

由上,代码self.name = value会调用__setattr__内置函数,所以会导致循环无限递归,正确的定义方式为

def __setattr__(self, name, value):

self.__dict__[name] = value # assigning to the dict of names in the class

# define custom behavior here

5.3 __delattr__

__delattr__(self, name)

与__setattr__相同,但是作用是删除属性而不是设置属性,为了防止无限递归,还需要采取与__setattr__相同的预防措施(在__delattr__的实现中调用del self.name将导致无限递归)

5.4 __getattribute__

__getattribute__(self, name)

不建议使用该函数,因为极少情况下可以不产生bug正确使用。

每次获取属性时候,都会调用该函数

5.5 总结

Python的魔法方法非常重要且强大,如果任意使用可能会带来破坏,因此,在已经充分了解了自定义属性访问之前,不要随意使用该魔法方法,事实上,魔法方法往往过于强大和反直觉,它存在的原因是:通过它,可以自由的做任何想做的事情,但是如果不充分熟悉,使用将会非常困难。

class AccessCounter(object):

'''A class that contains a value and implements an access counter.

The counter increments each time the value is changed.'''

def __init__(self, val):

super(AccessCounter, self).__setattr__('counter', 0)

super(AccessCounter, self).__setattr__('value', val)

def __setattr__(self, name, value):

if name == 'value':

super(AccessCounter, self).__setattr__('counter', self.counter + 1)

# Make this unconditional.

# If you want to prevent other attributes to be set, raise AttributeError(name)

super(AccessCounter, self).__setattr__(name, value)

def __delattr__(self, name):

if name == 'value':

super(AccessCounter, self).__setattr__('counter', self.counter + 1)

super(AccessCounter, self).__delattr__(name)

六、自定义序列

七、反射

八、可调用对象

在python中,函数是第一类对象,这意味着它们可以被传递给函数和方法,好像其他第一类对象一样(数值、字符串等),而这是一个非常强大的功能。

通过魔法函数__call__,可以使得实例也表现的像函数一样,以便可以调用实例,可以将实例作为参数在函数调用中传递。

8.1 __call__

__call__(self, [args...])

允许将实例进行函数调用,如下,实际作用为e(5,6)实际为调用e.__call__(5,6)

在经常需要修改实例的状态的场景下,使用__call__调用实例,修改实例状态是一种十分直观且优雅的方式

class Entity(object):

'''Class to represent an entity. Callable to update the entity's position.'''

def __init__(self, size, x, y):

self.x, self.y = x, y

self.size = size

def __call__(self, x, y):

'''Change the position of the entity.'''

self.x, self.y = x, y

if __name__ == '__main__':

e = Entity(size=10, x=1, y=2)

print(e)

e(5, 6)

print(e)

九、上下文管理

十、抽象基类

十一、描述符对象

十二、复制

十三、序列化对象

十四、结论

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

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

相关文章

python扫雷 广度优先_广度优先搜索(BFS)解题总结

定义 广度优先搜索算法(Breadth-First-Search),是一种图形搜索算法。 简单的说,BFS是从根节点开始,沿着树(图)的宽度遍历树(图)的节点。 如果所有节点均被访问,则算法中止。 BFS同样属于盲目搜索。 一般用队…

python默认参数陷阱_python默认参数陷阱

0|1陷阱?学过函数的人一定听说过函数的默认参数,关于函数的默认参数,请看以下的例子:def extendList(val, lst[]):lst.append(val)return lstlist1 extendList(10)list2 extendList(123, [])print(list1 %s % list1)print(list…

python裁剪图片并保存_python – 如何从图像中剪切轮廓并将其保存到新文件中

大家好,这是我的第一个问题所以请保持温和.我有一个计算机视觉领域的项目,我是新的,我会很感激一些帮助.我有一个pcb的图像,我的(首先)任务是从背景中切断电路板并将其保存到新文件.如果结果只是没有灰色背景的普通pcb,那就没问题了. 我到目前为止尝试的是,首先使用阈值将图像转…

opencv如何把一个矩阵不同列分离开_学习OPEN_CV

OpenCv中文论坛精华地址http://www.opencv.org.cn/index.php/User:Ollydbg23http://sivp.sourceforge.net/(sivp)一、基础操作1. 数据类型 数据结构了解图像相关:cvArr cvMat IplImage数据数组的维数, 与数据的通道数 见P46 (76)2. 常见的矩阵操作熟悉3…

python文件合并_用Python 将两个文件的内容合并成一个新的文件.

一个文件的内容是:IntroductiontoProgramming,NetworkingFundamentals,InternetworkingTechnologies,PlatformTechnologies,InformationTechnologyforUsers,ComputerForensics,Enterpr... 一个文件的内容是: Introduction to Programming, Networking Fundamentals, Internetwo…

flash代码_Flash如何对制作文件进行优化

对FLASH进行优化分为两方面,一方面是代码上的优化,主要是通过优化提高FLASH性能,降低CPU占用和内存使用。另一方面是资源的优化,这方面的优化是为了减小编译后的文件大小以及制作文件的大小,因为如果不进行相应的优化&…

潜流式湿地计算_人工湿地计算书

人工湿地计算书1、尾水提升泵房集水池基本参数集水池设计规模为30000m3/d,约折合1250m3/h,按水力停留时间HRT为0.25 h计,集水井有效容积应为312.5 m3,考虑到与污水厂原有排污管道相契合,集水设计尺寸为:LBH…

deepin系统转为windows_windows系统下安装深度系统deepin

前期准备DiskGenius(用来扩展分区)deepin-20-amd64.iso(深度系统镜像文件)相关文件下载首先下载安装时要用的工具,分别为:DiskGenius , UltraISODiskGenius是一款磁盘工具,创建系统分区。UltraISO是用来打开系统光盘镜像文件工具。Win8/8.1/10无需下载Ul…

c3等待加载样式 vue_Vue.js__简易加载等待动画

Vue.js__简易加载等待动画Vue实现为览或讲琐了过自系一读页围这就多网解元当维自加,加载动画的样式取自其他出处,侵直分调浏器代,刚求的一学础过功互有解小久宗点差维含数删。将Vue属性览或讲琐了过自系一读页围这就多网解元当维和方法复制到…

软件开发模型_QT开发(二十三)——软件开发流程

一、软件开发流程简介软件开发流程是通过一系列步骤保证软件产品的顺利完成,是软件产品在生命周期内的管理学。软件开发流程的本质是软件开发流程与具体技术无关,是开发团队必须遵守开的规则。二、常见软件开发流程模型常见的软件开发流程模型包括即兴模…

python循环语句for计数_Bash For循环(递增计数)与for循环用法详解

先来看for循环的例子&#xff1a;用Bash Shell的for循环&#xff0c;每次递增数是500。复制代码 代码示例:#!/bin/bash##每次递增的数ADD_NUM500#递增1的话取消下行注释&#xff0c;并相应的注释另一句for的开头的#for ((i1;i<29500;i))#递增定义的数for ((i1;i<29500;i$…

python3.6.2用pyinstaller3.4报错_OceanBase 2.2 版本体验:用 BenchmarkSQL 跑 TPC-C

OB君&#xff1a;好消息&#xff01;「 OceanBase 2.2 版本 」正式上线官网啦&#xff01;&#xff08;点击阅读原文即可直接下载&#xff09;OceanBase 2.2版本是成功支撑2019年天猫双11大促的稳定版本&#xff0c;同时也是用于TPC-C测试且荣登TPC-C性能榜首的版本。我们将在接…

hive窗口函数_Hive sql窗口函数源码分析

在了解了窗口函数实现原理 spark、hive中窗口函数实现原理复盘 和 sparksql比hivesql优化的点(窗口函数)之后&#xff0c;今天又撸了一遍hive sql 中窗口函数的源码实现&#xff0c;写个笔记记录一下。简单来说&#xff0c;窗口查询有两个步骤&#xff1a;将记录分割成多个分区…

容大打印机ip修改工具_M1芯片版Mac无法连接打印机怎么办?

文末有优惠券在入手了M1芯片版MacBook Pro后&#xff0c;昨天我打算连接一下实验室的打印机。这个打印机的型号是HP LaserJet Professional M1213nf MFP&#xff0c;在同一个局域网内通过搜索IP即可连接。在我的旧设备2015款MacBook Air上&#xff0c;很轻松就连接了打印机。可…

语音对讲软件_三款语音转文字工具,语音输入,高效转换,准确率高

关于语音转文字的软件我在之前讲了很多&#xff0c;有些人听了也用了&#xff0c;效果不错&#xff0c;有些人看了就忘了&#xff0c;主要是不知道用它干嘛&#xff0c;其实语音转文字的软件主要功能就是为了让自己在写作的时候可以减少时间&#xff0c;提高效率&#xff0c;其…

linux中如何复制文件并重命名_linux复制重命名 linux复制一个文件并重命名

linux下怎么复制一个文件到另外一个目录并且重命名&#xff1f;使用Linux的CP命令复制一个文件&#xff0c;并指定一个新的文件名作为目标文件参数&#xff0c;实现复制文件时重命名文件的功能。例如&#xff0c;下面的命令将/root/fileaaa分配给/home目录并将其重命名为filebb…

python程序员搞笑段子_程序员的爆笑漫画和段子

Hi&#xff01;大家好呀&#xff01;我是你们幽默的喵哥&#xff01;每次推送&#xff0c;都是给大家推荐实用的项目或者技术&#xff0c;都比较枯燥。今天&#xff0c;喵哥就来给大家搞个有趣且幽默的。在程序员圈子中&#xff0c;我们也是有自己的职业文化的。比如&#xff0…

野火stm32呼吸灯程序_说一说STM32启动过程

STM32上电后是怎么启动的&#xff1f;main函数之前单片机都做了些什么&#xff1f;带着这些疑问我们开始进入游戏。。。。。首先&#xff0c;开局一张图&#xff0c;过程全靠编&#xff0c;如有说错的地方望能指正启动大致流程1- 上电启动或者硬件复位2- 单片机从0x00地址开始执…

linuxpython升级3.5_linux升级python3.5到3.6

在ubuntu里&#xff0c;zlib叫zlib1g&#xff0c;相应的zlib-devel叫zlib1g.dev。默认的安装源里没有zlib1g.dev。要在packages.ubuntu.com上找。$sudo apt-get install ruby然后再装zlib1g-dev就可以了$sudo apt-get install zlib1g-dev1. 安装必备的软件包centos: yum -y gro…

apache启动失败_请检查相关配置.√mysql5.1已启动._1、Apache启动失败,请检查相关配置-百度经验...

前几天电脑系统崩溃了,后边到服务中心重新恢复了系统,但是回来使用APMServ 5.2.6发现:1、Apache启动失败,请检查相关配置。√MySQL5.1已启动。系统的各种服务我都检查过了,都是正常开启的,百思不得其解,后边在百度上搜索一篇文章有个例子照做了以后结果成功了。---------------…