Как ограничить диапазон значений в словаре? - PullRequest
0 голосов
/ 26 января 2019

Я хотел бы наложить ограничения на значение в словаре. Например, предположим, что у меня есть следующий словарь

speed = {
    'x': 8,
    'y': 0,
    'z': 4}

И я хочу, чтобы значение, соответствующее клавише x в словаре скорости, всегда было меньше 10. Например, если я использую это в какой-то функции

    calcuate_speed(speed)

или если я реализую математическое преобразование

    speed["x"] += 1 

значение не должно быть больше определенного предела, который я определил. Какой самый простой способ справиться с этим?

Ответы [ 3 ]

0 голосов
/ 26 января 2019

Вы можете сделать это следующим образом:

from collections import UserDict


class MyDict(UserDict):
    def __setitem__(self, key, value):
        if value > 10: # any validation
            raise ValueError('Too big!')

        super().__setitem__(key, value)

Но будет лучше использовать класс с property.

Полная версия:

from collections import UserDict

from math import sqrt


class VectorDict(UserDict):
    def __init__(self, *args, speed_limit, **kwargs):
        self.speed_limit = speed_limit
        super().__init__(*args, **kwargs)

    def __setitem__(self, key, value):
        if self._calc_speed(key, value) > self.speed_limit:
            raise ValueError('Too big!')

        super().__setitem__(key, value)

    def _calc_speed(self, replace_key=None, replace_value=0):
        square_sum = 0
        for key, value in self.items():
            if key == replace_key:
                value = replace_value

            square_sum += value ** 2

        return sqrt(square_sum)

    @property
    def speed(self):
        return self._calc_speed()


example_1d = VectorDict(x=1, speed_limit=5)
example_2d = VectorDict(x=1, y=5, speed_limit=7)
example_3d = VectorDict(x=1, y=5, z=3, speed_limit=13)

print(example_3d.speed)
example_3d['x'] += 10 # ValueError: Too big!
0 голосов
/ 26 января 2019

Определите класс MyClass со свойством speed:

class MyClass:
    def __init__(self):
        self.speed = 0

    def __setattr__(self, k, v):
        if k == 'speed' and v > 10: 
            return
        self.__dict__[k] = v

Здесь я просто игнорирую любые изменения speed, если это недопустимое значение, но вы можете обрабатывать его по-другомусогласно вашим потребностям (например, поднять исключение)

Вот демонстрационная версия:

m = MyClass()
m.speed = 8 
print(m.speed)
m.speed += 1
print(m.speed)
m.speed += 1
print(m.speed)
m.speed += 1
print(m.speed)

Мы получаем следующий вывод:

8
9
10
10
0 голосов
/ 26 января 2019

Просто добавьте немного контроля значения в вашем цикле. Например:

if (speed['x'] >= 10):
        speed['x'] = 9
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...