Как получить доступ к другому аргументу в аргументе по умолчанию в классе данных Python? - PullRequest
0 голосов
/ 16 октября 2018

Я пытаюсь получить значение по умолчанию 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 ]

0 голосов
/ 16 октября 2018

Вы можете использовать метод __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)
0 голосов
/ 16 октября 2018

Вам нужно будет использовать функцию __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 не выдана.

0 голосов
/ 16 октября 2018

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

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

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.

...