面向对象中的索引,切片,比较操作(将对象理解为列表)

  • 一、索引操作
  • 二、切片操作
  • 三、比较操作
  • 四、上下文布尔值


一、索引操作

作用
    可以对一个实例对象进行索引操作

步骤
    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"]

设索引python 索引值python_字符串


索引操作的具体应用

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)

设索引python 索引值python_设索引python_02

二、切片操作

正常列表的切片操作:

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]# 切片

设索引python 索引值python_字符串_03


这时我们发现,切片操作输出的是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]# 切片

设索引python 索引值python_面向对象_04


在获取元素时的切片操作也类似:

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]

设索引python 索引值python_面向对象_05


切片操作的具体应用:

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[:]) #这是针对一个普通列表的切片操作

设索引python 索引值python_python_06

三、比较操作

正常情况下比较操作是这样的

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)

设索引python 索引值python_设索引python_07


注意事项: 如果这几种比较方法并没有全部定义,在进行相反的操作时,系统会自动置换没有定义的方法,比如只定义了 “ < ”,没有定义 “ > ”,在进行 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)

设索引python 索引值python_面向对象_08


但是这种置换并不能叠加,比如<和=并不能合并成<=,但是在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)

设索引python 索引值python_开发语言_09

四、上下文布尔值

主要是__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("布尔类型返回为假")

设索引python 索引值python_面向对象_10