Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Most elegant way to avoid None objects in class? #400

Closed
madig opened this issue Jun 22, 2018 · 3 comments
Closed

Most elegant way to avoid None objects in class? #400

madig opened this issue Jun 22, 2018 · 3 comments
Labels

Comments

@madig
Copy link

madig commented Jun 22, 2018

(continuing from #170 which I don't want to derail)

I have a class like this:

@attr.s(frozen=True, auto_attribs=True)
class Status:
    weight: int = attr.ib(cmp=True)
    message: str = attr.ib(
        cmp=False,
        converter=lambda value: str() if value is None else value,
    )
    code: str = attr.ib(
        cmp=False,
        converter=lambda value: str() if value is None else value,
    )

    @classmethod
    def Debug(cls, message=None, code=None):
        return cls(weight=0, message=message, code=code)

    [...]

    @classmethod
    def Error(cls, message=None, code=None):
        return cls(weight=6, message=message, code=code)

It can be instantiated like this: Status.Error("This and that is wrong etc.", code="mismatched-something"). However, instantiating it like Status.Error() should result in Status(weight=6, message="", code=""), i.e. I want to avoid None objects. Python unfortunately makes it more tedious than it should be to give out non-None default arguments.

@hynek noted that I may want to use default="" and use attr.NOTHING as the default argument in the constructors, however:

In [1]: import attr
   ...: @attr.s
   ...: class Status:
   ...:     a = attr.ib(default="")
   ...:     @classmethod
   ...:     def aaa(cls, a=attr.NOTHING):
   ...:         return cls(a)
   ...:

In [2]: Status.aaa()
Out[2]: Status(a=NOTHING)

In [3]: Status.aaa("")
Out[3]: Status(a='')

In [4]: import attr
   ...: @attr.s
   ...: class Status:
   ...:     a = attr.ib(default="")
   ...:     @classmethod
   ...:     def aaa(cls, a=None):
   ...:         return cls(a=a or attr.NOTHING)

In [5]: Status.aaa()
Out[5]: Status(a=NOTHING)
@madig
Copy link
Author

madig commented Jun 22, 2018

(I suppose I can use def aaa(cls, a=""): here because strings are immutable, but I'd like to know about a more general approach.)

@hynek
Copy link
Member

hynek commented Jun 22, 2018

Ugh right the NOTHING way doesn’t work because attrs uses literal "" as default parameters if possible.

@hynek
Copy link
Member

hynek commented Jun 22, 2018

I guess what could be done is some kind of attr.converters.default_if_none(default=NOTHING, factory=None) so you could write attr.converters.default_if_none(default="") or attr.converters.default_if_none(factory=list). I think I had uses for that too before. 🤔

@hynek hynek added the Feature label Jun 23, 2018
hynek added a commit that referenced this issue Jul 28, 2018

Verified

This commit was signed with the committer’s verified signature. The key has expired.
Synthetica9 Patrick Hilhorst
fixes #400
@hynek hynek closed this as completed in afd2584 Jul 28, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants