【问题标题】:Add attribute to class list to return all objects with specific attribute将属性添加到类列表以返回具有特定属性的所有对象
【发布时间】:2014-08-11 03:56:30
【问题描述】:

我有以下问题:

让我们开始吧!

假设我有一个具有一些基本属性的类 Person:

class Person(object):
    def __init__(self, name=None, gender=None, single=None):
        self.name=name
        self.gender=gender
        self.single=single

我创建了一个名为 Dating 的列表类,它将包含所有 Person 对象

class Dating(object):
    def __init__(self):
        self.members=[]

My_People=Dating()

My_People.members.append(Person("Jack","Male",False))
My_People.members.append(Person("Jill","Female",True))
My_People.members.append(Person("George","Male",True))
My_People.members.append(Person("Sandy","Female",False))

对,那么问题出在哪里?

是否可以通过创建某种属性来为列表类分配一个属性以访问 My_People 列表的单个成员:

My_People.members.singles

这样会返回一个具有 single == True 属性的 Person 对象列表吗?

感谢所有帮助。 (顺便说一句,我以前对 Python 的经验很少)

【问题讨论】:

  • 停止调用__init__ 方法,无需您的帮助,它确实可以这样工作)
  • 已编辑问题。现在好点了吗?
  • 有人知道为什么这被否决了吗?反馈很有用,因此我可以编辑问题并希望解决问题

标签: python list class filter attributes


【解决方案1】:

如果您不受 My_People.members.singles 语法的约束,您可以更简单地执行此操作:

class Dating(object):

    def __init__(self):
        self.members = []

    @property
    def single_members(self):
        return [m for m in members if m.single]

现在您可以通过以下方式访问列表:

My_People.single_members

【讨论】:

    【解决方案2】:

    怎么样:

    class Attribute(list):
        def __getattr__(self, attr):
            if attr == 'single':
                return [person for person in self if person.single]
            raise AttributeError()
    
    class Person(object):
        def __init__(self, name=None, gender=None, single=None):
            self.name = name
            self.gender = gender
            self.single = single
    
        def __repr__(self):
            return 'Person({person.name}, {person.gender}, {person.single})'.format(person=self)
    
    
    class Dating(object):
        members = Attribute()
    
    
    My_People = Dating()
    
    My_People.members.append(Person("Jack", "Male", False))
    My_People.members.append(Person("Jill", "Female", True))
    My_People.members.append(Person("George", "Male", True))
    My_People.members.append(Person("Sandy", "Female", False))
    
    >>> print My_People.members.single
    [Person(Jill, Female, True), Person(George, Male, True)]
    >>> print My_People.members
    [Person(Jack, Male, False), Person(Jill, Female, True), Person(George, Male, True), Person(Sandy, Female, False)]
    

    【讨论】:

      【解决方案3】:

      要添加这样的属性,您必须子类列表类型:

      class FilterableList(list):
          def __getattr__(self, name):
              # assume non-existing attributes are boolean filters
              return [elem for elem in self if getattr(elem, name)]
      

      请注意,这并不是那么灵活;只有True 值是通过这种方式找到的。您可以赋予属性名称更多含义,但通常无论如何您都希望在Dating 类上执行此操作,并使用方法更有表现力地过滤您的数据。

      演示:

      >>> class Person(object):
      ...     def __init__(self, name, gender, single):
      ...         self.name=name
      ...         self.gender=gender
      ...         self.single=single
      ...     def __repr__(self):
      ...         return 'Person({name!r}, {gender!r}, {single!r})'.format(**vars(self))
      ... 
      >>> class FilterableList(list):
      ...     def __getattr__(self, name):
      ...         # assume non-existing attributes are boolean filters
      ...         return [elem for elem in self if getattr(elem, name)]
      ... 
      >>> members = FilterableList([Person("Jack","Male",False), Person("Jill","Female",True), Person("George","Male",True), Person("Sandy","Female",False)])
      >>> members
      [Person('Jack', 'Male', False), Person('Jill', 'Female', True), Person('George', 'Male', True), Person('Sandy', 'Female', False)]
      >>> members.single
      [Person('Jill', 'Female', True), Person('George', 'Male', True)]
      

      【讨论】:

      • 感谢您,这正是我所需要的,我喜欢您解决方案的灵活性。另外,我以前从未使用过 repr,它也确实会派上用场!
      【解决方案4】:

      首先,您不需要在 My_People 实例上调用 __init__(),Python 会自动执行此操作。

      对于这个问题,您可以从 list 继承并添加一个 singles 属性,如下所示:

      class Person(object):
          def __init__(self, name=None, gender=None, single=None):
              self.name=name
              self.gender=gender
              self.single=single
      
      class Dating(list):
          @property
          def singles(self):
              return [person for person in self if person.single ]
      
      My_People=Dating()
      
      My_People.append(Person("Jack","Male",False))
      My_People.append(Person("Jill","Female",True))
      My_People.append(Person("George","Male",True))
      My_People.append(Person("Sandy","Female",False))
      
      print My_People.singles
      

      【讨论】:

      • 太好了,我明白了。因此,每次要访问 My_People.singles 时都必须遍历 My_People 列表,并且没有直接的方法可以使用 single==True 属性调用这些对象。
      • 我喜欢从列表子类化的建议,非常方便
      • @user1083734 您当然可以保存.singles 返回的结果,以避免在每次访问时遍历列表。
      • 但是每次 My_People 列表发生变化时,我是否必须通过再次调用该函数来更新单打结果?
      猜你喜欢
      • 2015-10-21
      • 1970-01-01
      • 2022-01-01
      • 2016-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多