Reputation: 3658
This is just a little curiosity. I usually find myself updating a class attribute inherited in a subclass and I'd like to know how others deals with it. I know that I can't update them in the __init__
: since it's a class attribute I would update it to the superclass instances as well. So I usually do something like this:
class A(object):
attribute = {
1: 'a',
...,
5: 'e',
}
class B(A):
attribute = {
1: 'a',
...,
5: 'e',
6: 'f',
}
But, since I like to follow the DRY principle as much as possible and I'd like to know if someone use a more elegant way to do this without completely copy and paste the attribute.
As asked this is a concrete example with Django forms:
class LoginForm(AuthenticationForm):
username = forms.EmailField(label=_('Email'))
error_messages = {
'inactive': _('This account is inactive.'),
'invalid_login': _('Please enter a correct username and password. '
'Note that both fields may be case-sensitive.'),
'unconfirmed': _('Your account is not confirmed yet. Please '
'check your email and follow the instructions '
'in order to activate it.'),
}
def confirm_login_allowed(self, user):
super(LoginForm, self).confirm_login_allowed(user)
if not user.confirmed:
raise forms.ValidationError(
self.error_messages['unconfirmed'],
code='unconfirmed')
The error_messages attribute is inherited from django.contrib.auth.forms.AuthenticationForm but I wanted to add the 'unconfirmed' key so I had to copy and paste the 'inactive' and 'invalid_login' keys too.
Upvotes: 1
Views: 109
Reputation: 69120
If you do put it in __init__
then every instance of the subclass (B
in this case), will see the update. The only time you would not is if you specify the class directly:
B.attribute[6]
# KeyError
One way without using __init__
is to:
class B(A):
attribute = A.attribute.copy()
attribute.update({
6: 'f',
7: 'g',
})
print(B().attribute) # --> {1:'a', ..., 5:'e', 6:'f', 7:'g'}
print(A().attribute) # --> {1:'a', ..., 5:'e'}
The point to remember is that a class's code is executed as it is created, so you can use normal Python to make adjustments.
Upvotes: 3
Reputation: 123491
This seems to work:
class A(object):
attribute = {
1: 'a',
5: 'e',
}
class B(A):
attribute = A.attribute.copy()
attribute[6] = 'f'
print(A.attribute) # -> {1: 'a', 5: 'e'}
print(B.attribute) # -> {1: 'a', 5: 'e', 6: 'f'}
Upvotes: 1