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

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss