1.构造和析造

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

__init__()方法

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

  1. >>> class Rectangle:
  2. def __init__(self,x,y):
  3. self.x = x
  4. self.y = y
  5. def getPeri(self):
  6. return (self.x+self.y)*2
  7. def getArea(self):
  8. return self.x * self.y
  9. >>> rect = Rectangle(3,4)
  10. >>> rect.getPeri()
  11. 14
  12. >>> rect.getArea()
  13. 12
  14. >>> #init返回值一定是None
  15. >>> class A:
  16. def __init__(self):
  17. return "A"
  18. >>> a = A()
  19. Traceback (most recent call last):
  20. File "", line 1, in
  21. a = A()
  22. TypeError: __init__() should return None, not 'str'

__new__()方法

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

  1. >>> class CapStr(str):
  2. def __new__(cls,string):
  3. string = string.upper()
  4. return str.__new__(cls,string)
  5. >>> a = CapStr("I love FishC.com")
  6. >>> a
  7. 'I LOVE FISHC.COM'

__del__()方法

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

  1. >>> class C:
  2. def __init__(self):
  3. print("我是init方法,我被调用了")
  4. def __del__(self):
  5. print("我是del方法,我被调用了")
  6. >>> c1 = C()
  7. 我是init方法,我被调用了
  8. >>> c2 = c1
  9. >>> c3 = c2
  10. >>> del c3
  11. >>> del c2
  12. >>> del c1
  13. 我是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)

反运算的魔方方法

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

3. 简单定制(计时器)

time模块

  1. import time as t
  2. class MyTimer():
  3. def __init__(self):
  4. self.unit = ['年','月','日','小时','分','秒']
  5. self.prompt = "未开始计时!"
  6. self.lasted = []
  7. self.begin = 0
  8. self.end = 0
  9. # 调用实例直接显示结果
  10. def __str__(self):
  11. return self.prompt
  12. __repr__ = __str__
  13. # 计算两次计时器对象之和
  14. def __add__(self, other):
  15. prompt = "总共运行了"
  16. result = []
  17. for index in range(6):
  18. result.append(self.lasted[index] + other.lasted[index])
  19. if result[index]:
  20. prompt += (str(result[index]) + self.unit[index])
  21. return prompt
  22. # 开始计时
  23. def start(self):
  24. self.begin = t.localtime()
  25. self.prompt = "提示:请先调用stop()停止计时!"
  26. print("计时开始")
  27. # 停止计时
  28. def stop(self):
  29. if not self.begin:
  30. print("提示:请先调用start()进行计时")
  31. else:
  32. self.end = t.localtime()
  33. self._calc()
  34. print("计时结束")
  35. # 内部方法,计算运行时间
  36. def _calc(self):
  37. self.lasted = []
  38. self.prompt = "总共运行了"
  39. for index in range(6):
  40. self.lasted.append(self.end[index] - self.begin[index])
  41. if self.lasted[index]:
  42. self.prompt += (str(self.lasted[index]) + self.unit[index])
  43. # 为下一轮计时初始化变量
  44. self.begin = 0
  45. self.end = 0
  46. print(self.prompt)
  47. >>> t1 = MyTimer()
  48. >>> t2 = MyTimer()
  49. >>> t1.start()
  50. 计时开始
  51. >>> t2.start()
  52. 计时开始
  53. >>> t1.stop()
  54. 总共运行了121
  55. 计时结束
  56. >>> t2.stop()
  57. 总共运行了15
  58. 计时结束
  59. >>> t1
  60. 总共运行了121
  61. >>> t2
  62. 总共运行了15
  63. >>> t1+t2
  64. '总共运行了1分36秒'

利用perf_counter()和process_time()

  1. import time as t
  2. class MyTimer:
  3. def __init__(self):
  4. self.prompt = "未开始计时"
  5. self.lasted = 0.0
  6. self.begin = 0
  7. self.end = 0
  8. self.default_timer = t.perf_counter
  9. def __str__(self):
  10. return self.prompt
  11. __repr__ = __str__
  12. def __add__(self,other):
  13. result = self.lasted + other.lasted
  14. prompt = "总共运行了%0.2f秒" % result
  15. return prompt
  16. def start(self):
  17. self.begin = self.default_timer()
  18. self.prompt = "提示:请先调用stop()停止计时"
  19. print("计时开始!")
  20. def stop(self):
  21. if not self.begin:
  22. print("提示:请先调用start()开始计时")
  23. else:
  24. self.end = self.default_timer()
  25. self._calc()
  26. print("计时结束")
  27. def _calc(self):
  28. self.lasted = self.end - self.begin
  29. self.prompt = "总共运行了%0.2f秒" % self.lasted
  30. print(self.prompt)
  31. self.begin = 0
  32. self.end = 0
  33. def set_timer(self,timer):
  34. if timer == 'process_time':
  35. self.default_timer = t.process_time
  36. elif timer == 'perf_counter':
  37. self.default_timer = t.perf_counter
  38. else:
  39. print("输入无效")
  40. t1 = MyTimer()
  41. t1.set_timer('perf_counter')
  42. t1.start()
  43. t.sleep(5.2)
  44. t1.stop()
  45. t2 = MyTimer()
  46. t2.set_timer('perf_counter')
  47. t2.start()
  48. t.sleep(5.2)
  49. t2.stop()
  50. print(t1 + t2)
  51. >>>
  52. 计时开始!
  53. 总共运行了5.23
  54. 计时结束
  55. 计时开始!
  56. 总共运行了5.21
  57. 计时结束
  58. 总共运行了10.44
  59. >>>

4.属性访问

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

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

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

  1. class Rectangle:
  2. def __init__(self,width=0,height=0):
  3. self.width = width
  4. self.height = height
  5. def __setattr__(self,name,value):
  6. if name == 'square':
  7. self.width = value
  8. self.height = value
  9. else: #避免死循环的两种方式
  10. # super().__setattr__(name,value)
  11. self.__dict__[name] = value
  12. def getArea(self):
  13. return self.width * self.height
  14. >>> r1 = Rectangle(4,5)
  15. >>> r1.getArea()
  16. 20
  17. >>> r1.square = 10
  18. >>> r1.getArea()
  19. 100
  20. >>>

5. 描述符

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

__get__(self,instance,owner) 访问属性,返回属性的值
__set__(self,instance,value) 在属性分配中调用,不返回任何内容
__delete__(self,instance) 控制删除操作,不返回任何值
  1. >>> class Mydecript:
  2. def __get__(self,instance,owner):
  3. print("getting...",self,instance,owner)
  4. def __set__(self,instance,value):
  5. print("setting...",self,instance,value)
  6. def __delete__(self,instance):
  7. print("deleting...",self,instance)
  8. >>> class Test:
  9. x = Mydescript()
  10. Traceback (most recent call last):
  11. File "", line 1, in
  12. class Test:
  13. File "", line 2, in Test
  14. x = Mydescript()
  15. NameError: name 'Mydescript' is not defined
  16. >>> class Test:
  17. x = Mydecript()
  18. #Mydecript是x的描述类
  19. >>> test = Test()
  20. >>> test.x
  21. getting... <__main__.Mydecript object at 0x030EAFB0> <__main__.Test object at 0x03108050>
  22. >>> test.x = "X-man"
  23. setting... <__main__.Mydecript object at 0x030EAFB0> <__main__.Test object at 0x03108050> X-man
  24. >>> del test.x
  25. deleting... <__main__.Mydecript object at 0x030EAFB0> <__main__.Test object at 0x03108050>

例题:温度的转换

  1. class Celsius:
  2. def __init__(self,value = 26.0):
  3. self.value = float(value)
  4. def __get__(self,instance,owner):
  5. return self.value
  6. def __set__(self,instance,value):
  7. self.value = float(value)
  8. class Fahrenheit:
  9. def __get__(self,instance,owner):
  10. return instance.cel * 1.8 + 32
  11. def __set__(self,instance,value):
  12. instance.cel = (float(value) - 32) / 1.8
  13. class Temperature:
  14. cel = Celsius()
  15. fah = Fahrenheit()
  16. >>> temp = Temperature()
  17. >>> temp.cel
  18. 26.0
  19. >>> temp.cel = 30
  20. >>> temp.fah
  21. 86.0
  22. >>> temp.fah = 100
  23. >>> temp.cel
  24. 37.77777777777778
  25. >>>

6.定制序列

Python魔法方法详解

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

  1. class CountList:
  2. def __init__(self,*args):
  3. self.values = [x for x in args]
  4. self.count = { }.fromkeys(range(len(self.values)),0)
  5. def __len__(self):
  6. return len(self.values)
  7. def __getitem__(self,key):
  8. self.count[key] += 1
  9. return self.values[key]
  10. >>> c1 = CountList(1,3,5,7,9)
  11. >>> c1[1]
  12. 3
  13. >>> c2 = CountList(2,4,6,8,10)
  14. >>> c2[1]
  15. 4
  16. >>> c1[1]+c2[1]
  17. 7
  18. >>> c1.count
  19. {0: 0, 1: 2, 2: 0, 3: 0, 4: 0}
  20. >>> c2[1]
  21. 4
  22. >>> c2.count
  23. {0: 0, 1: 3, 2: 0, 3: 0, 4: 0}
  24. >>>

7.迭代器

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

  1. >>> string = "FishC"
  2. >>> it = iter(string)
  3. >>> next(it)
  4. 'F'
  5. >>> next(it)
  6. 'i'
  7. >>> next(it)
  8. 's'
  9. >>> next(it)
  10. 'h'
  11. >>> next(it)
  12. 'C'
  13. >>> next(it)
  14. Traceback (most recent call last):
  15. File "", line 1, in
  16. next(it)
  17. StopIteration
  18. >>> string = "FishC"
  19. >>> it = iter(string)
  20. >>> while True:
  21. try:
  22. each = next(it)
  23. except StopIteration:
  24. break
  25. print(each)
  26. F
  27. i
  28. s
  29. h
  30. C
  31. >>> for each in string:
  32. print(each)
  33. F
  34. i
  35. s
  36. h
  37. C
  38. >>>

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

  1. >>> class Fibs:
  2. def __init__(self,n=10):
  3. self.a = 0
  4. self.b = 1
  5. self.n = n
  6. def __iter__(self):
  7. return self
  8. def __next__(self):
  9. self.a,self.b = self.b,self.a + self.b
  10. if self.a > self.n:
  11. raise StopIteration
  12. return self.a
  13. >>> fibs = Fibs()
  14. >>> for each in fibs:
  15. print(each)
  16. 1
  17. 1
  18. 2
  19. 3
  20. 5
  21. 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. Debug模式的三种配置方法

    使用`app.config.from_object`的方式加载配置文件: 1. 导入`import config`.2. 使用`app.config.from_object(config)`. ### ...

  2. Raspberry Pi 4B 安装QT5和qtCreator

    https://blog.csdn.net/coekjin/article/details/52049273 sudo apt-get install qt5-default sudo apt-get ...

  3. malloc&&fread

    const char *wavePath = [_filePath UTF8String]; FILE *fh; int16_t * adbuf; fh = fopen(wavePath, " ...

  4. react踩坑

    1.列表渲染一定要注意key的唯一性,不然会导致页面只更新部分的bug graphVertexConfigList.data.map((item, index) => { return < ...

  5. ASE——第一次结对作业

    ASE--第一次结对作业 问题定义 很早就听说了MSRA的黄金点游戏,让大家写Bot来参加比赛看谁的AI比较聪明可以操盘割韭菜.深感ASE课程老师设计的任务太用心了,各种接口都准备好了,大家只用专注于 ...

  6. Yii2使用PHPExcel读取excel

    个人使用过程中保存一些使用PHPExcel的经验,以便后来翻阅:与PHP的Yii框架结合,可以轻松使用.而且根本不用网上所说的修改Yii的自动加载文件等方法.具体使用方法:下载phpoffice ht ...

  7. Java中的可变参数和asList方法

    可变参数: List.of

  8. loadrunner——win7+LR11配置

    一. 安装vmware虚拟机 下载安装vmware15后,可使用密钥为:CG392-4PX5J-H816Z-HYZNG-PQRG2 二. 安装win7系统 2.1下载win7镜像文件 2.2 vmwa ...

  9. Angular.js分页代码

                $scope.reloadList=function(){                             $scope.findPage( $scope.pagina ...

  10. 折半枚举——poj3977

    暴力搜索超时,但是折半后两部分状态支持合并的情况,可用折半枚举算法 poj3977 给一个序列a[],从里面找到k个数,使其和的绝对值最小 经典折半枚举法+二分解决,对于前一半数开一个map,map[ ...