Как получить доступ к другому аргументу в аргументе по умолчанию в классе данных 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
,