Iterate through class members in order of their declaration

后端 未结 3 646
南旧
南旧 2020-12-15 08:51

I got this problem writing a little GUI lib that maps classes to simple table views. Every class member of a certain type = column, and order of columns is important. But...

相关标签:
3条回答
  • 2020-12-15 09:00

    It's possible in Python3, through the use of PEP3115 which allows you to override the dict type in the metaclass while the class is being constructed (eg. to use an OrderedDict which tracks the insertion order). Here's an implementation of this approach:

    class OrderedMeta(type):
        @classmethod
        def __prepare__(metacls, name, bases): 
            return OrderedDict()
    
        def __new__(cls, name, bases, clsdict):
            c = type.__new__(cls, name, bases, clsdict)
            c._orderedKeys = clsdict.keys()
            return c
    
    class Person(metaclass=OrderedMeta):
        name = None
        date_of_birth = None
        nationality = None
        gender = None
        address = None
        comment = None
    
    for member in Person._orderedKeys:
        if not getattr(Person, member):
            print(member)
    

    In Python2, it's a lot more tricky. It would be achievable with something fairly hacky like introspecting the source, and working out the definition order from the AST, but that's probably a lot more trouble than it's worth.

    0 讨论(0)
  • 2020-12-15 09:15

    If all you need is an aggregate of variables, perhaps you should use a namedtuple instead. It also maintains the order of the fields (as it's a tuple).

    from collections import namedtuple
    Person = namedtuple('Person', ('name',
                                   'data_of_birth',
                                   'nationality',
                                   'gender',
                                   'address',
                                   'comment'))
    print Person._fields
    
    0 讨论(0)
  • 2020-12-15 09:22

    Ok, it's not an answer per se but a workaround that only works in the context of original question ("Every class member [which is an instance] of a certain type = column, and order of columns is important"). The solution is to introduce a class variable _count into the CertainType class, and increment it at every instantiation. After that all class members of the CertainType are packed into a list which is sorted using key=attrgetter('_count')

    P.S. Omitting that "which is an instance" part was a mistake on my part and it has limited range of solutions considerably. Sorry for that.

    0 讨论(0)
提交回复
热议问题