3.魔法方法

Python的对象天生拥有一些神奇的方法,它们总被双下划线所包围,他们是面向对象的 Python 的一切。他们是可以给你的类增加魔力的特殊方法,如果你的对象实现(重载)了这些方法中的某一个,那么这个方法就会在特殊的情况下被 Python 所调用,你可以定义自己想要的行为,而这一切都是自动发生的。

总之,Python 的魔术方法非常强大。

下面将列举这些魔法方法,并有针对性的对部分重点方法进行阐述。

3.1.基本的魔法方法

3.1.1.__new__和__init__

__new__方法是真正的类构造方法,用于产生实例化对象(空属性)。重写__new__方法可以控制对象的产生过程。

__init__方法是初始化方法,负责对实例化对象进行属性值初始化,此方法必须返回None,__new__方法必须返回一个对象。重写__init__方法可以控制对象的初始化过程。

使用__new__创建单例模式

class Person(object):

__instance = None

__init_flag = False

def __new__(cls, name):

if cls.__instance == None:

cls.__instance = object.__new__(cls)

return cls.__instance

else:

# 返回上一次创建的对象的引用

return cls.__instance

def __init__(self,name):

if Person.__init_flag == False:

self.name = name

Person.__init_flag = True

aP = Person('小明')

print(id(aP))

print(aP.name)

运行结果:

140005334645616

小明

bP = Person('小王')

print(id(bP))

print(bP.name)

运行结果:

140005334645616

小明

3.1.2.__str__和__repr__

两者的目的都是为了显式的显示对象的一些必要信息,方便查看和调试。__str__被print默认调用,__repr__被控制台输出时默认调用。即,使用__str__控制用户展示,使用__repr__控制调试展示。

class Person:

def __init__(self, name, age):

self.name = name

self.age = age

p = Person('小明', 26)

print(p)

运行结果:

class Person:

def __init__(self, name, age):

self.name = name

self.age = age

def __str__(self):

return f'{self.__class__}, {self.name}, {self.age}'

p = Person('小明', 26)

print(p)

运行结果:

, 小明, 26

3.1.3.__call__

__call__方法提供给对象可以被执行的能力,就像函数那样,而本质上,函数就是对象,函数就是一个拥有__call__方法的对象。拥有__call__方法的对象,使用callable可以得到True的结果,可以使用()执行,执行时,可以传入参数,也可以返回值。所以我们可以使用__call__方法来实现实例化对象作为装饰器:

对象变为可调用的

class Person(object):

def __init__(self, name):

self.name = name

def __call__(self, friend):

print('My name is %s...' % self.name)

print('My friend is %s...' % friend)

p = Person('小明')

p('小王')

运行结果:

My name is 小明...

My friend is 小王...

实例对象版本装饰器

class Checker:

def __init__(self, require_num):

self.require_num = require_num

def __call__(self, func):

self.func = func

def inner(*args, **kw):

if len(args) != self.require_num:

print('函数参数个数不符合预定义,无法执行函数')

return None

return self.func(*args, **kw)

return inner

@Checker(2)

def show(*args):

print('show函数成功执行!')

show(1)

运行结果:

函数参数个数不符合预定义,无法执行函数

3.1.4.__del__

__del__用于当对象的引用计数为0时自动调用。

__del__一般出现在两个地方:1、手工使用del减少对象引用计数至0,被垃圾回收处理时调用。2、程序结束时调用。

__del__一般用于需要声明在对象被删除前需要处理的资源回收操作

手工调用del 可以将对象引用计数减一,如果减到0,将会触发垃圾回收

class Person:

def __del__(self):

print('调用对象的del方法,此方法将会回收此对象内存地址')

p = Person() # 调用对象的__del__方法回收此对象内存地址

del p

print('下面还有程序其他代码')

运行结果:

调用对象的del方法,此方法将会回收此对象内存地址

下面还有程序其他代码

程序直接结束,也会调用对象的__del__方法回收地址

3.2.属性相关

相关使用说明,已经在描述符章节进行了阐述,这里再次总结下:

当使用obj.x = y的时候触发对象的setattr方法,当del obj.x的时候触发对象的delattr方法。

当尝试访问对象的一个不存在的属性时,会触发getattr方法,getattr方法是属性查找中优先级最低的。

如果定义了__getattr__,而没有任何代码(即只有pass),则所有不存在的属性值都是None而不会报错,可以使用super().__getattr__()方法来处理

__getatrribute__是一个属性访问截断器,即,在你访问属性时,这个方法会把你的访问行为截断,并优先执行此方法中的代码,此方法应该是属性查找顺序中优先级最高的。

属性查找顺序:实例的getattribute-->实例对象字典-->实例所在类字典-->实例所在类的父类(MRO顺序)字典-->实例所在类的getattr-->报错

3.3.比较操作符

class Car():

def __init__(self,carname,oilcp100km, price):

self.carname,self.oilcp100km,self.price = carname,oilcp100km, price

def __lt__(self,other):

print("execute __lt__")

return self.price

car1,car2 = Car('爱丽舍',8,10),Car('凯美瑞',7,27)

car1>car2

运行结果:

execute __lt__

False

3.4.算数运算符

3.5.反运算

3.6.增量赋值运算

3.7.一元操作符

3.8.类型转换

3.9.上下文管理(with 语句)

这两个方法的重写可以让我们对一个对象使用with方法来处理工作前的准备,以及工作之后的清扫行为。

class MySQL:

def connect(self):

print('启动数据库连接,申请系统资源')

def execute(self):

print('执行sql命令,操作数据')

def finish(self):

print('数据库连接关闭,清理系统资源')

def __enter__(self): # with的时候触发,并赋给as变量

self.connect()

return self

def __exit__(self, exc_type, exc_val, exc_tb): # 离开with语句块时触发

self.finish()

with MySQL() as mysql:

mysql.execute()

运行结果:

启动数据库连接,申请系统资源

执行sql命令,操作数据

数据库连接关闭,清理系统资源

3.10.容器类型

3.10.1.__iter__和__next__

这2个方法用于将一个对象模拟成序列。内置类型如列表、元组都可以被迭代,文件对象也可以被迭代获取每一行内容。重写这两个方法就可以实现自定义的迭代对象。

定义一个指定范围的自然数类,并可以提供迭代,使用for循环则不提示StopInteration错误

class Num:

def __init__(self, max_num):

self.max_num = max_num

self.count = 0

def __iter__(self):

return self

def __next__(self):

if self.count < self.max_num:

self.count += 1

return self.count

else:

raise StopIteration('已经到达临界')

num = Num(10)

for i in num:

print(i) # 循环打印1---10

运行结果:

1

2

3

4

5

6

7

8

9

10

使用next()方法依次迭代,最后提示StopInteration错误

num = Num(2)

print(next(num))

print(next(num))

print(next(num))

运行结果:

1

2

---------------------------------------------------------------------------

StopIteration Traceback (most recent call last)

in

2 print(next(num))

3 print(next(num))

----> 4 print(next(num))

in __next__(self)

13 return self.count

14 else:

---> 15 raise StopIteration('已经到达临界')

16

17 num = Num(10)

StopIteration: 已经到达临界

3.10.2.__getitem__、__setitem__和__delitem__

重写此系列方法可以模拟对象成列表或者是字典,即可以使用key-value的类型。

class PersonManager:

def __init__(self):

self.li = []

self.dic = {}

def __getitem__(self, item):

if isinstance(item, int):

# 通过下标得到对象

return self.dic[self.li[item]]

elif isinstance(item, slice):

# 通过切片得到一串对象

start = item.start

stop = item.stop

return [ self.dic[p] for p in self.li[start:stop]]

else:

# 给定的key类型错误

raise TypeError('你输入的key类型错误!')

def __setitem__(self,key,value):

self.li.append(key)

self.dic[key]=value

class Person:

def __init__(self, name):

self.name = name

def __str__(self):

return f'人员: {self.name}'

__repr__ = __str__

pm = PersonManager()

pm[0]= Person('小明')

pm[1]= Person('大白')

pm[2]= Person('小红')

pm[3]= Person('胖虎')

print(pm[0])

print(pm[0:3])

运行结果:

人员: 小明

[人员: 小明, 人员: 大白, 人员: 小红]

更多文章,请关注:

kmeans python interation flag_Python自学笔记-第六章面向对象编程(下)相关推荐

  1. 《疯狂Java讲义》学习笔记 第六章 面向对象(下)

    <疯狂Java讲义>学习笔记 第六章 面向对象(下) 6.1包装类 基本数据类型 包装类 byte Byte short Short int Integer long Long char ...

  2. Java基础学习——第六章 面向对象编程(下)

    Java基础学习--第六章 面向对象编程(下) 一.关键词:static 1. static关键字的引入 当我们编写一个类时,其实就是在描述其对象的属性和行为,而并没有产生实质上的对象,只有通过new ...

  3. 《疯狂Java讲义》学习笔记 第六章 面向对象(下续)

    这里## 6.6 Java 9改进的接口 6.6.1 接口的概念 6.6.2 Java 9中接口的定义 6.6.3接口的继承 ==以下代码中纯在自己的很多错误== 6.6.4使用接口 6.6.5接口和 ...

  4. Linux(b站视频兄弟连)自学笔记第六章——软件包管理

    Linux(b站视频兄弟连)自学笔记第六章--软件包管理 简介 软件包分类 RPM命令管理 包命令与依赖性 安装升级与卸载 查询 校验和文件提取 yum在线管理 IP地址的配置和网络yum源 yum命 ...

  5. 非零基础自学Golang 第18章 HTTP编程(下) 18.2 HTTP服务端 18.2.2 启动HTTP服务器 18.2.3 启动HTTPS服务器

    非零基础自学Golang 文章目录 非零基础自学Golang 第18章 HTTP编程(下) 18.2 HTTP服务端 18.2.2 启动HTTP服务器 18.2.3 启动HTTPS服务器 第18章 H ...

  6. Linux(b站视频兄弟连)自学笔记第十一章——shell编程

    Linux(b站视频兄弟连)自学笔记第十一章--shell基础 正则表达式 字符截取命令 cut命令 printf命令 awk命令 sed命令 字符处理命令 判断条件 流程控制 if语句 case语句 ...

  7. kmeans python interation flag_Python / Scipy Integration数组

    我正在尝试编写一个执行以下操作的程序: >从数组中获取V的值 >将V值传递给相对于E的积分 >将积分结果输出到数组I中 >情节I对抗V 这个等式看起来很讨厌,但除了V. Her ...

  8. keras之父《python深度学习》笔记 第六章

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 深度学习用于文本和序列 前言 一.处理文本数据 1.文本向量化介绍 2.one-hot编码 3.embedding编码 4.预训练词向 ...

  9. B站韩顺平java学习笔记(六)--面向对象编程章节

    目录 一.类和对象 1.定义及区别 2.对象内存布局 3.属性/成员变量 (1)基本介绍 (2)注意事项和细节说明 (3)访问属性 4.对象 (1)创建对象 (2)对象分配机制 ​(3)Java创建对 ...

最新文章

  1. UNITY2018 真机开启deepprofiling的操作
  2. spring-基于xml的aop开发-快速入门
  3. getResourceAsStream总是返回null以及intellij总是提示Argument ‘inputStream‘ might be null
  4. Lucifer的一场暴强围英雄表演
  5. A/B HDU - 1576 (逆元或拓展欧几里得或数学公式)多解法求大数结果
  6. 说明exit()函数作用的程序
  7. 串口服务器接无线网桥,AB7006-HMS串口服务器、Anybus-M主站、Anybus-S从站接口模块...
  8. c语言erfc函数,erf、erff、erfl、erfc、erfcf、erfcl
  9. MySQL 报错:Parameter ‘@XXX‘ must be defined.
  10. 计算机专业就业方向 【转】
  11. C语言自学指南(总觉 光阴不够)
  12. 安格鲁貂出现感冒如何解决?
  13. python小乌龟绘制迷宫_python小乌龟turtle数学作图
  14. 4ye含泪用python爬取了自己的公众号粉丝数据
  15. 华为防火墙应用层过滤--URL
  16. python语言入门(一)
  17. 企业上云要几步?中拓互联奉送企业上云全攻略
  18. 华为测试 称砝码
  19. C语言中内嵌汇编asm语法
  20. 突破IP封锁,共享网络

热门文章

  1. 【报告分享】京东大数据研究院:2020线上农产品消费趋势报告(附下载)
  2. Network Password Recovery工具查看windows凭据密码
  3. RobotFramework set global/suite/test variable
  4. java caller_callee和caller属性的区别
  5. 面试题:看数字找规律
  6. Binder的Native实现libbinder
  7. Go语言核心之美 2.6-常量
  8. python|excel分列--部分分列(pandas,concat)
  9. 【Unity3D日常开发】Unity中的资源加载与文件路径
  10. python倒背如流_python基本操作(五)