ROBERT RICHARDSON ROBERT RICHARDSON - 18 days ago 6
Python Question

Python: Why do I get an exception using super() but not with explicit super class name?

I am getting an exception when I try to access a base class's property using

super()
, but not when I use the base class name explicitly. Here is the derived class:

from CPSA_TransactionLogOutSet import CPSA_TransactionLogOutSet

class CPSA_TransactionFailureSet(CPSA_TransactionLogOutSet):
def __init__(self, connection, failedTransactionKey):
super().__init__(connection)
CPSA_TransactionLogOutSet.C_TRANS_TYP = "TRANS_FAIL"
super().C_TRANS_TYP = "TRANS_FAIL"
super().DefaultTableName = 'CPSA_TRANSACTION_LOG_IN'
super()._keyFields.append('J_TRANS_SEQ')


but trying to create an instance raises an
AttributeError
exception:

AttributeError: 'super' object has no attribute 'C_TRANS_TYP'


The base class consists of an
__init__()
method and a set of properties, only one of which is shown here:

class CPSA_TransactionLogOutSet(Recordset):
def __init__(self, connection):
super().__init__(connection)
self.DefaultTableName = 'CPSA_TRANSACTION_LOG_OUT'

@property
def C_TRANS_TYP(self):
return self.GetValue('C_TRANS_TYP')
@C_TRANS_TYP.setter
def C_TRANS_TYP(self, value):
self.SetValue('C_TRANS_TYP', value)


Why can't I use
super()
to access the
C_TRANS_TYP
property?

Answer

You don't need to use super() at all because there is no override on the current class. The descriptor will be bound to self without super(). The same applies to the other attributes on self:

def __init__(self, connection, failedTransactionKey):
    super().__init__(connection)
    self.C_TRANS_TYP = "TRANS_FAIL"
    self.DefaultTableName = 'CPSA_TRANSACTION_LOG_IN'
    self._keyFields.append('J_TRANS_SEQ')

super() is only needed to access descriptors that would not otherwise be reachable via self. The normal access path (via the instance) suffices here.

super() can't be used to bind data descriptors in an assignment or del obj.attr statement, because super() objects do not implement __set__ or __delete__. In other words, using super().attribute works for reading the attribute only, never for writing or deleting.

Setting CPSA_TransactionLogOutSet.C_TRANS_TYP is also incorrect; that replaces the descriptor object on the class. By executing that line, you removed the descriptor from the class hierarchy altogether, so neither self.C_TRANS_TYP nor super().C_TRANS_TYP would trigger the property you defined before.

Comments