1

I have implemented an iterable class in python3.8 following this post implementing the weakref() function in order to be able to delete elements of the class, as explained in the post's accepted answer.

The problem is that if I populate the iterable class inside a function I am no longer able to iterate over its elements:

#! /usr/bin/env python3.8

import sys
import weakref
# from memory_profiler import profile

# IN = "/home/enrico/Dropbox/NY/asilo_variant/inputs/merged.idter_M.norm.PASS.filtered.head1k.VEPoutput.vcf"

a = [ "a", "b", "c", "d" ]

class VEPh_iterator(type):
    def __iter__(self):
        return self.classiter()

class VEPh:
    '''
        this stores VEP header and relative column numbers and chars
    '''
    __metaclass__ = VEPh_iterator
    by_id = {}

    def __init__(self, id, column_number):
        self.id = id
        # self.by_id[id] = self
        self.by_id[id] = weakref.ref(self)
        self.column_number = column_number

    @classmethod
    def classiter(cls):
        # return iter(cls.by_id.values())
        return (i for i in (i() for i in cls.by_id.values()) if i is not None)

def readVCF( ):
    name_dict = {}
    for i,s in enumerate(a) :
        name_dict.update({ i : s })
        name_dict[i] = VEPh( s, i )

if __name__ == "__main__" :
    readVCF( )
    for v in VEPh.classiter():
        print( "  -  " + v.id + " :    " + str(v.column_number) )

calling it has an empty OUT:

python3.8 /home/enrico/Dropbox/NY/asilo_variant/asilo_variant.stackoverflow.py

### NO STDOUT

if modified removing weakref() it works:

#! /usr/bin/env python3.8

import sys
import weakref
# from memory_profiler import profile

# IN = "/home/enrico/Dropbox/NY/asilo_variant/inputs/merged.idter_M.norm.PASS.filtered.head1k.VEPoutput.vcf"

a = [ "a", "b", "c", "d" ]

class VEPh_iterator(type):
    def __iter__(self):
        return self.classiter()

class VEPh:
    '''
        this stores VEP header and relative column numbers and chars
    '''
    __metaclass__ = VEPh_iterator
    by_id = {}

    def __init__(self, id, column_number):
        self.id = id
        self.by_id[id] = self
        # self.by_id[id] = weakref.ref(self)
        self.column_number = column_number

    @classmethod
    def classiter(cls):
        return iter(cls.by_id.values())
        # return (i for i in (i() for i in cls.by_id.values()) if i is not None)

def readVCF( ):
    name_dict = {}
    for i,s in enumerate(a) :
        name_dict.update({ i : s })
        name_dict[i] = VEPh( s, i )

if __name__ == "__main__" :
    readVCF( )
    for v in VEPh.classiter():
        print( "  -  " + v.id + " :    " + str(v.column_number) )

calling it works:

python3.8 /home/enrico/Dropbox/NY/asilo_variant/asilo_variant.stackoverflow.py 
  -  a :    0
  -  b :    1
  -  c :    2
  -  d :    3

I guess the problem is that weakref() is somehow lost between functions, but how can I make it callable by outer functions?

cccnrc
  • 1,195
  • 11
  • 27

0 Answers0