面向对象中的索引,切片,比较操作(将对象理解为列表)
- 一、索引操作
- 二、切片操作
- 三、比较操作
- 四、上下文布尔值
一、索引操作
作用
可以对一个实例对象进行索引操作
步骤
1. 实现三个内置方法
设置元素的方法
def __setitem__(self, key, value):
获取元素的方法
def __getitem__(self, item):
删除元素的方法
def __delitem__(self, key):
2. 可以以索引的形式操作对象
增/改
p[1] = 666
p["name"] = "sz"
查
p["name"]
p[1]
删
del p["name"]
del p[1]举例如下:
class Person:
def __setitem__(self, key, value):
print("setitem", key, value)
def __getitem__(self, item):
print("getitem", item)
def __delitem__(self, key):
print("delitem", key)
p = Person()
p["name"] = 'sz'
print(p["name"])
del p["name"]
索引操作的具体应用
class Person:
def __init__(self):
self.cache = {}
def __setitem__(self, key, value):
# print("setitem", key, value)
self.cache[key] = value
def __getitem__(self, item):
# print("getitem", item)
return self.cache[item]
def __delitem__(self, key):
# print("delitem", key)
del self.cache[key]
p = Person()
p["name"] = 'sz'
print(p.cache)
print(p["name"])
del p["name"]
print(p.cache)
二、切片操作
正常列表的切片操作:
l=[1,2,3,4,5,6]
print(l[1:4:2]) # 正常列表的切片操作实例对象的切片操作使用的函数还是索引操作三连函数:
先测试__setitem__函数:
class Person:
def __setitem__(self, key, value):
print("key = {},value = {}".format(key,value))
p=Person()
p[1]=0 # 索引
p[0:4:2]=[1,2]# 切片
这时我们发现,切片操作输出的是slice(0, 4, 2),所以key并不是一个简单的字符串或者数值,而是一个slice的实例对象(切片对象),在python中查看slice的源码,在末尾处可以看到三个属性
start = property(lambda self: 0)
""":type: int"""
step = property(lambda self: 0)
""":type: int"""
stop = property(lambda self: 0)
""":type: int"""我们可以通过start,step,stop操作slice对象,具体操作如下:
class Person:
def __setitem__(self, key, value):
#print("key = {},value = {}".format(key,value))
print("列表开始:",key.start)
print("列表步长:", key.step)
print("列表结尾:", key.stop)
p=Person()
p[0:4:2]=[1,2]# 切片
在获取元素时的切片操作也类似:
class Person:
def __setitem__(self, key, value):
#print("key = {},value = {}".format(key,value))
print("列表开始:",key.start)
print("列表步长:", key.step)
print("列表结尾:", key.stop)
def __getitem__(self, item):
print("getitem",item)
print("列表开始:", item.start)
print("列表步长:", item.step)
print("列表结尾:", item.stop)
p=Person()
p[0:4:2]=[1,2]# 切片
p[0:5:2]
切片操作的具体应用:
class Person:
def __init__(self):
self.items = [1, 2, 3, 4, 5, 6, 7, 8]
def __setitem__(self, key, value):
if isinstance(key, slice): # 先判定key是普通数字或者字符串还是slice对象
self.items[key.start: key.stop: key.step] = value
else:
self.items[key]=value
def __getitem__(self, item):
return self.items[item] # 其实不判定,这样写也是可以的
p = Person()
p[0:6:2] = ["a", "b", "c"] # 切片
print(p.items)
print(p[0:6:2])
p[1]="xxxx"
print(p[:]) # 这是面向对象切片操作
print(p.items[:]) #这是针对一个普通列表的切片操作
三、比较操作
正常情况下比较操作是这样的
a=10
b=2
print(a>b)在面向对象类中实现比较操作要用到比较方法,self是当前类,other是比较类:
方法 | 解释 |
__eq__(self, other) | 相等(==) |
__ne__(self, other) | 不相等(!=) |
__lt__(self, other) | 小于(<) |
__le__(self, other) | 小于或等于(<=) |
__gt__(self, other) | 大于(>) |
__ge__(self, other) | 大于或等于(>=) |
具体示例如下:
class Person:
# == != >= <=
def __init__(self, age, height):
self.age = age
self.height = height
# ==
def __eq__(self, other): # other是另一个参与比较的对象
return self.age == other.age
# !=
def __ne__(self, other):
return self.age != other.age
# >
def __gt__(self, other):
return self.age > other.age
# >=
def __ge__(self, other):
return self.age >= other.age
# <
def __lt__(self, other):
return self.age < other.age
# <=
def __le__(self, other):
print("lt")
return self.age < other.age
p1 = Person(18, 180)
p2 = Person(17, 190)
print(p1 == p2)
print(p1 <= p2)
注意事项: 如果这几种比较方法并没有全部定义,在进行相反的操作时,系统会自动置换没有定义的方法,比如只定义了 “ < ”,没有定义 “ > ”,在进行 p1 > p2 的操作时,会自动置换成p2 < p1,然后去执行由__lt__(self, other):定义的小于方法,示例如下:
class Person:
# == != >= <=
def __init__(self, age, height):
self.age = age
self.height = height
# <
def __lt__(self, other):
print("lt,self={},other={}".format(self.age,other.age))
return self.age < other.age
p1 = Person(18, 180)
p2 = Person(17, 190)
print(p1<p2)
print(p1>p2) # 没有定义__gt__(self, other):方法,会自动置换p1和p2,即当前语句变成print(p2<p1)
但是这种置换并不能叠加,比如<和=并不能合并成<=,但是在functools包中使用@functools.total_ordering装饰器是可以实现合并操作的,示例如下:
import functools
@functools.total_ordering
class Person:
# == != >= <=
def __init__(self, age, height):
self.age = age
self.height = height
# <
def __lt__(self, other):
print("lt,self={},other={}".format(self.age,other.age))
return self.age < other.age
#==
def __eq__(self, other): # other是另一个参与比较的对象
return self.age == other.age
print(Person.__dict__.keys())运行结果:
dict_keys(['__module__', '__init__', '__lt__', '__eq__', '__dict__', '__weakref__', '__doc__', '__hash__', '__gt__', '__le__', '__ge__'])
进程已结束,退出代码 0可以看出,系统自动定义了>,>=,<=。其使用方法是先执行小于,在执行等于。
import functools
@functools.total_ordering
class Person:
# == != >= <=
def __init__(self, age, height):
self.age = age
self.height = height
# <
def __lt__(self, other):
print("lt,self={},other={}".format(self.age,other.age))
print("小于")
return self.age < other.age
#==
def __eq__(self, other): # other是另一个参与比较的对象
print("等于")
return self.age == other.age
print(Person.__dict__.keys())
p1 = Person(18, 180)
p2 = Person(17, 190)
print(p1<=p2)
print(p1>p2)
四、上下文布尔值
主要是__bool__方法,看代码就行
class Person:
def __init__(self):
self.age=20
def __bool__(self):
return self.age>=18
class Person2:
pass
p=Person()
p2=Person2()
if p2:
print("布尔类型返回为真")
if p:
print("布尔类型返回为真")
p.age=15
if p:
print("布尔类型返回为真")
else:
print("布尔类型返回为假")
















