简体   繁体   中英

How to create a dynamically updating list of class instances, satisfying a particular condition? (Python)

I want to create a list of class instances that automatically updates itself following a particular condition on the instance attributes.

For example, I have a list of object of my custom class Person() and I want to be able to generate a list that always contains all the married persons, ie all persons having the attribute 'MAR_STATUS' equal to 'MARRIED'.

Is this possible at all in Python? I have used a C++ precompiler for microsimulations that had a very handy built-in called "actor_set" which did exactly this. But I have no idea of how it was implemented in C++.

Thank you.

List comprehension:

[person for person in people if person.MAR_STATUS == 'MARRIED']

If you need to assign it to a variable and you want that variable to automatically update on every access, you can put this same code in a lambda, a normal function, or, if your variable is a class member, in a property getter.

It is poor form to have "action at a distance" / mutations / side-effects unless it is very carefully controlled.

That said, imperative language will let you do this, if you really want to, as follows. Here we use python's [ property getters and setters ]:

MARRIED_SET = set()
def updateMarriedSet(changedPerson):
    if hasattr(changedPerson,'married') and changedPerson.married==Person.MARRIED:
        MARRIED_SET.add(changedPerson)
    else:
        MARRIED_SET.discard(changedPerson)

class Person(object):
    ...

    @property
    def married(self):
        """The person is married"""
        return self._married

    @married.setter
    def married(self, newStatus):
        self._married = newStatus
        updateMarriedSet(self)

    @married.deleter
    def married(self):
        del self._married
        updateMarriedSet(self)

I can imagine this might, possibly, be useful to ensure accesses to getMarriedPeople() runs in O(1) time rather than amortized O(1) time.

The simple way is to generate the list on the fly eg, as shown in @sr2222's answer.

As an alternative you could call an arbitrary callback each time MAR_STATUS changes. Use __new__ if Person instances are immutable or make MAR_STATUS a property and call registered callbacks in the setter method (see notifications in traits library for a more complex implementation).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM