Как смоделировать `` `WHERE``` из SQL или` `` grep``` в Python для итерации и изменения данных с определенными атрибутами? - PullRequest
0 голосов
/ 26 мая 2019

Я ищу быстрый и простой инструмент для имитации WHERE из SQL.В коллекции (список, набор, словарь и т. Д.) Объектов (каждый из которых должен быть экземпляром списка или класса) я хотел бы выбрать только объекты с некоторыми определенными свойствами / атрибутами и обработать их.

Пример 1:

stuff = {
    "item1":[1,2,3],
    "item2":[4,5,6,7,8,9],
    "item3":[2,4,5]
}

def myfunc(this): # this is the dict above
    result = list()
    for item in this:
        if len(item) == 3:
            result.append(item)
    return result

В примере 1 myfunc имитирует return items in stuff WHERE len(item)==3, который ищет и возвращает объекты длиной 3 в словаре stuff.

Пример 2:

class thing:
    def init(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c

item1 = thing(1,2,3)
item2 = thing(2,3,4)
item3 = thing(3,5,7)
test_list = [item1, item2, item3]

def func(this): # this is the test_list
    result = list()
    for item in this:
        if item.a % 2:
            result.append(item)
    return result

В примере 2 func имитирует return items in test_list WHERE (item.a % 2) == 1, который возвращает объекты, где object.a нечетный.

В обоих примерах коллекция объектов сканируется на определенные атрибуты, которыевыполнить определенные условия и вернуть те объекты для обработки.

Ответы [ 3 ]

0 голосов
/ 26 мая 2019

Вы можете использовать __dict__ экземпляра для доступа ко всем переменным экземпляра.Если вам нужно применить определенные условия, такие как int или что-то еще, вы можете использовать instainceof или подобное.

class particle(object):
    def __init__(self):
        self.height = 100

particles = [particle() for _ in range(2)]

for item in particles:
    item.height -= 1

for item in particles:
    for key in item.__dict__.keys():
        item.__dict__[key] = 5

item .__ dict __ [key] = 5 => Здесь я получаю доступ к переменным экземпляра и изменяю значение.Если вам нужно добавить условие, вы можете добавить сюда.

0 голосов
/ 26 мая 2019

Хаки-код впереди (лучшее решение ниже)

Вы можете реализовать __iter__ в гостях, чтобы он возвращал все атрибуты экземпляра, тогда вы сможете в значительной степени достичь того, что вы ищете:

class particle:
    def __init__(self):
        self.x = 90
        self.y = 70

    def __iter__(self):
        yield from self.__dict__


particles = [particle() for _ in range(2)]

for particle in particles:
    for attribute in particle:
        current_val = getattr(particle, attribute)
        if isinstance(current_val, int):
            setattr(particle, attribute, current_val - 1)

for particle in particles:
    print(particle.x, particle.y)

Выходы

89 69
89 69

лучшее решение

Однако Я не думаю, что это правильный подход. Лучшим способом может быть реализация модификации атрибута внутри самого класса.

class particle:
    def __init__(self):
        self.x = 90
        self.y = 70

    def change_all_attributes(self, attr_type, change_by):
        for attr_name, attr_value in self.__dict__.items():
            if isinstance(attr_value, attr_type):
                setattr(self, attr_name, attr_value + change_by)


particles = [particle() for _ in range(2)]

for particle in particles:
    particle.change_all_attributes(int, -1)
    print(particle.x, particle.y)

Выходы

89 69
89 69

Что вы получаете:

  • Более идиоматический код. Изменение в атрибуте выполняется классом, а не произвольным вложенным циклом где-то в вашем коде (проще для отладки).
  • Встроенный способ управления типом измененных атрибутов и степенью их изменения

Это можно сделать еще дальше, используя методы получения и установки свойств.

0 голосов
/ 26 мая 2019

Вы можете проверить в цикле, если элемент int, например,

isinstance(item, int)
...