-
Notifications
You must be signed in to change notification settings - Fork 53
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
Should it be possible to pass parameter(s) to the post-init function? #17
Comments
One option is to inspect Something like:
The generated
This could always be added at a later date. I've occasionally needed functionality like this, but I've found ways to work around it. |
On the other hand, finding out the parameter names in the presence of classmethod, staticmethod, and other descriptors might be impossible. Maybe something like:
|
Maybe this is an area where we can just copy attrs' design?
|
To my knowledge, attrs doesn't let you pass in parameters to their |
At least in this stage, and given the discussion about attrs vs. stdlib, let's stick to that. |
…of parameterized __dataclass_post_init__. Add a test showing the technique.
Food for thought, no action item here. It occurs to me that one way around this is to have init-only members of a dataclass. That is, members that are params to I think this best way to do this would be to treat them like we do with
I'm not sure what we'd want to leave in |
But ' database' *is* an attribute on self, right? I think it should be
considered a field, just a rather shy one.
|
I guess it could be a member of the class, if it had a default value. Let's first look at how
There's never any assignment to C.x, so there's no attribute defined on the class. And, it's not a field, so there's no per-instance attribute. Maybe you should be required to have a default value, but I say leave it up to the class author. Here's how
So, there is now a class attribute I would propose that an Then the only difference between a |
Note that as of #73, |
OK, I get it now, sounds fine.
|
While I like this idea a lot, I'm running in to some complications with base classes that also have |
@ilevkivskyi : Any comments on this design? I want to make sure I'm not doing anything that won't work well with static type checkers. The only wart on it is that you'd need to repeat typing information if you wanted to fully specify
Like Later today I'll post a note about how this would work with base classes. |
It is fine with mypy. We will anyway need some
|
@ilevkivskyi : Thanks. Good news. And omitting the type on the |
Yes, as I mentioned we will need some special-casing anyway to construct the |
… pseudo-fields in __dataclass_fields__, and filter them out as needed.
Here's an example of how this would work with inheritance. The field ordering is the same as with real fields: base fields (in order) before derived fields (in order):
Normally, I think you'd end up using named parameters in such a complicated case, but this test doesn't have them to make sure I actually get the fields in the right order. I can't find where we had the discussion, but we've previously determined that we can't automatically chain |
… simply implement InitVar. An open issue is if I support any type on it at all, or just make it always plain "init_param: InitVar".
This sounds right. We have regular fields, Agreed on the chaining, but we should make it very clear in the docs that users should call super methods. In fact maybe there should be a no-op |
Yes, that description of the kinds of fields is spot-on. Instead of adding I think we had a similar discussion with chaining That said, I think we could inspect |
One "interesting" byproduct of having Here, with a default value for an
Produces:
If we omit the default for
Produces:
I think this all follows logically from how the various functions are defined, but it might be surprising to callers. But then |
Apart from |
Yes, this With that, I'd like to refocus this issue on |
OK. |
I'm standing on the sidelines here, but I just realized why we have to
leave the choice of what to do with super args up to the user -- if there's
cooperative multiple inheritance, there may be fields that are not known
from looking at the current class and its MRO. And these need to be dealt
with using **kwds. But not every user will want this -- if they don't care
about cooperative MI, they're welcome to just call the immediate super
class's method with the exact arguments it takes.
|
@gvanrossum : agreed. I lied about there being no more issues. The issue of where to specify the type of the It could be:
Or:
@ilevkivskyi : Any preference? All things being equal I'd prefer the former because of the parallel with |
@ericvsmith |
I'd like to support just one. It doesn't really make a difference to dataclasses, since it ignore the type. It just needs @gvanrossum : Do you have an opinion? See #17 (comment) (2 messages up). The goal is to not repeat the type information for the Another reason to require it on the class variable annotation (my slight preference) is that this is valid (if ill-advised):
Which produces [Edit: slight wording improvement] |
I would make the former canonical: @dataclass
class C:
i: int
db: InitVar[DatabaseType]
def __post_init_(self, db): ... This keeps the types all in one place, and matches what's done for ClassVar. We can't stop users from also annotating the methods (if they want type checking) so the redundant form must also be allowed: @dataclass
class C:
i: int
db: InitVar[DatabaseType]
def __post_init_(self, db: DatabaseType) -> None: ... but that's the case for all sorts of correspondences. Having the form with just InitVar in the class feels weird, we don't have any precedent for that. |
… approach is to implement it from scratch, instead of trying to whittle down ClassVar.
…on that InitVar fields must be passed to replace().
Currently the post-init function
__dataclass_post_init__
takes no parameters. Should it be possible to pass one or more parameters from__init__
to the post-init function? Is it possible to make the parameter optional?It would be nice to pass parameters to
__init__
which do not initialize fields, but are accessible to the post-init function. But, it might mess up the interface too much, and there are issues with calling__dataclass_post_init__
'ssuper()
function if we decide to change the number of parameters.This issue is a placeholder to decide this issue before the code and PEP are finalized. Any suggestions or thoughts are welcome.
The text was updated successfully, but these errors were encountered: