2

I am confused on why the code below does not work:

class ComparativeAnnotatorConfiguration(HashableNamespace):
    """
    Takes the initial configuration from the main driver script and builds paths to all files that will be produced
    by these tasks.
    """
    def __init__(self, args, gene_set, query_genome_files, target_genome_files, annot_files, transmap):
        self.work_dir = os.path.join(args.workDir, 'comparativeAnnotator', gene_set.sourceGenome, gene_set.geneSet)
        self.metrics_dir = os.path.join(args.outputDir, 'metrics')
        self.tx_set_dir = os.path.join(args.outputDir, 'tm_transcript_set')
        self.reference = self.Reference(args, query_genome_files, annot_files, self.work_dir)
        self.transmap = self.TransMap(args, query_genome_files, target_genome_files, annot_files, transmap, self.work_dir)

    class Reference(HashableNamespace):
        """
        The args object that will be passed directly to jobTree
        """
        def __init__(self, args, query_genome_files, annot_files, out_dir):
            self.__dict__.update(vars(args.jobTreeOptions)) 
            self.outDir = out_dir
            self.refGenome = query_genome_files.genome
            self.refFasta = query_genome_files.genome_fasta
            self.sizes = query_genome_files.chrom_sizes
            self.annotationGp = annot_files.gp
            self.gencodeAttributes = annot_files.attributes
            self.mode = 'reference'

    class TransMap(Reference):
        """
        The args object that will be passed directly to jobTree
        """
        def __init__(self, args, query_genome_files, target_genome_files, annot_files, transmap, out_dir):
            super(self.__class__, self).Reference.__init__(self, args, query_genome_files, annot_files, out_dir)
            self.genome = target_genome_files.genome
            self.psl = transmap.psl
            self.refPsl = annot_files.psl
            self.targetGp = transmap.gp
            self.fasta = target_genome_files.fasta
            self.mode = 'transMap'

Attempting to instantiate leads to the error:

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

I have tried different versions such as super(TransMap, self).Reference.__init__ and Reference.__init__, but all give different versions of a NameError. How is this different than the simple case outlined here:

Using super() in nested classes

Community
  • 1
  • 1
Ian Fiddes
  • 2,821
  • 5
  • 29
  • 49

3 Answers3

3

You want this:

super(ComparativeAnnotatorConfiguration.TransMap, self).__init__(...)

This is a consequence of Python's class scoping rules: class variables are not in scope inside methods. This does not change just because your "variable" is itself a class. As far as Python is concerned, that's exactly the same thing.

In Python 3, you can write the far simpler:

super().__init__(...)

This is yet another reason to upgrade.

Kevin
  • 28,963
  • 9
  • 62
  • 81
0

You could use super(ChildClass, self).__init__()

class BaseClass(object):
    def __init__(self, *args, **kwargs):
        pass

class ChildClass(BaseClass):
    def __init__(self, *args, **kwargs):
        super(ChildClass, self).__init__(*args, **kwargs)

Sample Inheritance and initializing parent constructor code :

class Car(object):
    condition = "new"

    def __init__(self, model, color, mpg):
        self.model = model
        self.color = color
        self.mpg   = mpg

class ElectricCar(Car):
    def __init__(self, battery_type, model, color, mpg):
        self.battery_type=battery_type
        super(ElectricCar, self).__init__(model, color, mpg)

car = ElectricCar('battery', 'ford', 'golden', 10)
print car.__dict__

Here's the output:

{'color': 'golden', 'mpg': 10, 'model': 'ford', 'battery_type': 'battery'}
Hassan Mehmood
  • 1,414
  • 1
  • 14
  • 22
-1
super(self.__class__, self).__init__()

will call the __init__ method of parent class.

Shanu Pandit
  • 122
  • 1
  • 10
  • 3
    **Don't do that**. It misbehaves if you subclass the current class. The first argument to `super()` should (almost) always be an import-time constant, not something you figure out by inspecting `self`. – Kevin Feb 05 '16 at 05:07
  • @Kevin, yes i understand that, sorry i didn't mean that way, and yes there are other drawbacks too, of using it, and yes the best way to use directly `super().__init__(...)` but still thanks for making me correct – Shanu Pandit Feb 05 '16 at 05:26