Description
Hi,
I'm part of a team that's in the early stages of migrating a large legacy app to Python. I'm pushing pretty hard for the team to adopt attrs as our standard way of doing OOP. I know the "attr way" is to avoid inheritance as much as possible, but that's not always possible, especially when you are part of a team with a project that likes to rely on inheritance (generally nothing too crazy, just simple stuff, but still - it's used a lot in the app and it's a good fit a lot of how the app works). One thing we do a lot is have base classes that device attributes that subclasses "further refine". With these, we want to be able to "extended" the attribute definition from the parent classes vs. totally overwrite it. It doesn't seem like this is possible today in attrs. For example:
import attr
import inspect
@attr.s
class One:
myattrib = attr.ib(
default=1,
validator=attr.validators.instance_of(int),
converter=int,
)
@attr.s
class Two(One):
myattrib = attr.ib(
default=2
)
print(inspect.getsource(One().__init__))
print(inspect.getsource(Two().__init__))
Output when run:
def __init__(self, myattrib=attr_dict['myattrib'].default):
self.myattrib = __attr_converter_myattrib(myattrib)
if _config._run_validators is True:
__attr_validator_myattrib(self, __attr_myattrib, self.myattrib)
def __init__(self, myattrib=attr_dict['myattrib'].default):
self.myattrib = myattrib
So if we want to extend the definition of myattrib
, we would have to copy/paste the full definition vs. just modify what is different. What would people think about an option that says "take the full definition from the superclasses and just "merge in" this one extra aspect." Having to repeat the full definition across an inheritance hierarchy gets old (and ugly) pretty quick. :-)
Just by way of context on both this ticket and the other ticket I have opened (#573 - lazy=True option), the legacy app we are using is coming from Perl. Yes, I know everyone loves to hate Perl, :-) but hear me out. :-) The app uses Moose (https://metacpan.org/pod/Moose) and it's "lightweight cousin" Moo (https://metacpan.org/pod/Moo) and for all the bad things everyone wants to cast at Perl, the Moose/Moo "OOP framework" is really nice and has some great features. It has completely changed how OOP is done in Perl and took it from horrible to really nice (nobody has done OOP in Perl for 10+ years without using Moose.) (The creator of Moose, Stevan Little, spent lots of time studying and using lots of other OOP methodologies and was able to incorporate the "best of the best" ideas.) It's very similar to attrs in many ways, but there are a few things missing that are SOOO handy, useful, powerful, etc. :-)
In terms of how Moose would write the above example (and use the "+" to signify an "override"):
package One;
use Moo;
use Types::Standard 'Int';
has 'myattrib' => (
is => 'ro',
default => 1,
isa => Int,
coerce => sub { int(shift) }, # Not required for str->int but to show how others work
);
package Two;
use Moo;
extends 'One';
has '+myattrib' => ( # <== Note the '+'
default => 2,
);
Would something like an extend=True
option to attrs be a nice addition to trigger similar behavior to the "+" shown above?
Thank you