0

Really simple question here. After ben is created, is there anyway I can call ben[0] to call name and ben[1] to call age?

i'm wondering if there is a way to access these attributes as a list.

class People():
    def __init__(self, name, age):

ben=People("ben", "10")
3
  • That entirely depends on what the rest of your class definition and the init method says... Commented Oct 25, 2013 at 21:50
  • 3
    It is more logical to use attributes ben.name and ben.age. If you insist on using indexing, you should implement __getitem__ on the class. Commented Oct 25, 2013 at 21:50
  • @Ben: Not many 10-year-olds have thousands of rep points; nice job. :) Commented Oct 25, 2013 at 22:22

3 Answers 3

5

It sounds like you're trying to build a namedtuple:

>>> import collections
>>> People = collections.namedtuple('People', 'name age')
>>> ben = People("ben", 10)
>>> ben.name
'ben'
>>> ben[0]
'ben'

If you want additional functionality in your class beyond just having attributes, you can just inherit from the namedtuple instead of using it directly:

>>> class People(collections.namedtuple('People', 'name age')):
...     def __str__(self):
...         return self.name.title() + '!'
>>> ben = People("ben", 10)
>>> print(ben)
Ben!
>>> ben
People(name='ben', age=10)
>>> ben.name
'ben'
>>> ben[0]
'ben'
Sign up to request clarification or add additional context in comments.

Comments

4
class People(object):     
    def __init__(self,name,age):
        self.stuff = [name,age]
    def __getitem__(self, arg):
        return self.stuff[arg]

and here it is

>>> b = People("ben",10)
>>> b[0]
'ben'
>>> b[1]
10
>>>

you could also do something like

class People(object):     
    def __init__(self,name,age):
        self.stuff = {'name':name,'age':age}
    def __getitem__(self, arg):
        return self.stuff[arg]

b = People("asd",10)
b['age']
b['name']

1 Comment

no __getitem__ is called when you access it with square brackets ... __init__ creates a list
1

What you want to do with your class is impossible, because its attributes have no inherent order, because they're stored in a dict, so there is no reasonable way to map ben[0] to ben.name instead of to ben.age.

But you can modify the class in a few different ways to make it reasonable:

  • Pick an order and store it in a list (e.g., in a class attribute). Then, your __getitem__ just calls getattr(self, self._fields[index]).
  • Pick an order that you can define programmatically (e.g., sorted order).
  • Use a metaclass to make your class store its attributes in an OrderedDict, in which case the order in which you assign them in __init__ is their order. So it's just self.__dict__.values()[index].
  • Use __slots__ instead of a dict for your attributes.

If you look at the source for collections.namedtuple, you can see that it's using a combination of these: there's a class attribute named _fields to store the field names, while the field values are stored in the tuple that it inherits from, and it then defines __dict__ as a @property that puts them together an OrderedDict on the fly. This is probably far more clever than you need to be. And, if you do need to be this clever, just use or inherit from a namedtuple in the first place.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.