python 学习汇总50:对象重载魔法 2实例(进阶学习- tcy)

2024-03-20 09:58

本文主要是介绍python 学习汇总50:对象重载魔法 2实例(进阶学习- tcy),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

对象重载 2018/11/18
目录简明魔法目录汇总参考 本人博文对象重载魔法 11.__str__,__repr__,__abs__ ,__len__, __reversed__重载2.运算符重载二元运算符重载方法格式: 2.1.算术运算重载2.2.反向算术运算重载2.3.复合赋值算术运算重载4.迭代器(高级):4.1.迭代器重载4.2.可迭代对象重载1.__iter__迭代对象2.支持索引切片5.上下文管理器重载6.__call__重载7.索引和切片运算符的重载[ ]:实例1__repr__,__neg__,__contains__,__getitem__ ,__setitem__ ,__delitem__重载IN 对象检测索引切片    实例2 class 实现list 功能:__len__,__getitem__,__setitem__,__delitem__,__iter__,__reversed__重载8.特性属性重载:__getattr__(self, attr)@property实例8.1.__getattr__动态返回一个属性:利用完全动态__getattr__写出一个链式调用:实例8.2.此示例示意特性属性的用法实例8.3.此示例示意特性属性的用法'9.其他魔法 
https://blog.csdn.net/qq_27297393/article/details/80685474  人工智能
1.__str__,__repr__,__abs__ ,__len__, __reversed__,__round__重载:
class MyClass:
def __init__(self, data):
self.data = data
def data_type(self,data):# 转换python基本数据类型
return isinstance(self.data, (str, int, float, complex, bool, tuple, dict, list, set, frozenset))'''1.对象转字符串函数 '''
def __str__(self): # str(obj)返回一个字符串
if self.data_type(self.data):
return "%s" % self.data
else:
return None
# __repr__ = __str__ #简单写法省略下面定义def __repr__(self): # repr(x)返回对象的表达式字符串
return '%s' % self.data''' 2.内建函数重载'''
def __abs__(self):# __abs__ abs(obj)
if isinstance(self.data, (int,float)):
if self.data < 0:
t = -self.data
else:
t=self.data
else:
t=None
return tdef __len__(self):# __len__ len(obj)
'''len(obj) 不能直接用于数字,在这里可以返回1'''
if self.data_type(self.data):
if isinstance(self.data, numbers.Number):
t=1
else:
t=len(self.data)
else:
t=None
return t'''3.数值转换函数重载'''
# __complex__ complex(obj)
# __int__ int(obj)
# __float__ float(obj)
# __bool__ bool(obj)
def __bool__(self):
lst=[0,0.0,'',"",None,(),[],{}]
return self.data not in lst# 测试程序c1= MyClass(1) # 对象转字符串函数
print(c1,str(MyClass(10.1)),repr(MyClass(1+2j))) # 3种方法等效 # 1 10.1 (1+2j)# 内建函数重载
print(abs(MyClass(1.2)),abs(MyClass(-1.2)),abs(MyClass(1+2j)),abs(MyClass('f')))# 1.2 1.2 None None# 数值转换函数重载
print(bool(MyClass(None)),bool(MyClass(-1.2)),bool(MyClass([])),bool(MyClass('f')))# False True False True 
2.运算符重载
二元运算符重载方法格式: def __xxx__(self, other): 
2.1.算术运算重载
方法名 运算符和表达式 说明
__add__(self, rhs) self + rhs  加法
__sub__(self, rhs) self - rhs  减法
__mul__(self, rhs) self * rhs  乘法
__truediv__(self, rhs) self / rhs  除法
__floordiv__(self, rhs) self // rhs  地板法
__mod__(self, rhs) self % rhs 求余(取模)
__pow__(self, rhs) self ** rhs  冪运算注:rhs (right hands side)  右手边2.2.反向算术运算重载
当运算符的左侧为内建类型时,右侧为自定义类型进行算术运算时,会出现TypeError错误,
因无法修改内建类型的代码来实现运算符重载,此时需要使用反向算术运算符重载来完成重载方法名 运算符和表达式 说明
__radd__(self, lhs) lhs + self  加法
__rsub__(self, lhs) lhs - self  减法
__rmul__(self, lhs) lhs * self  乘法
__rtruediv__(self, lhs) lhs / self  除法
__rfloordiv__(self, lhs) lhs // self  地板法
__rmod__(self, lhs) lhs % self 求余(取模)
__rpow__(self, lhs) lhs ** self  冪运算复合赋值算术运算重载方法名 运算符和表达式 说明
__iadd__(self, rhs) self += rhs  加法
__isub__(self, rhs) self -= rhs  减法
__imul__(self, rhs) self *= rhs  乘法
__itruediv__(self, rhs) self /= rhs  除法
__ifloordiv__(self, rhs) self //= rhs  地板法
__imod__(self, rhs) self %= rhs 求余(取模)
__ipow__(self, rhs) self **= rhs < /FONT> 冪运算说明
a、如__add__和__iadd__方法不同运算结果不同,x += x 和 x = x + x 是不等价
b、如果__add__和__iadd__同时存在,复合运行优先采用__iadd__方法
c、如果__iadd__不存在,复合运行采用__add__方法
d、如果__add__和__iadd__均存在,运行报错

 实例1: 

class MyNumber:
def __init__(self, data):
self.data = datadef __repr__(self):
return "%f" % self.data #应当根据数据类型判断输出,此处省略#1.算术运算重载 推荐写法
def __add__(self, other):
return self.data + otherdef __sub__(self, rhs): # return MyNumber(self.data - rhs.data) 算术运算重载 不推荐,采用上面格式
return self.data - rhs #必须为rhs,不能为rhs.data#2.反向算术运算重载
def __radd__(self, other):
return self.data + other #2.算术运算重载 推荐写法
def __rsub__(self, lhs): #二个减法反着写,这样能够实现数字和类的任意减法
return lhs-self.data#3.复合赋值算术运算符重载
def __iadd__(self, other):
return self.data+othern1 = MyNumber(100)
n2 = MyNumber(200)
n3 = n1 + n2 # 等同于n1.__add__(n2)print("n1=", n1, 'n2=', n2,type(n1)) # n1= 100.000000 n2= 200.000000 <class '__main__.MyNumber'>
print('n1+n2 =',n1+n2,'n1-n2=', n1-n2,type(n1+n2),type(n1-n2)) # n1+n2 = 300 n1-n2= -100 <class 'int'> <class 'int'>
print('n1-n2 =',1000-n2,type(n1-n2),1000-n1,n1-1000,type(1000-n1))# n1-n2 = 800 <class 'int'> 900 -900 <class 'int'>n3 = MyNumber(300)
n4 = MyNumber(400)
n5 = MyNumber(500)
n3+=n4
n5+=1000
print('+n3 =',n3,type(n3),'+n4 =',n4,type(n4),n5,type(n5))
# +n3 = 700 <class 'int'> +n4 = 400.000000 <class '__main__.MyNumber'> 1500 <class 'int'>

 实例2: 

class i_complex(object):
def __init__(self,real,imag=0):
self.real=float(real)
self.imag=float(imag)
def __repr__(self):
return 'complex(%s,%s)' % (self.real,self.imag)
def __str__(self):
return '(%g +%j)' % (self.real,self.imag)
#self+other
def __add__(self,other):
return complex(self.real+other.real,self.imag+other.imag)
#self-other
def __sub__(self,other):
return complex(self.real-other.real,self.imag-other.imag)#逆向操作reversed operand
def __radd__(self,other):
return complex(other.real+self.real,other.imag+self.imag)
def __rsub__(self,other):
return complex(other.real-self.real,other.imag-self.imag)#测试:a1=i_complex(1,-11)
a2=i_complex(2,-22)
a3=i_complex(3,-33)
a4=i_complex(4,-44)print(a1+a2,a1+2+3j,2+3j+a1)#(3-33j) (3-8j) (3-8j) 
4.迭代器(高级):
4.1.迭代器:可以通过next函数取值的对象就是迭代器
迭代器协议:对象用next取下一数据,无数据触发StopIteration异常来终止迭代的约定
迭代器的实现:通过__next__(self) 方法用来实现迭代器协议
重载方法
class MyIterator:
def __next__(self):
迭代器协议
return 数据
4.2.可迭代对象
是指能用iter(obj) 函数返回迭代器对象;可迭代对象内部要定义__iter__(self) 方法来返回迭代器对象
重写方法
class MyIterable:
def __iter__(self):
语句块
return 迭代器

 实例1:

class Iterable(object):
def __init__(self, data):
self.data = datadef __iter__(self):
return Iterator(self.data)class Iterator(object):
def __init__(self, data):
self.data = data
self.index =0# len(data)def __next__(self):
if self.index >= len(self.data) :
raise StopIteration
i=self.index
self.index += 1
return self.data[i]it = Iterable('abcde')for i in it:
print(i) # a b c d e
for i in it:
print(i) # a b c d e
实例2:  
'''1.__iter__返回一个迭代对象'''
class Fib(object):
def __init__(self,n=1000):
self.a, self.b = 0, 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 # 返回下一个值'''2.支持索引切片'''
def __getitem__(self, n): # 把对象视作list或dict 没有对负数作处理
if isinstance(n, int): # n是索引
a, b = 1, 1
for x in range(n):
a, b = b, a + b
return a
if isinstance(n, slice): # n是切片
start = n.start; stop = n.stop;
a, b = 1, 1; lst = [];
for x in range(stop):
if x >= start:
lst.append(a)
a, b = b, a + b
return lst''' 
3.测试:for循环:'''a=Fib(100)
for i1 in a:
print(i1,end=';')
print('\n')
for i2 in range(11):
print(a[i2],end=';')
print('\n')
print(a[0:11])''' 
4.输出:
1;1;2;3;5;8;13;21;34;55;89;
1;1;2;3;5;8;13;21;34;55;89;
[1,1,2, 3, 5, 8, 13, 21, 34, 55, 89]
'' 
5.上下文管理器:
class ContextManager(object):
def __init__(self, flag):
print('ContextManager.__init__(%s)' % flag)
self.flag = flagdef __enter__(self):
print('ContextManager.__enter__()')
return selfdef __exit__(self, exc_type, exc_val, exc_tb):
print( 'ContextManager.__exit__(%s, %s, %s)' % (exc_type, exc_val, exc_tb))
if exc_type is None:
print("退出with时没有发生异常")
else:
print("退出with时,有异常,类型是", exc_type, "错误是", exc_val)
print("__exit__法被调用,已离开with语句")
# return self.flag
try:
with ContextManager(True) as a:
raise RuntimeError('error message handled')with ContextManager(False):
raise RuntimeError('error message propagated')
except:
print("有错误发生,已转为正常")
finally:
print("这是with语句之外,也是程序的最后一条语句")输出:
# ContextManager.__init__(True)
# ContextManager.__enter__()
# ContextManager.__exit__(<class 'RuntimeError'>, error message handled, <traceback object at 0x0000000002244FC8>)
# 退出with时,有异常,类型是 <class 'RuntimeError'> 错误是 error message handled
# __exit__法被调用,已离开with语句
# 有错误发生,已转为正常
# 这是with语句之外,也是程序的最后一条语句
6.__call__任何类定义__call__()方法,就可直接对实例进行调用: 
1) 对象实例有自己属性方法,调用实例方法时用instance.method()来调用
2) 直接在实例本身上调用
3) 判断变量是对象还是函数:callable(Student('Tom'))class Student(object):
def __init__(self, name='空 '):
self.name = name
def __call__(self,id=0):# 定义参数
print('My name is %s.id=%s' % (self.name,id))
return self.name,id#测试程序:
对实例直接调用好比对函数调用,可把对象看成函数把函数看成对象
s = Student('Bob')
s(80)# My name is Bob.id=80print(
callable(Student('Tom')),# 判断变量是对象还是函数:# True
callable(s(160)), #My name is Bob.id=160 # False
callable(s), # True
type(s(320)), #My name is Bob.id=320 # <class 'tuple'>
s(480)) #My name is Bob.id=480 # ('Tom', 100)

 7.索引和切片运算符的重载[ ]: 

重载方法 运算符和表达式 说明
__getitem__(self, i) x = self[i] 索引/切片取值
__setitem__(self,i,val) self.[i]=val 索引/切片赋值
__delitem__(self, i) del self[i] del语句索引/切片实例1:__repr__,__neg__,__contains__,__getitem__ ,__setitem__ ,__delitem__重载class MyList():#可以继承list
def __init__(self, iterable=()):
self.data = [x for x in iterable]def __repr__(self):
return 'MyList(%r)' % self.datadef __neg__(self):#取负值
'''规则是正变负,负变正'''
L = (-x for x in self.data)
return MyList(L)'''IN 对象检测'''
def __contains__(self, v):# in
return v in self.data'''索引切片'''
def __getitem__(self, i):#创建一个slice切片对象
# if isinstance(i, int): # i 是索引
if isinstance(i, slice): # i 是切片
start = i.start
stop = i.stop
if start is None:
start = 0
return self.data[i]def __setitem__(self, i, val):#把对象视作list或dict来对集合赋值
self.data[i] = valdef __delitem__(self, i):
del self.data[i]L1 = MyList([1, -2, 3, -4, 5])
L2 = -L1 # 等同于L1.__neg__()
print(L2,type(L2)) # MyList([-1, 2, -3, 4, -5]) <class '__main__.MyList'>
print(3 in L1,2 not in L1) #True Truex = L1[0] # L1.__getitem__(0) =1
s=slice(0,2)
print('L1[0]=',x,L1[s]) #L1[0]= 1 [1, -2]L1[1] = 2 # L1.__setitem__(1, 2)
print('1==>',L1) #1==> MyList([1, 2, 3, -4, 5])
print('2==>',L1[0:3:1]) # 切片读取列表[1, 2, 3]
del L1[1]
print('3==>',L1) #3==> MyList([1, 3, -4, 5])
L1[::] = [] # 删除 列表中值
print('4==>',L1) #4==> MyList([])

 实例2 class 实现list 功能:

 __len__,__getitem__,__setitem__,__delitem__,__iter__,__reversed__重载 

class FunctionalList:
''' 实现了内置类型list的功能,并丰富了一些其他方法: head, tail, init, last, drop, take'''
def __init__(self, values=None):
if values is None:
self.values = []
else:
self.values = values
def __len__(self):
return len(self.values)
def __getitem__(self, key):
return self.values[key]
def __setitem__(self, key, value):
self.values[key] = value
def __delitem__(self, key):
del self.values[key]
def __iter__(self):
return iter(self.values)
def __reversed__(self):
return FunctionalList(reversed(self.values))
def append(self, value):
self.values.append(value)
def head(self):
# 获取第一个元素
return self.values[0]
def tail(self):
# 获取第一个元素之后的所有元素
return self.values[1:]
def init(self):
# 获取最后一个元素之前的所有元素
return self.values[:-1]
def last(self):
# 获取最后一个元素
return self.values[-1]
def drop(self, n):
# 获取所有元素,除了前N个
return self.values[n:]
def take(self, n):
# 获取前N个元素
return self.values[:n]#测试
a=FunctionalList([0,1,2,3,4,5,6])
a[6]=-6
print(a[6],a.drop(5),len(a),a.values,list(a),list(reversed(a)))#reversed反转迭代器
# -6 [5, -6] 7 [0, 1, 2, 3, 4, 5, -6] [0, 1, 2, 3, 4, 5, -6] [-6, 5, 4, 3, 2, 1, 0]
del a[0]
print(a.values)# [1, 2, 3, 4, 5, -6]
a.append(7)
print(a.values)# [1, 2, 3, 4, 5, -6, 7]
8.特性属性: 
分类:
__getattr__(self, attr)
@property
作用
a、用来模拟一个属性
b、实现其它语言所拥有的 getter 和 setter功能(实现魔法函数)
c、通过@property装饰器可以对模拟的属性赋值和取值加以控制
实例8.1.__getattr__动态返回一个属性:
class Student(object):#类的所有属性和方法调用全部动态化处理
def __init__(self):
self.name = 'Tom'
def __getattr__(self, attr):
if attr=='score': #动态返回一个属性
return 99
if attr=='age': #返回函数:
return lambda: 25s = Student()
a1=s.name #'Tom'
a2=s.score #99
a3=s.age() #25
print(a1,a2,a3)#利用完全动态__getattr__写出一个链式调用:
class Chain(object):
def __init__(self, path=''):
self._path = path
def __getattr__(self, path):
print('==> path=',path,';self._path=',self._path)
return Chain('%s/%s' % (self._path, path))
def __str__(self):
return self._path
__repr__ = __str__a=Chain().status.user.timeline.list #'/status/user/timeline/list'
print(a)# 输出:
# ==> path= status ;self._path= 
# ==> path= user ;self._path= /status
# ==> path= timeline ;self._path= /status/user
# ==> path= list ;self._path= /status/user/timeline
# /status/user/timeline/list# 实例8.2.此示例示意特性属性的用法
class Student:
def __init__(self, score):
self.__score = scoredef get_score(self):
'''实现getter'''
return self.__scoredef set_score(self, s):
'''实现setter'''
print("正在调用setter")
if 0 <= s <= 100:
self.__score = s
else:
raise ValueErrorscore = property(get_score, set_score)s = Student(59)
print(s.score) # print(s.get_score())=59
s.score = 97 # 正在调用setter:s.set_score(97)=97
print(s.score) # 97 
# 实例8.3.此示例示意特性属性的用法'class Student:
def __init__(self, score):
self.__score = score@property
def score(self): # score = propery(score)
'''实现getter'''
return self.__score@score.setter
def score(self, s):
'''实现setter'''
print("正在调用setter")
if 0 <= s <= 100:
self.__score = s
else:
raise ValueErrors = Student(88)
print(s.score) # print(s.get_score())=88
s.score = 50 #正在调用setter:s.set_score(50)
print(s.score) #50

 9.其他魔法: 

1、比较运算符的重载
方法名 运算符和表达式 说明 
__lt__(self, rhs) self < rhs 小于
__le__(self, rhs) self <= rhs 小于等于
__gt__(self, rhs) self > rhs 大于
__ge__(self, rhs) self >= rhs 大于等于
__eq__(self, rhs) self == rhs 等于
__ne__(self, rhs) self != rhs 不等于
注: 比较运算符通常返回布尔值True 或False2、位运算符的重载
方法名 运算符和表达式 说明 
__invert__(self, rhs) ~self 取反(一元运算符)
__and__(self, rhs) self & rhs 位与
__or__(self, rhs) self | rhs 位或
__xor__(self, rhs) self ^ rhs 位异或
__lshift__(self, rhs) self << rhs 左移
__rshift__(self, rhs) self >> rhs 右移反向位运算符的重载方法名 运算符和表达式 说明
__rand__(self, lhs) lhs & self 位与
__ror__(self, lhs) lhs | self 位或
__rxor__(self, lhs) lhs ^ self 位异或
__rlshift__(self, lhs) lhs << self 左移
__rrshift__(self, lhs) lhs >> self 右移复合赋值位运算符的重载方法名 运算符和表达式 说明
__iand__(self, rhs) self &= rhs 位与
__ior__(self, rhs) self |= rhs 位或
__ixor__(self, rhs) self ^= rhs 位异或
__ilshift__(self, rhs) self <<= rhs 左移
__irshift__(self, rhs) self >>= rhs 右移3、一元运算符的重载
方法名 运算符和表达式 说明
__neg__(self) - self 负号
__pos__(self) + self 正号
__invert__(self) ~ self 取反重载方法:def __xxx__(self):

 

这篇关于python 学习汇总50:对象重载魔法 2实例(进阶学习- tcy)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/829097

相关文章

使用Python绘制蛇年春节祝福艺术图

《使用Python绘制蛇年春节祝福艺术图》:本文主要介绍如何使用Python的Matplotlib库绘制一幅富有创意的“蛇年有福”艺术图,这幅图结合了数字,蛇形,花朵等装饰,需要的可以参考下... 目录1. 绘图的基本概念2. 准备工作3. 实现代码解析3.1 设置绘图画布3.2 绘制数字“2025”3.3

python使用watchdog实现文件资源监控

《python使用watchdog实现文件资源监控》watchdog支持跨平台文件资源监控,可以检测指定文件夹下文件及文件夹变动,下面我们来看看Python如何使用watchdog实现文件资源监控吧... python文件监控库watchdogs简介随着Python在各种应用领域中的广泛使用,其生态环境也

Python中构建终端应用界面利器Blessed模块的使用

《Python中构建终端应用界面利器Blessed模块的使用》Blessed库作为一个轻量级且功能强大的解决方案,开始在开发者中赢得口碑,今天,我们就一起来探索一下它是如何让终端UI开发变得轻松而高... 目录一、安装与配置:简单、快速、无障碍二、基本功能:从彩色文本到动态交互1. 显示基本内容2. 创建链

Java调用Python代码的几种方法小结

《Java调用Python代码的几种方法小结》Python语言有丰富的系统管理、数据处理、统计类软件包,因此从java应用中调用Python代码的需求很常见、实用,本文介绍几种方法从java调用Pyt... 目录引言Java core使用ProcessBuilder使用Java脚本引擎总结引言python

python 字典d[k]中key不存在的解决方案

《python字典d[k]中key不存在的解决方案》本文主要介绍了在Python中处理字典键不存在时获取默认值的两种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录defaultdict:处理找不到的键的一个选择特殊方法__missing__有时候为了方便起见,

使用Python绘制可爱的招财猫

《使用Python绘制可爱的招财猫》招财猫,也被称为“幸运猫”,是一种象征财富和好运的吉祥物,经常出现在亚洲文化的商店、餐厅和家庭中,今天,我将带你用Python和matplotlib库从零开始绘制一... 目录1. 为什么选择用 python 绘制?2. 绘图的基本概念3. 实现代码解析3.1 设置绘图画

Python pyinstaller实现图形化打包工具

《Pythonpyinstaller实现图形化打包工具》:本文主要介绍一个使用PythonPYQT5制作的关于pyinstaller打包工具,代替传统的cmd黑窗口模式打包页面,实现更快捷方便的... 目录1.简介2.运行效果3.相关源码1.简介一个使用python PYQT5制作的关于pyinstall

使用Python实现大文件切片上传及断点续传的方法

《使用Python实现大文件切片上传及断点续传的方法》本文介绍了使用Python实现大文件切片上传及断点续传的方法,包括功能模块划分(获取上传文件接口状态、临时文件夹状态信息、切片上传、切片合并)、整... 目录概要整体架构流程技术细节获取上传文件状态接口获取临时文件夹状态信息接口切片上传功能文件合并功能小

python实现自动登录12306自动抢票功能

《python实现自动登录12306自动抢票功能》随着互联网技术的发展,越来越多的人选择通过网络平台购票,特别是在中国,12306作为官方火车票预订平台,承担了巨大的访问量,对于热门线路或者节假日出行... 目录一、遇到的问题?二、改进三、进阶–展望总结一、遇到的问题?1.url-正确的表头:就是首先ur

Oracle Expdp按条件导出指定表数据的方法实例

《OracleExpdp按条件导出指定表数据的方法实例》:本文主要介绍Oracle的expdp数据泵方式导出特定机构和时间范围的数据,并通过parfile文件进行条件限制和配置,文中通过代码介绍... 目录1.场景描述 2.方案分析3.实验验证 3.1 parfile文件3.2 expdp命令导出4.总结