Search code examples
pythonconstructorinitializationpython-attrs

How best to initialize a class using an attribute from attrs?


In vanilla Python to create a class which, when initiated, would also initiate another class I would use __init__(self):

class SomeClass:
    __init__(self, token: str):
        self.token = token
        client = WebClient(auth=self.token)

But in attrs, I can't do this. The following yields an error because it is passing a _CountringAttr object, not the resolved string.

@attr.s()
class SomeClass:
    token: str = attr.ib()
    client = WebClient(auth=token)

What is the "right" way of accomplishing this?


Solution

  • You can either use a default:

    @attr.define
    class SomeClass:
        token: str
        client: WebClient = attr.field()  # needed! attr.ib works too
    
        @client.default
        def _client_factory(self):
            return WebClient(self.token)
    

    or __attrs_post_init__:

    @attr.define
    class SomeClass:
        token: str
        client: WebClient = attr.field(init=False)
    
        def __attrs_post_init__(self):
            self.client = WebClient(self.token)
    

    P.S. I'm using the modern attrs APIs to make them more known. Check out https://www.attrs.org/en/latest/names.html if you want to know more.