1.构造和析造

魔法方法就是被双下划线包围的方法

__init__()方法

__init__方法默认没有参数,返回值为none。类实例化对象需有明确的初始化步骤要重写函数

>>> class Rectangle:
def __init__(self,x,y):
self.x = x
self.y = y
def getPeri(self):
return (self.x+self.y)*2
def getArea(self):
return self.x * self.y >>> rect = Rectangle(3,4)
>>> rect.getPeri()
14
>>> rect.getArea()
12
>>> #init返回值一定是None
>>> class A:
def __init__(self):
return "A" >>> a = A()
Traceback (most recent call last):
File "", line 1, in
a = A()
TypeError: __init__() should return None, not 'str'

__new__()方法

__new__()方法在实例化对象时返回一个实例对象,参数是cls,是第一个被调用的方法

>>> class CapStr(str):
def __new__(cls,string):
string = string.upper()
return str.__new__(cls,string) >>> a = CapStr("I love FishC.com")
>>> a
'I LOVE FISHC.COM'

__del__()方法

__del__()方法在对象将要被销毁时被调用

>>> class C:
def __init__(self):
print("我是init方法,我被调用了")
def __del__(self):
print("我是del方法,我被调用了") >>> c1 = C()
我是init方法,我被调用了
>>> c2 = c1
>>> c3 = c2
>>> del c3
>>> del c2
>>> del c1
我是del方法,我被调用了

对象生成后,所有对它的引用都被del之后,才会启动垃圾回收机制

关于垃圾回收机制

2.算数运算

运算符 对应的魔法方法 中文注释
+ __ add__(self, other) 加法
- __ sub__(self, other) 减法
* __ mul__(self, other) 乘法
/ __ truediv__(self, other) 真除法
// __ floordiv__(self, other) 整数除法
% __ mod__(self, other) 取余除法
divmod(a, b) __ divmod__(self, other) 把除数和余数运算结果结合
** __ pow__(self, other[,modulo]) self的other次方再对modulo取余
<< __ lshift__(self, other) 按位左移
>> __ rshift__(self, other) 按位右移
& __ and__(self, other) 按位与操作
^ __ xor__(self, other) 按位异或操作(同为0,异为1)
__ or__(self, other) 按位或操作(有1则1)

反运算的魔方方法

>>> class Nint(int):
def __radd__(self,other):
return int.__sub__(self,other) >>> a = Nint(5)
>>> b = Nint(3)
>>> a + b
8
>>> 1 + b
2
>>> #此处执行了3-1,self是3,other是1

3. 简单定制(计时器)

time模块

import time as t

class MyTimer():
def __init__(self):
self.unit = ['年','月','日','小时','分','秒']
self.prompt = "未开始计时!"
self.lasted = []
self.begin = 0
self.end = 0
# 调用实例直接显示结果
def __str__(self):
return self.prompt __repr__ = __str__ # 计算两次计时器对象之和
def __add__(self, other):
prompt = "总共运行了"
result = []
for index in range(6):
result.append(self.lasted[index] + other.lasted[index])
if result[index]:
prompt += (str(result[index]) + self.unit[index])
return prompt # 开始计时
def start(self):
self.begin = t.localtime()
self.prompt = "提示:请先调用stop()停止计时!"
print("计时开始") # 停止计时 def stop(self):
if not self.begin:
print("提示:请先调用start()进行计时")
else:
self.end = t.localtime()
self._calc()
print("计时结束") # 内部方法,计算运行时间
def _calc(self):
self.lasted = []
self.prompt = "总共运行了"
for index in range(6):
self.lasted.append(self.end[index] - self.begin[index])
if self.lasted[index]:
self.prompt += (str(self.lasted[index]) + self.unit[index])
# 为下一轮计时初始化变量
self.begin = 0
self.end = 0
print(self.prompt) >>> t1 = MyTimer()
>>> t2 = MyTimer()
>>> t1.start()
计时开始
>>> t2.start()
计时开始
>>> t1.stop()
总共运行了1分21秒
计时结束
>>> t2.stop()
总共运行了15秒
计时结束
>>> t1
总共运行了1分21秒
>>> t2
总共运行了15秒
>>> t1+t2
'总共运行了1分36秒'

利用perf_counter()和process_time()

import time as t

class MyTimer:
def __init__(self):
self.prompt = "未开始计时"
self.lasted = 0.0
self.begin = 0
self.end = 0
self.default_timer = t.perf_counter def __str__(self):
return self.prompt
__repr__ = __str__
def __add__(self,other):
result = self.lasted + other.lasted
prompt = "总共运行了%0.2f秒" % result
return prompt
def start(self):
self.begin = self.default_timer()
self.prompt = "提示:请先调用stop()停止计时"
print("计时开始!")
def stop(self):
if not self.begin:
print("提示:请先调用start()开始计时")
else:
self.end = self.default_timer()
self._calc()
print("计时结束")
def _calc(self):
self.lasted = self.end - self.begin
self.prompt = "总共运行了%0.2f秒" % self.lasted
print(self.prompt)
self.begin = 0
self.end = 0 def set_timer(self,timer):
if timer == 'process_time':
self.default_timer = t.process_time
elif timer == 'perf_counter':
self.default_timer = t.perf_counter
else:
print("输入无效") t1 = MyTimer()
t1.set_timer('perf_counter')
t1.start()
t.sleep(5.2)
t1.stop()
t2 = MyTimer()
t2.set_timer('perf_counter')
t2.start()
t.sleep(5.2)
t2.stop()
print(t1 + t2) >>>
计时开始!
总共运行了5.23秒
计时结束
计时开始!
总共运行了5.21秒
计时结束
总共运行了10.44秒
>>>

4.属性访问

魔法方法 含义
__ getattr__(self, name) 定义当用户试图获取一个不存在的属性时的行为
__ getattribute__(self, name) 定义当该类的属性被访问时的行为
__ setattr__(self, name, value) 定义当一个属性被设置时的行为
__ delattr__(self, value) 定义当一个属性被删除时的行为

避免属性魔法方法的死循环:

使用super()调用基类、给特殊属性__dict__赋值

class Rectangle:
def __init__(self,width=0,height=0):
self.width = width
self.height = height def __setattr__(self,name,value):
if name == 'square':
self.width = value
self.height = value
else: #避免死循环的两种方式
# super().__setattr__(name,value)
self.__dict__[name] = value def getArea(self):
return self.width * self.height >>> r1 = Rectangle(4,5)
>>> r1.getArea()
20
>>> r1.square = 10
>>> r1.getArea()
100
>>>

5. 描述符

将某种特殊类型的类的实例指派给另一个类的属性

__get__(self,instance,owner) 访问属性,返回属性的值
__set__(self,instance,value) 在属性分配中调用,不返回任何内容
__delete__(self,instance) 控制删除操作,不返回任何值
>>> class Mydecript:
def __get__(self,instance,owner):
print("getting...",self,instance,owner)
def __set__(self,instance,value):
print("setting...",self,instance,value)
def __delete__(self,instance):
print("deleting...",self,instance) >>> class Test:
x = Mydescript() Traceback (most recent call last):
File "", line 1, in
class Test:
File "", line 2, in Test
x = Mydescript()
NameError: name 'Mydescript' is not defined
>>> class Test:
x = Mydecript()
#Mydecript是x的描述类 >>> test = Test()
>>> test.x
getting... <__main__.Mydecript object at 0x030EAFB0> <__main__.Test object at 0x03108050>
>>> test.x = "X-man"
setting... <__main__.Mydecript object at 0x030EAFB0> <__main__.Test object at 0x03108050> X-man
>>> del test.x
deleting... <__main__.Mydecript object at 0x030EAFB0> <__main__.Test object at 0x03108050>

例题:温度的转换

class Celsius:
def __init__(self,value = 26.0):
self.value = float(value) def __get__(self,instance,owner):
return self.value def __set__(self,instance,value):
self.value = float(value) class Fahrenheit:
def __get__(self,instance,owner):
return instance.cel * 1.8 + 32 def __set__(self,instance,value):
instance.cel = (float(value) - 32) / 1.8 class Temperature:
cel = Celsius()
fah = Fahrenheit() >>> temp = Temperature()
>>> temp.cel
26.0
>>> temp.cel = 30
>>> temp.fah
86.0
>>> temp.fah = 100
>>> temp.cel
37.77777777777778
>>>

6.定制序列

Python魔法方法详解

例题:编写一个不可变的自定义列表,要求记录列表中每个元素被访问的次数

class CountList:
def __init__(self,*args):
self.values = [x for x in args]
self.count = { }.fromkeys(range(len(self.values)),0) def __len__(self):
return len(self.values) def __getitem__(self,key):
self.count[key] += 1
return self.values[key] >>> c1 = CountList(1,3,5,7,9)
>>> c1[1]
3
>>> c2 = CountList(2,4,6,8,10)
>>> c2[1]
4
>>> c1[1]+c2[1]
7
>>> c1.count
{0: 0, 1: 2, 2: 0, 3: 0, 4: 0}
>>> c2[1]
4
>>> c2.count
{0: 0, 1: 3, 2: 0, 3: 0, 4: 0}
>>>

7.迭代器

迭代器是实现了__next__()方法的对象,不能回退

>>> string = "FishC"
>>> it = iter(string)
>>> next(it)
'F'
>>> next(it)
'i'
>>> next(it)
's'
>>> next(it)
'h'
>>> next(it)
'C'
>>> next(it)
Traceback (most recent call last):
File "", line 1, in
next(it)
StopIteration
>>> string = "FishC"
>>> it = iter(string)
>>> while True:
try:
each = next(it)
except StopIteration:
break
print(each) F
i
s
h
C
>>> for each in string:
print(each) F
i
s
h
C
>>>

例题:使用迭代器实现斐波那契数列

>>> class Fibs:
def __init__(self,n=10):
self.a = 0
self.b = 1
self.n = n
def __iter__(self):
return self
def __next__(self):
self.a,self.b = self.b,self.a + self.b
if self.a > self.n:
raise StopIteration
return self.a >>> fibs = Fibs()
>>> for each in fibs:
print(each) 1
1
2
3
5
8

Python学习笔记(七)——魔法方法的更多相关文章

  1. Python学习笔记:魔术方法详解

    准备工作 为了确保类是新型类,应该把 _metaclass_=type 入到你的模块的最开始. class NewType(Object): mor_code_here class OldType: ...

  2. Python学习笔记七

    面向对象编程 面向对象的特性如下: 类:具有相同属性和方法的一类事物,成为类. 对象:类的实例化后的结果,一个类可以实例化多个对象,每个对象也可以不同的属性. 封装:在类中对数据的赋值,类里面包含着类 ...

  3. Python学习笔记七-错误和异常

    程序员总是和各种错误打交道,学习如何识别并正确的处理程序错误是很有必要的. 7.1错误和异常 1.错误 从软件方面来看,错误分为语法错误和逻辑错误两种.这两种错误都将导致程序无法正常进行下去,当Pyt ...

  4. python学习笔记七——字典

    4.3 字典结构 字典是Python中重要的数据类型,字典的由“键-值”对组成的集合,字典中的“值”通过“键”来引用. 4.3.1 字典的创建 字典由一系列的“键-值”(key-value)对组成,“ ...

  5. python学习笔记之split()方法与with

    Python split()方法 以下内容摘自:http://www.runoob.com/python/att-string-split.html 描述 Python split()通过指定分隔符对 ...

  6. python学习笔记(七) 类和pygame实现打飞机游戏

    python中类声明如下: class Student(object): def __init__(self, name, score): self.name = name self.score = ...

  7. python学习笔记(七):面向对象编程、类

    一.面向对象编程 面向对象--Object Oriented Programming,简称oop,是一种程序设计思想.在说面向对象之前,先说一下什么是编程范式,编程范式你按照什么方式来去编程,去实现一 ...

  8. python学习笔记(七)-函数

    函数 方法 功能说白了,函数就是把一堆代码组合到一起,变成一个整体.函数不调用不会被执行.作用在于提高代码的复用性.定义函数 def greet_user(): """关 ...

  9. python学习笔记七 初识socket(进阶篇)

    socket socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. sock ...

  10. webdriver(python)学习笔记七——多层框架定位与智能等待

    多层框架或窗口定位: switch_to_frame() switch_to_window() 智能等待: implicitly_wait() 现在web应用中经常会遇到框架如(frame)或窗口(w ...

随机推荐

  1. Linux安装配置Nginx服务器

    如有需要可以加我Q群[308742428]大家一起讨论技术,有偿服务. 后面会不定时为大家更新文章,敬请期待. 喜欢的朋友可以关注下. 前言 今天搭建nginx服务器,来访问静态资源文件. Nginx ...

  2. Angular 4 变更检测机制 ChangeDetectorRef 使用方法

    1.在angular 2中,回调函数的返回结果,不会自动更新视图层的显示,可以用 ChangeDetectorRef 来驱动angular更新视图. import {ChangeDetectorRef ...

  3. sql语句练习50题(Mysql版-详加注释)

    表名和字段 1.学生表       Student(s_id,s_name,s_birth,s_sex) --学生编号,学生姓名, 出生年月,学生性别 2.课程表       Course(c_id, ...

  4. ZOJ-3662 Math Magic 背包DP

    这题不错,可惜我还是太弱了,没想到qwq. 看了网上大佬题解之后写的,对比了一下代码,好像我写的还是挺简洁的(逃,只是吞行比较多). 因为直接用lcm的值做下标会超时,所以我们观察发现可以组成lcm为 ...

  5. 笔记62 Spring Boot快速入门(二)

    SpringBoot部署 一.jar方式 1.首先安装maven. <1>下载最新的maven版本:https://maven.apache.org/download.cgi <2& ...

  6. 2、Python 接口框架

    common:存放通用的工具类 config:存放配置文件信息 result:存放result.html run_suite.py:最后执行的文件 1.excel_util:利用 openpyxl 进 ...

  7. hdu 5792 线段树+离散化+思维

    题目大意: Given a sequence A with length n,count how many quadruple (a,b,c,d) satisfies: a≠b≠c≠d,1≤a< ...

  8. [HCTF 2018]WarmUp

    靶场首页 打开靶场后,查看源码即可看到<!--source.php--> 打开source.php页面 代码如下 <?php     highlight_file(__FILE__) ...

  9. lct 模版题 bzoj 2002 2049

    很早就有人给我推荐的模版题,然后我最近才刷的(' '    ) 昨天的tree 不知道比他们高到哪里去了,我和他谈笑风生啊! bzoj 2002 弹飞绵羊 重点:这道题的cut和link 由于这道题链 ...

  10. Windows 安装 Anaconda3+PyCharm

    由于本人使用的是windows 10 操作系统,所以介绍在 windows 10 系统中安装 Anaconda3 的过程. 下载 Anaconda 官网下载地址:https://www.anacond ...