-
-
Notifications
You must be signed in to change notification settings - Fork 374
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
Example of initialsing base class in a derived class #167
Comments
Hmmm, I found the "How Does It Work?" documentation, which states that attrs never calls Still a good example would be good :) |
Yeah, if all your bases are attrs classes without |
How do you initialise a base class attribute with a different value? e.g. base class has member I tried using I did try |
Generally speaking, we believe that subclassing for object composition is a bad thing, therefore attrs doesn’t have explicit support for many things that it entails. That said, getting two members |
A while ago I was asking this same question. I was not looking for a way to overwrite an attribute, but just call As I continued learning what I was doing, I noticed a thread was not needed anymore (and therefore the inheritance), but I'm still curious: how to initialize the parent class with attrs? It seems there are two cases:
Is that correct? Thanks! |
Looks correct, yes. Calling |
The reason I called I did not mention that at first because I thought that was the wrong way to do it. I thought that Now that you mentioned and after thinking a second time, I think that behavior is actually wrong. import attr
a_post_init_called = False
@attr.s
class A(object):
a = attr.ib()
def __attrs_post_init__(self):
global a_post_init_called
a_post_init_called = True
b_post_init_called = False
@attr.s
class B(A):
b = attr.ib()
def __attrs_post_init__(self):
global b_post_init_called
b_post_init_called = True
super().__init__('')
try:
b = B('a', 'b')
except Exception as e:
print(e)
print('post inits called: {}, {}'.format(a_post_init_called,
b_post_init_called)) output:
(I passed Just to clarify: I do not think that using attrs like this is correct and I am not asking you to provide anything to support code like this. I am just reporting something that seems wrong. |
To summarize: If you subclass from another attrs class, the subclass collects all attributes from the parent class hierarchy, and from itself, and generates a brand new But if your superclass did some special
Demonstration of all cases: @attr.s
class A:
a = attr.ib()
def __attrs_post_init__(self):
print('a hello')
@attr.s
class B(A): # Because this class has a post-init, only THIS post-init will run.
b = attr.ib()
def __attrs_post_init__(self):
super().__attrs_post_init__() # Without manually calling, A's post-init wouldn't run.
print('b hello')
@attr.s
class C(A): # Because this class lacks a post-init, the one from A will run instead.
c = attr.ib() Result in python console:
Of course, in hindsight, perhaps attr should have been coded so that its But it's way too late to change that design now, since most people have code now that manually calls the superclass post-init function as shown in example B above. And there are many great arguments for the way things are designed, because it means that YOU decide if you want the superclass I just wanted to document everything. Thanks @hynek @felipedau @BrendanSimon for all your info in this thread. |
If I have a class hierarchy using attrs, how do I initialise the parent class ?
Normally the constructor would call
super().__init__()
right? How is this done with attrs classes?Could you provide and example in the examples documentation please :)
The text was updated successfully, but these errors were encountered: