运算重载的限制
算数运算符的重载
算数运算符的重载:一元算数运算符
保留方法 | 对应操作 | 描述 |
---|---|---|
.neg(self) | -obj | 定义对象取负的运算逻辑 |
.pos(self) | +obj | 定义对象取正的运算逻辑 |
.abs(self) | abs(obj) | 定义对象绝对值的运算逻辑 |
.invert(self) | ~obj | 定义对象取反的运算逻辑 |
算数运算符的重载:二元算数运算符
保留方法 | 对应操作 | 描述 |
---|---|---|
.add(self,other) | Obj+other | 定义两个对象加法的运算逻辑 |
.sub(self,other) | Obj-other | 定义两个对象减法的运算逻辑 |
.mul(self,other) | Obj*other | 定义两个对象乘法的运算逻辑 |
.truediv(self,other) | Obj/other | 定义两个对象除法的运算逻辑 |
.floordiv(self,other) | Obj//other | 定义两个对象整数除的运算逻辑 |
.mod(self,other) | Obj%other | 定义两个对象模的运算逻辑 |
.divmod(self,other) | Divmod(obj,other) | 定义两个对象除模的运算逻辑 |
.pow(self,other) | Obj**other | 定义对象幂的运算逻辑 |
.lshift(self,other) | Obj<定义对象左移的运算逻辑 |
|
.rshift(self,other) | Obj>>other | 定义对象右移的运算逻辑 |
.and(self,other) | Obj&other | 定义两个对象位与的运算逻辑 |
.xor(self,other) | Obj^other | 定义两个对象位异或的运算逻辑 |
.or(self,other) | Objother | 定义两个对象位或的运算逻辑 |
例:
class newlist(list): #继承list类型的新类型,重载加法。
def __add__(self,other):
result=[]
for i in range(len(self)):
try:
result.append(self[i]+other[i])
except:
result.append(self[i])
return result
ls=newlist([1,2,3,4,5,6])
lt=newlist([1,2,3,4])
print(ls+lt)
#输出结果为:
#2,4,6,8,5,6
比较运算的重载
保留方法 | 对应操作 | 描述 |
---|---|---|
.lt(self,other) | obj两个对象比较操作的运算重载 |
|
.le(self,other) | obj<=other | 两个对象比较操作的运算重载 |
.eq(self,other) | obj==other | 两个对象比较操作的运算重载 |
.ne(self,other) | obj!=other | 两个对象比较操作的运算重载 |
gt(self,other) | obj>other | 两个对象比较操作的运算重载 |
.ge(self,other) | obj>=other | 两个对象比较操作的运算重载 |
#例子:
class newlist(list):
def __lt__(self,other):
s,t=0,0
for c in self:
s+=c
for c in other:
t+=c
return True if s<t else False
ls=newlist([1,2,3,4])
lt=newlist([1,3,4,5])
print([1,2,3,4]<[1,3,4,5])
print(ls<lt)
#输出结果为:
#False
#True
成员运算的重载
成员运算的种类
保留方法 | 对应操作 | 描述 |
---|---|---|
.getitem(self,key) | Obj[k] | 定义获取对象中序号k元素的运算逻辑,k为整数 |
.setitem(self,key,v) | Obj[k]=v | 定义赋值对象中序号k元素的运算逻辑 |
.delitem(self,key) | Del obj[k] | 定义删除对象中序号k元素的运算逻辑 |
.reversed(self) | Obj.reversed() | 定义对象逆序的运算逻辑 |
.contains(self,item) | Item in obj | 定义in操作符对应的运算逻辑 |
例子:
class newlist(list):
def __contains__(self,item):
s=0
for c in self:
s+=c
if super().__contains__(item) or item==s
return True
else:
return False
ls=newlist([6,1,2,3])
print(6 in ls,12 in ls)
#输出结果为:
#True True
其他运算的重载
Python内置函数
保留方法 | 对应操作 | 描述 |
---|---|---|
.repr(self) | repr(obj) | 定义对象可打印字符串的运算逻辑。 |
.str(self) | str(obj) | 定义对象字符串转换操作的运算逻辑 |
.len(self) | len(obj) | 定义对象长度操作的运算逻辑 |
.int(self) | int(obj) | 定义对象整数转换的运算逻辑 |
.float(self) | float(obj) | 定义对象浮点数转换的运算逻辑 |
.complex(self) | complex(obj) | 定义对象复数转换的运算逻辑 |
.round(self) | round(obj) | 定义对象四舍五入的运算逻辑 |
.bytes(self) | bytes(obj) | 定义对象字节串转换的运算逻辑 |
.bool(self) | bool(obj) | 定义对象布尔运算的运算逻辑 |
.format(self,format_spec) | obj.format()\format(obj) | 定义对象格式化输出的运算逻辑 |
#例子:
class newlist(list):
def __format__(self,format_spec):
t=[]
for c in self:
if type(c)==type(“字符串”):
t.append(c)
else:
t.append(str(c))
return “,”.join(t)
ls=newlist([1,2,3,4])
print(format[1,2,3,4])
print(format(ls))
#输出结果为:
#[1,2,3,4]
#1,2,3,4
多态的理解
dc1=DemoClass("老王")
dc2=DemoClass("老李")
dc1.lucky()
dc1.lucky(10)
dc1.lucky("10")
dc1.lucky(dc2)
dc1.lucky(10,100)
对于同一个类的方法
多态Polymorphism:仅针对方法,方法灵活性的抽象
天然支持:Python方法无类型声明限制
#例子:
class democlass:
def __init__(self.name):
self.name=name
def __id__(self): #重载id函数对应逻辑
return len(self.name)
def luck(self,salt): #需要方法能够处理不同参数,不对输入做约束
s=0 #输入类型读使用文档就好,要深入理解文档约束
#而非语法约束
for c in self.name
s+=(ord(c)+id(salt))%100
return s
dc1=democlass(“老王”)
dc2=democlass(“老李”)
print(dc1.lucky(10))
print(dc1.lucky(“10”))
print(dc1.lucky(dc2))
天然支持:python方法/函数支持多种参数形式
class DemoClass:
def __init__(self,name):
self.name=name
def __id__(self):
return len(self.name)
def lucky(self,salt=0,more=9)
s=0
for c in self.name:
s+=(ord(c)+id(salt)+more)%100
return s
dc1=DemoClass("老王")
print(dc1.lucky())
print(dc1.lucky(10))
print(dc1.lucky(10,100))
引用Reference:对象的指针
ls=[1,2,3,4,5]
lt=ls
print(id(ls))
print(id(lt))
#输出结果为
#93463456
#93463456
python内部机制对引用的处理
不可变对象的引用:整数\字符串
a=10
b=a
c=10
print(id(a))
print(id(b))
print(id(c))
#输出结果为:
#1376965824
#1376965824
#1376965824
# 赋值仅实现了增加引用的功能。
#- python解释器内部对a和c维护1个对象。
a="python计算生态"
b=a
c="python"
d="计算生态"
e=c+d
f="python计算生态"
print(id(a))
print(id(b))
print(id(c))
print(id(d))
print(id(e))
print(id(f))
#输出结果a\b\f指向同一内存地址。
#但是e作为运算后产生的对象,由解释器重新建立。
可变对象的引用:列表
la=[]
lb=la
lc=[]
print(id(la))
print(id(lb))
print(id(lc))
#81732512
#81732512
#81021088
#赋值新增了一个对象的引用
#每个可变对象都由解释器重新创建,不复用内存
la=[]
lb=la
lb.append(1)
print(la,id(la))
print(lb,id(lb))
#对象修改后,所有引用的值都被修改。
导致引用+1的情况
导致引用 - 1的情况
引用reference:对象的指针
浅拷贝和深拷贝
ls=["python",[1,2,3]]
la=ls.copy()
lb=[:]
lc=list(ls)
print("ls",id(ls),ls)
print("la",id(la),la)
print("lb",id(lb),lb)
print("lc",id(lc),lc)
#此时la,lb,lc,ls不是赋值指向同一地址,而是生成了不用的内存地址id均不相同。
ls=["python",[1,2,3]]
la=ls.copy()
lb=[:]
lc=list(ls)
for i in [ls,la,lb,lc]:
for c in i:
print(c,id(c)," ",end=" ")
print(" ",i,id(i))
#打印输出后你会发现列表被拷贝了,但是元素没有被拷贝。
#列表本身只是一个容器,他实际表达每个元素对象的指针。
ls=["python",[1,2,3]]
la=ls.copy()
lb=[:]
lc=list(ls)
lc[-1].append(4)
print(lc,la)
print(ls,lb)
#在lc最后一个列表改变后,所有la,lb,lc都发生了变换。
#这就是浅拷贝的问题。
深拷贝:完全拷贝对象内容
import copy
ls=["python",[1,2,3]]
lt=copy.deepcopy(ls)
for i in [ls,lt]:
for c in i:
print(c,id(c)," ",end=" ")
print(" ",i,id(i))
#列表内部各可变对象元素都被拷贝
类的方法引用
再看类的实例方法
class DemoClass:
def __init__(self,name):
self.name=name
def lucky(self,salt=0):
s=0
for c in self.name:
s+=(ord(c)+id(salt))%100
return s
dc1=DemoClass("老李")
lucky=dc1.lucky
print(DemoClass.lucky(dc1,10))#注释1
print(dc1.lucky(10))#注释1
print(lucky(10)) #与<对象名>.<方法>是一个对方法的引用
'''
注释1
<对象名>.<方法>(方法参数)
等价于
<类名>.<方法名>(<对象名>,方法参数)
'''
命名空间的理解
命名空间:从名字到对象的一种映射
count=0 #模块的命名空间
def getCounting(a): #第一层函数的命名空间
count=0
if a!="":
def doCounting(): #第二层函数的命名空间
nonlocal count
count+=1
doCounting()
return count
print(getCounting("1"),count)
print(getCounting("2"),count)
print(getCounting("3"),count)
#1 0
#1 0
#1 0
'''
nonlocal声明变量不在当前命名空间,变量在上层命名空间,但不是全局。
global声明变量在全局命名空间。
'''
类的特性装饰器
@property:类的特性装饰器
class DemoClass:
def __init__(self,name):
self.name=name
@property #@property 用于转换方法为属性
def age(self):
return self._age #返回一个属性值
@age.setter #@<方法名>.setter,用于设定属性的赋值操作。
def age(self,value):
if value<0 or value>100:
value=30
self._age=value #对同名属性值的赋值操作进行处理。
dc1=DemoClass("老李")
dc1.age=-100
print(dc1.age)
#输出结果为:30
自定义的异常类型
异常Exception 也是一种python类
class DemoException(Exception): #自定义一个异常类型
def __init__(self,name,msg="自定义异常")
self.name=name
self.msg=msg
try:
raise DemoException("脚本错误") #raise保留字产生异常
except DemoException as e:
print("{}异常的报警时{}".format(e.name,e.msg))
类的名称修饰
名称修饰:类中名称的变换约定
_ X:单下划线开头的名称修饰
class DemoClass:
def __init__(self,name):
self.name=name
self._nick=name+"同志" 约定内部使用
def getNick(self):
return self._nick
dc1=DemoClass("老李")
print(dc1.getNick())
print(dc1._nick) #仍然可以外部调用
X_ :单下划线结尾的名称修饰
__X:双下划线开头的名称修饰
双下划线开头和结尾的名称修饰
_:单下划线
python最小空类
class <类名>():
pass
class EmptyClass:
pass
a=EmptyClass()
a.name="老李"
a.age=50
a.family={"儿子":"小李","女儿":"马冬梅"}
print(a.family)
print(a.__dict__)