python中的operator模块

1. itemgetter 函数

1.1 itemgetter 功能和参数

itemgetter是Python内置的operator模块中的函数之一,用于获取可迭代对象中的某个元素(或多个元素)或者对象的属性值。itemgetter函数可以接受一个或多个参数,每个参数可以是一个整数、一个字符串或一个可以调用的对象。

  • itemgetter(n):获取可迭代对象中第n个元素。
  • itemgetter(n1, n2, …):获取可迭代对象中第n1、n2、…个元素,返回一个元组。
  • itemgetter(attr):获取可迭代对象中元素的attr属性。
  • itemgetter(item):获取可迭代对象中元素为item的元素。(item可以是任何可比较的对象,包括数值、字符串、元组等。)

1.2 底层原理

itemgetter函数是通过实现一个类,并在类中定义一个 __getitem__() 方法来实现的。
在类的实例化过程中,可以将要获取的元素的索引或属性名作为参数传递给类的构造方法,该参数会被保存在类的属性中。
当调用类的实例时,实际上是调用了 __getitem__() 方法,并将可迭代对象作为参数传递给该方法。
__getitem__() 方法会根据保存的参数,获取可迭代对象中指定元素的值或对象的指定属性值,并返回这个值。
# itemgetter函数的底层实现可以看做是以下代码:

class ItemGetter:
    def __init__(self, *items):
        self.items = items
    def __getitem__(self, index):
        if isinstance(index, int):
            return lambda x: x[index]
        elif isinstance(index, str):
            return lambda x: getattr(x, index)
        elif callable(index):
            return lambda x: index(x)
        else:
            raise TypeError('Invalid argument type')

def itemgetter(*items):
    return ItemGetter(*items)

# ItemGetter 类定义了一个构造方法 __init__(),该方法接受一个或多个参数,
# 这些参数表示要获取的元素的索引或属性名,并将它们保存在类的 items 属性中。
# 同时,ItemGetter 类还实现了一个特殊方法 __getitem__(),该方法接受一个可迭代对象作为参数,
# 并根据保存的 items 属性,获取可迭代对象中指定元素的值或对象的指定属性值。
# 
# itemgetter() 函数实际上是对 ItemGetter 类的实例化,返回一个 ItemGetter 类的对象。
# 这个对象可以作为一个可调用的函数使用,并接受一个可迭代对象作为参数,
# 返回可迭代对象中指定元素的值或对象的指定属性值。

1.3 优缺点

  • itemgetter函数的优点在于其简洁、高效、通用性强,可以用于各种场景下的元素获取操作。 同时,它还可以作为参数传递给其他函数,如sorted、max、min等,使得这些函数更加灵活。
  • 缺点在于itemgetter函数只能获取指定的元素,而不能进行其他操作,如过滤、转换等。此外,如果需要获取的属性不是固定的,而是动态生成的,那么itemgetter函数就无法满足需求。

1.4 示例方法

  • 获取列表中指定索引的元素
from operator import itemgetter

lst = ['a', 'b', 'c', 'd', 'e']
getter = itemgetter(2)
print(getter(lst)) # 'c'

  • 获取列表中多个索引对应的元素
lst = ['a', 'b', 'c', 'd', 'e']
getter = itemgetter(2, 4)
print(getter(lst)) # ('c', 'e')


  • 获取字典中指定属性的值
dct = {'a': {'name': 'Alice', 'age': 23},
       'b': {'name': 'Bob', 'age': 25},
       'c': {'name': 'Charlie', 'age': 20}}
getter = itemgetter('name')
print(list(map(getter, dct.values()))) # ['Alice', 'Bob', 'Charlie']

  • 列表套字典,然后按照字典的某一个键或者多个键来对列表套字典的数据格式来排序
from operator import itemgetter
from pprint import pprint

data_list = [
    {"name": "java", "num_1": 10, "num_2": 1},
    {"name": "c", "num_1": 8, "num_2": 96},
    {"name": "go", "num_1": 160, "num_2": 0},
    {"name": "html", "num_1": 20, "num_2": 1},
    {"name": "vue", "num_1": 1, "num_2": 1},
]
# sorted() 函数默认升序
by_name = sorted(data_list, key=itemgetter('name'))
by_num_1 = sorted(data_list, key=itemgetter('num_1'))
pprint(by_name)
pprint(by_num_1)

# [{'name': 'c', 'num_1': 8, 'num_2': 96},
#  {'name': 'go', 'num_1': 160, 'num_2': 0},
#  {'name': 'html', 'num_1': 20, 'num_2': 1},
#  {'name': 'java', 'num_1': 10, 'num_2': 1},
#  {'name': 'vue', 'num_1': 1, 'num_2': 12}]
# [{'name': 'vue', 'num_1': 1, 'num_2': 12},
#  {'name': 'c', 'num_1': 8, 'num_2': 96},
#  {'name': 'java', 'num_1': 10, 'num_2': 1},
#  {'name': 'html', 'num_1': 20, 'num_2': 1},
#  {'name': 'go', 'num_1': 160, 'num_2': 0}]

# 先对num_2进行排序,如果有相同的,再按照num_1再次排序
by_num_1_num_2 = sorted(data_list, key=itemgetter('num_2', 'num_1'))
pprint(by_num_1_num_2)
# [{'name': 'go', 'num_1': 160, 'num_2': 0},
#  {'name': 'vue', 'num_1': 1, 'num_2': 1},
#  {'name': 'java', 'num_1': 10, 'num_2': 1},
#  {'name': 'html', 'num_1': 20, 'num_2': 1},
#  {'name': 'c', 'num_1': 8, 'num_2': 96}]

  • 列表套字典,然后按照字典的某个键取出最大或者最小的那个字典
from operator import itemgetter

data_list = [
    {"name": "java", "num_1": 10, "num_2": 1},
    {"name": "c", "num_1": 8, "num_2": 96},
    {"name": "go", "num_1": 160, "num_2": 0},
    {"name": "html", "num_1": 20, "num_2": 1},
    {"name": "vue", "num_1": 1, "num_2": 1},
]

min_data = min(data_list, key=itemgetter('num_1'))
print(min_data)
max_data = max(data_list, key=itemgetter('num_1'))
print(max_data)

# {'name': 'vue', 'num_1': 1, 'num_2': 1}
# {'name': 'go', 'num_1': 160, 'num_2': 0}

  • 按照元素属性排序
lst = [{'name': 'Alice', 'age': 23},
       {'name': 'Bob', 'age': 25},
       {'name': 'Charlie', 'age': 20}]
getter = itemgetter('age')
lst.sort(key=getter)
print(lst) # [{'name': 'Charlie', 'age': 20}, {'name': 'Alice', 'age': 23}, {'name': 'Bob', 'age': 25}]

  • 获取嵌套列表中指定元素
lst = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
getter = itemgetter(1, 2)
print([getter(sublst) for sublst in lst]) # [(2, 3), (5, 6), (8, 9)]

2. attrgetter 函数

2.1 功能参数

operator模块中的attrgetter函数是一个用于获取对象属性的函数。其作用是传入一个属性名称,返回一个函数,这个函数可以获取对象中的该属性的值。

attrgetter函数的参数可以是字符串或者字符串组成的列表,用于指定要获取的属性。
如果属性不存在,会引发AttributeError异常。

attrgetter函数的用法非常灵活,它可以用于排序、过滤、分组等各种操作中,可以根据对象的某个属性进行排序或者分组。
此外,attrgetter函数还可以用于自定义对象的比较函数。

具体来说,attrgetter函数可以接受以下参数:
    1.attrgetter(attr)
        传入一个字符串表示要获取的属性名称。如果要获取的属性是嵌套的,可以用"."进行分隔,例如attrgetter("x.y.z")表示要获取的属性是x对象的y属性的z属性的值。
    2.attrgetter(attr1, attr2, ...)
        传入多个字符串表示要获取的多个属性名称。
    3.attrgetter(*attrs)
        传入一个由字符串组成的列表,表示要获取的多个属性名称。

2.2 底层原理

attrgetter函数主要使用了Python的属性访问机制,即通过getattr函数动态获取对象的属性值。
其底层实现思路如下:

1、首先判断函数是否传入了参数,如果没有,则返回一个返回输入参数本身的函数,否则继续执行。
2、定义一个内部函数g,该函数接受一个对象作为参数,并返回一个元组。
3、在函数g中,使用循环遍历每个属性,并使用getattr函数获取该属性的值,将其存储在一个列表中。
4、最后将该列表转换为元组,并返回。

需要注意的是,attrgetter函数返回的是一个函数对象,而不是具体的属性值。
因为该函数可能会被多次调用,每次调用传入的对象可能不同,因此需要返回一个能够处理不同对象的函数。


2.3 优缺点

  • 优点:
可以简化代码,减少重复性的操作。
可以提高代码的可读性,易于理解和维护。
可以根据属性的值进行排序和比较,便于对对象进行操作。
  • 缺点:
在一些情况下,使用attrgetter函数可能会导致代码的执行速度慢,因为需要额外的函数调用和内存分配。
有时候使用attrgetter函数会使代码变得复杂,不容易理解。
对于一些特定的数据结构,如树和图等,使用attrgetter函数可能不太方便。

2.4 示例方法

  • 按照对象的某个属性进行排序
from operator import attrgetter


class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __repr__(self):

        return f'[{self.name}, {self.age}]'



people = [Person('Alice', 25), Person('Bob', 30), Person('Charlie', 20)]
sorted_people = sorted(people, key=attrgetter('age'))
print(sorted_people)
# [[Charlie, 20], [Alice, 25], [Bob, 30]]
  • 对象列表按照某个属性排序
from operator import attrgetter

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __repr__(self):
        return f'{self.name}, {self.age}'

people = [Person('Alice', 25), Person('Bob', 30), Person('Charlie', 20)]
sorted_people = sorted(people, key=attrgetter('age'))
# sorted_people: [Charlie, 20, Alice, 25, Bob, 30]

  • 可以使用map方法获取对象列表中的某个属性值列表
from operator import attrgetter

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __repr__(self):
        return f'{self.name}, {self.age}'

people = [Person('Alice', 25), Person('Bob', 30), Person('Charlie', 20)]
ages = list(map(attrgetter('age'), people))
# ages: [25, 30, 20]

持续更新中。。。

你可能感兴趣的:(Python进阶,python,itemgetter,operator,字典,列表套字典)