Как получить доступ к другому аргументу в аргументе по умолчанию в классе данных Python?

Я пытаюсь получить значение по умолчанию id_ от name и наоборот.

@dataclass
class Item:
    id_ = NAME_TO_ID[name]
    name = ID_TO_NAME[id_]

Я должен иметь возможность вызывать класс так:

Item(id_=123)
Item(name='foo')

Если возможно, я также хотел бы, чтобы класс выдавал ошибку, когда оба id_ а также name предоставлены.

Item(id_=123, name='foo')  # ValueError: id_ and name cannot be provided together

Любые рекомендации о том, как я должен делать это?

3 ответа

Решение

Вы можете использовать написать __post_init__ способ сделать эти проверки

from dataclasses import dataclass, field

@dataclass
class Item:
    id_: int = field(default=None)
    name: str = field(default=None)
    def __post_init__(self):
        if self.id_ is None and self.name is None:
            raise TypeError("You must provide exactly one of name or id_")
        if self.id_ is not None and self.name is not None:
            raise TypeError("You must provide exactly one of name or id_")
        if self.id_ is not None:
            self.name = id_to_name(self.id_)
        else:
            self.id_ = name_to_id(self.name)

Вам нужно будет использовать __init__ функция вашего class,

Например,

class Item:
    # define __init__ such that it has a condition when both id_ and name are supplied
    # a ValueError is raised
    def __init__(self, id_, name=None):
        if (id_ and name):
            # raise error because both were supplied
            raise ValueError
        if (id_):
            # assign name and id
        elif (name):
            # assign name and id

Здесь, однако, пользователь должен передать значение для обоих. Вы можете просто поставить False или же None или какое-то ложное значение, так что оно передается и ValueError не выбрасывается.

Будет ли для вас работать что-то простое, как показано ниже?

При создании объекта проверьте, было ли предоставлено слишком много или слишком мало данных, а затем определите свойство, которое будет вычислять значение при необходимости?

class Item ():
    def __init__(self, id: int =None, name:str= None):
        if all ([name, id]):
            raise ValueError ("id_ and name cannot be provided together")
        elif not any ([name, id]):
            raise ValueError ("name or id must be provided for Item instantiation")
        else:
            self._name = name
            self._id = id
    @property
    def name (self) -> str:
        if self._name is None:
            #Compute the value and return it
            pass #remove this once you figure out your algorithm
        else:
            return self._name
    @property
    def id (self) ->int:
        if self._id is None:
            #Compute the value and return it
            pass #remove this once you figure out your algorithm
       else:
           return self._id

Обратите внимание, что вы также должны принять во внимание, что является действительным значением. В моем примере, приведенном в качестве примера, недостаточно, если вы рассматриваете целое число 0 действительный idи пустая строка "" действительный name,

Другие вопросы по тегам