root
root

Reputation: 80336

Python Class design: attributes

I constructed a class:

class Foo (object):
      def __init__(self,List):
          self.List=List
      @property
      def numbers(self):
          L=[]
          for i in self.List:
              if i.isdigit():
                 L.append(i)
          return L
      @property
      def letters(self):
          L=[]
          for i in self.List:
              if i.isalpha():
                 L.append(i)
          return L

>>> inst=Foo(['12','ae','45','bb'])
>>> inst.letters
['ae', 'bb']
>>> inst.numbers
['12', '45']

How can I add attributes so I could do inst.numbers.odd that would return ['45']?

Upvotes: 2

Views: 133

Answers (2)

mgilson
mgilson

Reputation: 309821

Here's a silly example:

class mylst(list):
    @property
    def odd(self):
        return [ i for i in self if int(i)%2 == 1 ]

class Foo(object):
    def __init__(self,lst):
        self.lst = list(lst)

    @property
    def numbers(self):
        return mylst( i for i in self.lst if i.isdigit() )

a = Foo(["1","2","3","ab","cd"])
print(a.numbers)
print(a.numbers.odd)

Basically, we just subclass list and add a property odd which returns another list. Since our structure is a subclass of list, it is virtually indistinguishable from the real thing (Horray duck typing!). mylst.odd could even return a new instance of mylst if you wanted to be able to filter it again (e.g. a.numbers.odd.in_fibinocci )

Upvotes: 2

Pierre GM
Pierre GM

Reputation: 20329

Your numbers property returns a list, so a numbers.odd won't work.

However, you could follow a workflow like:

  • define a small class Numbers, that would define two properties even and odd For example, Numbers could take a list as argument of its __init__, the even property would return only the even number of this list [i for i in List if int(i)%2 == 0] (and odd the odd ones)...

  • create an instance of Numbers in your Foo.numbers property (using your Foo.List to initialize it) and return this instance...

Your Numbers class could directly subclass the builtin list class, as suggested. You could also define it like

class Numbers(object):
    def __init__(self,L):
        self.L = L
    @property
    def even(self):
        return [i for i in self.L if not int(i)%2]
    def __repr__(self):
        return repr(self.L)

Here, we returning the representation of Numbers as the representation of its L attribute (a list). Fine and dandy until you want to append something to a Numbers instance, for example: you would have to define a Numb.append method... It might be easier to stick with making Numbers a subclass of list:

 class Numbers(list):
    @property
    def even(self):
        ...

Edited: corrected the // by a %, because I went too fast and wasn't careful enough

Upvotes: 3

Related Questions