I have a dataclass that looks like this
from dataclasses import dataclass, field
@dataclass
class Data:
name: str | None = None
file_friendly_name: str | None = field(default=None, init=False)
def __post_init__(self):
# If name, automatically create the file_friendly_name
if self.name:
self.file_friendly_name = "".join(
i for i in self.name if i not in "/:*?<>|"
)
If user passes name
on instantiation, file_friendly_name
is automatically created.
Is there a way to do it so that every time name
is updated/changed, file_friendly_name
also changes?
e.g.
data = Data()
data.name = 'foo/bar'
print(data.file_friendly_name) # want: 'foobar'
data = Data(name='foo/bar')
data.name = 'new?name'
print(data.file_friendly_name) # want: 'newname'
Update based on answers:
_name: str
and creating name
using getters/setters. But I don't like how when you do print(Data())
it shows _name
as an attribute. I'd like that not to happen.file_friendly_name
as a property. But then you can't see that as an attribute when you do print(Data())
. This is less of an issue but still not ideal.Can it just show name
and file_friendly_name
as attributes when doing print(Data())
?
I'd suggest defining file_friendly_name
as @property
instead.
from dataclasses import dataclass, fields
@dataclass
class Data:
name: str | None = None
@property
def file_friendly_name(self) -> str | None:
if self.name is not None:
return "".join(
i for i in self.name if i not in "\/:*?<>|"
)
else:
return None
def __repr__(self):
fields_str = [f'{field.name}={getattr(self, field.name)!r}'
for field in fields(self)]
fields_str.append(f'file_friendly_name={self.file_friendly_name}')
fields_res = ', '.join(fields_str)
return f'{type(self).__name__}({fields_res})'