__getitem__   在对实例或对象使用索引访问时调用,self[key]
__dir__     收集当前模块的信息,包括继承自其它基类(包括object类)的属性和方法
__new      定义如何创建实例
__init__      构造方法,实例创建时如何初始化
__del__      析构方法,对象在内存中被释放时,自动触发执行
__file__        当前文件在系统中的绝对路径
__hash__     hash值相同表示hash冲突,但并不代表对象值相同。列表不可hash,元组可hash。
          内建类型集合(set)的源码中就用到了"__hash__ = None",来表示set是不可hash类型。
          hash()等同于调用__hash__()方法
        isinstance(1,hashable) 是否可hash
__equal__    == 判断是否相等
      a == b 等价于
      a.__equal__(b)
__bool__      返回bool()布尔值,__bool__() --> __len__() 搜索顺序。
      如果没有__bool__(),则调用__len__()返回长度,非0就为真。
       如果__len__也没有定义,则所有实例都为真

可视化相关的魔术方法:
__repr__    重写表现形式,__str__ --> __repr__ --> object 查找顺序。至少有个__repr__
__str__      format(),print(),str()函数调用时使用的方法,如果没有__str__,则调用__repr__方法,所以这两个方法尽量写一样。
__bytes__      在对象使用bytes()函数时调用此方法
__ascii__

——————————————————————————————————————

运算符重载

容器
__len__     元素个数,必须大于等于0
        size有可能是容器的大小
__iter__     迭代容器时调用,返回一个新的迭代器对象
__contains__   in成员运算符 __contains__ --> __iter__顺序
__getitem__   返回self[key] 的值,不存在返回KeyError异常
__setitem__
__missing__   调用__getitem__时,key不存在时触发,以免抛异常

链式编程

深入学习综合症

__repr__ = __str__

——————————————————————————————————————————————

运算符重载,+= 举例:

class A:
def __init__(self,x):
self.x = x
def __repr__(self):
return str(self.x)
def __iadd__(self, other):
# return A(self.x + other.x) #生成新对象
self.x = self.x + other.x #就地修改
return self a1 = A(4)
a2 = A(10)
a3 = A(5)
print(id(a1),id(a2),id(a3))
a1 += a2
print(id(a1),a1)
~~~~~~
4362338144 4362338200 4362338256
4362338144 14 #对比可以看到前后的id(a1)内存地址一致,为就地修改

  上面例子是就地修改,下面这个例子是生成新对象,对比id(a1)内存地址。

class A:
def __init__(self,x):
self.x = x
def __repr__(self):
return str(self.x)
def __iadd__(self, other):
return A(self.x + other.x) #生成新对象
# self.x = self.x + other.x #就地修改
# return self a1 = A(4)
a2 = A(10)
a3 = A(5)
print(id(a1),id(a2),id(a3))
a1 += a2
print(id(a1),a1)
~~~~~~~~~~~~~~~~~~
4362338088 4362338144 4362338200
4362604616 14 #id(a1)值不等,生成的是新对象

  

练习:
设计二维坐标类Point,使其成为可hash类型,并比较2个坐标的实例是否相等。
class Point:
def __init__(self,x,y):
self.x = x
self.y = y
def __str__(self):
return '{},{}'.format(self.x,self.y)
def __eq__(self, other):
return (self.x == other.x) and (self.y == other.y)
def __iadd__(self, other):
return Point((self.x + other.x),(self.y + other.y)) p1 = Point(4,5)
p2 = Point(6,5) print(p1 == p2)
p1 += p2
print(p1)

  

练习:
购物车支持索引的方式检索商品:
class Color:
RED = 0
BLACK = 1
WHITE = 2
BLUE = 3 class Item:
def __init__(self,**kwargs):
self.spec = kwargs
def __repr__(self):
return str(sorted(self.spec.items()))
def __str__(self):
return str(sorted(self.spec.items()))
def __getitem__(self, item):
return self.spec.items()[item] class Cart:
def __init__(self):
self.items = []
def addItems(self,item):
self.items.append(item)
def getAllItems(self):
return self.items
def __add__(self, other): # +
pass
def __len__(self):
return len(self.getAllItems())
def __iter__(self):
return iter(self.items)
# for item in self.getAllItems():
# yield item
def __getitem__(self, index): #index
return self.items[index]
def __missing__(self, key): #只支持字典
print(key)
def __setitem__(self, key, value): #索引不可以超界
self.items[key] = value
return self.items mycart = Cart()
mycar = Item(mark='tesla',color=Color.WHITE,price='100w',speed='400km/h',year=2017)
myphone = Item(mark='Nokia',color=Color.BLACK,price=5000,memory='4G')
mymac = Item(mark='MacPro',color=Color.WHITE,price=19999,memory='16G',ssd='512G')
mycart.addItems(mycar)
mycart.addItems(myphone)
mycart.addItems(mymac)
for item in mycart.getAllItems():
# for item in mycart:
print(item.__dict__)
print(mycart.__len__())
print(mycart[2])

  

练习:斐波那契数列支持索引方式查找第n个数字。索引和调用两种方式:
class Fib:
"""0,1,1,2,3,5,8,13,21""" def __init__(self):
self.lst = [] def __call__(self, n, *args, **kwargs):
i = 0
prev, next = 0, 1
while True:
self.lst.append(prev)
if i == n:
return prev
prev, next = next, prev + next
i += 1 def __getitem__(self, item):
return self.__call__(item) f1 = Fib()
# print(f1(7))
# print(f1(8))
print(f1[8])

  

回顾下普通装饰器
import datetime
import time def timer(fn):
def wrapper(x, y):
start = datetime.datetime.now()
print('start:',start)
print(fn(x, y))
time.sleep(1)
stop = datetime.datetime.now()
# print('stop: ',stop)
return 'stop: {}'.format(stop) return wrapper @timer
def add(x, y):
return x + y num1 = add(3, 4)
print(num1)

  

上下文管理
类作为上下文,进入上下文时如果有定义__enter__方法,则做该方法的动作。
__enter__ 进去了帮我做某事,
__exit__ 离开时候帮忙
必须同时存在
import sys
sys.exit() 强制退出脚本
异常退出时处理
exc_type
exc_val
exc_tb traceback 类装饰器
两个装饰器同时装饰
with TimeIt() as f:
pass from functools import wrapås
@wraps(fn)
def self().... == wraps(fn)(self) 复制所有属性
类装饰是调用到__init__ 和__call__
--—————————————————————————————————————————————— ————————————————————————————————————————————————

  

用类做装饰器,调用的是__enter__和__exit__:
import datetime
import time class TimeIt:
def __init__(self, fn):
print('__init__...')
self.fn = fn def __enter__(self):
self.start = datetime.datetime.now()
print('Enter:', self.start)
return self def __call__(self, *args, **kwargs):
print('__call__....')
self.start = datetime.datetime.now()
print('Enter:', self.start)
print(self.fn(*args, **kwargs))
self.stop = datetime.datetime.now()
# print('Exit:', self.stop)
return 'Exit: {}'.format(self.stop) def __exit__(self, exc_type, exc_val, exc_tb):
self.stop = datetime.datetime.now()
print('Exit:', self.stop)
return self @TimeIt
def add(x, y):
time.sleep(1)
return x + y # with TimeIt(add) as foo:
# print(foo(3,4)) print(add(3, 4))

  

使用wraps的方式,拷贝所有属性:
import time
import datetime
from functools import wraps class TimeIt: def __init__(self, fn):
# self.__doc__ = fn.__doc__
print('init')
self._fn = fn
wraps(fn)(self)
#@wraps(fn) 等同于
#def self()...... def __enter__(self):
print('enter')
self.start = datetime.datetime.now()
return self def __call__(self, *args, **kwargs):
print('__call__')
start = datetime.datetime.now()
ret = self._fn(*args, **kwargs)
delta = (datetime.datetime.now() - start).total_seconds()
print("dec {} took {}".format(self._fn.__name__, delta))
return ret def __exit__(self, exc_type, exc_val, exc_tb):
print('exit')
delta = (datetime.datetime.now() - self.start).total_seconds()
print("context {} took {}".format(self._fn.__name__, delta))
return # def logger(fn):
# @wraps(fn)
# def wrapper(*args, **kwargs):
# start = datetime.datetime.now()
# ret = fn(*args, **kwargs)
# delta = (datetime.datetime.now() - start).total_seconds()
# print("dec {} took {}".format(fn.__name__, delta))
# return ret
# return wrapper @TimeIt
def add(x,y): # add = TimeIt(add)
"""This is a add function.~~~~~~~~~~~~~~~"""
time.sleep(2)
return x + y print(add(10,11)) print(add.__doc__)
print(add.__name__) print(add.__dict__)
# with TimeIt(add) as foo:
# print(foo(5, 16))

  

Python 面向对象(三) 魔术方法的更多相关文章

  1. Python - 面向对象编程 - 魔术方法(双下划线方法)

    什么是魔术方法 在Python中,所有以 __ 双下划线包起来的方法,都统称为 Magic Method 魔术方法,也叫双下划线方法 有哪些重要的魔术方法? __new__ https://www.c ...

  2. Python面向对象之魔术方法

    __str__ 改变对象的字符串显示.可以理解为使用print函数打印一个对象时,会自动调用对象的__str__方法 class Student: def __init__(self, name, a ...

  3. 十八、Python面向对象之魔术方法

    1.类的比较 class A(object): def __init__(self,value): self.value = value def __eq__(self,other): return ...

  4. Python 类的魔术方法

    Python中类的魔术方法 在Python中以两个下划线开头的方法,__init__.__str__.__doc__.__new__等,被称为"魔术方法"(Magic method ...

  5. Python面向对象三要素-继承(Inheritance)

    Python面向对象三要素-继承(Inheritance) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.继承概述 1>.基本概念 前面我们学习了Python的面向对象三 ...

  6. Python面向对象三要素-封装(Encapsulation)

    Python面向对象三要素-封装(Encapsulation) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.封装概述 将数据和操作组织到类中,即属性和方法 将数据隐藏起来,给 ...

  7. mac学习Python第一天:安装、软件说明、运行python的三种方法

    一.Python安装 从Python官网下载Python 3.x的安装程序,下载后双击运行并安装即可: Python有两个版本,一个是2.x版,一个是3.x版,这两个版本是不兼容的. MAC 系统一般 ...

  8. Python学习笔记之面向对象编程(三)Python类的魔术方法

    python类中有一些方法前后都有两个下划线,这类函数统称为魔术方法.这些方法有特殊的用途,有的不需要我们自己定义,有的则通过一些简单的定义可以实现比较神奇的功能 我主要把它们分为三个部分,下文也是分 ...

  9. Python中的魔术方法详解

    介绍 在Python中,所有以“__”双下划线包起来的方法,都统称为“Magic Method”,中文称『魔术方法』,例如类的初始化方法 __init__ ,Python中所有的魔术方法均在官方文档中 ...

随机推荐

  1. VS2015智能提示由英文改为中文

    使用 VS2015 时,在 4.0 下智能提示显示中文,在 4.5 下显示英文,对于我这种爱(ying)国(yu)人(tai)士(lan)来说,用起来太不方便了,于 是在 知乎 上找到个好方法如下: ...

  2. 彻底理解Java的Future模式

    先上一个场景:假如你突然想做饭,但是没有厨具,也没有食材.网上购买厨具比较方便,食材去超市买更放心. 实现分析:在快递员送厨具的期间,我们肯定不会闲着,可以去超市买食材.所以,在主线程里面另起一个子线 ...

  3. ArcGis for flex查询FeatureLayer数据

    1. 首先实例化一个FeatureLayer对象 private var featureLayer:FeatureLayer=new FeatureLayer(); 2.指定FeatureLayer对 ...

  4. VMware Tools安装方法及共享文件夹设置方法

    正确安装好VMware Tools后,可以实现主机与虚拟机之间的文件共享, 可以设置共享文件夹,以及在主机与虚拟机之间直接进行复制黏贴的操作. 安装方法: 选择"虚拟机"-> ...

  5. C陷阱和缺陷学习笔记

    这段时间把<C陷阱和缺陷>看了,没时间自己写总结.就转一下别人的学习笔记吧http://bbs.chinaunix.net/thread-749888-1-1.html Chapter 1 ...

  6. HTTPS和HTTP有什么区别?如何将HTTP转化成HTTPS

    不知道大家有没有注意到输入网址时的HTTP部分,在打开网站进行操作时有时候会自动跳转为HTTPS格式,这是为什么?HTTP与HTTPS到底有什么区别?如何将HTTP转化成HTTPS,针对这些问题,我们 ...

  7. python函数前篇

    函数:函数是指将一组语句的集合通过一个函数名封装起来,要想执行这个函数,只需调用其函数名即可 函数特性: 减少重复代码 使程序变得可扩展 使程序变得易维护 什么是函数? 函数就是具备某一特定功能的工具 ...

  8. Model Representation and Cost Function

    Model Representation To establish notation for future use, we’ll use x(i) to denote the “input” vari ...

  9. Visual Studio 调试技巧[Command Window & Immediate Window ](Tips)

    Visual Studio 调试技巧[Command Window & Immediate Window ](Tips) 1. immediate window 定义的一些 alias (// ...

  10. A计划(双层bfs)

    A计划 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submissio ...