0

I have the following code:

class Personne:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __getitem__(self, *args):
        keys = list(*args)
        return [self.__dict__[key] for key in keys]


if __name__ == '__main__':
    p = Personne('A', 20)
    # age = p['age']
    # print(age)
    # name = p['name']
    # print(name)
    name, age = p['name', 'age']
    print(name, age)

The uncommented part works fine, but the there is a problem in the commented code. How can i achieve the desired behaviour, which is to get attribute values based on arguments (can be one or many) passed to the getitem method.

Thanks.

moctarjallo
  • 1,479
  • 1
  • 16
  • 33

2 Answers2

3

The problem with passing passing only one string is in that when you call p['age'], the type of *args is a string and therefore list(*args) becomes ['a', 'g', 'e']. When you pass both 'age' and 'name', the *args is interpreted as a tuple and you get the appropriate result. One way to handle this issue could be to check the type of the *args parameter in the getitem(self, *args) method. The following modification would solve the issue you are facing (Python 3), though you might want to clean it a bit.

class Personne:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __getitem__(self, *args):
        if isinstance(*args, str):
            return self.__dict__[str(*args)]
        keys = list(*args)
        return [self.__dict__[key] for key in keys]


if __name__ == '__main__':
    p = Personne('A', 20)
    age = p['age']
    print(age)
    name = p['name']
    print(name)
    name, age = p['name', 'age']
    print(name, age)
    
    
CONSOLE OUTPUT : 

20
A
A 20
Bolat
  • 369
  • 1
  • 8
1

As I'm sure you're aware, currently your code returns an error because keys = list(*args) treats the string age as an iterable and tries to look for a, g, and e in self.__dict__. You could therefore check the type of the argument given to __getitem__ and perform the appropriate transformation of args to get the keys to return:

class Personne:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __getitem__(self, args):
        if isinstance(args, str):
            keys = [ args ] # args is a string
        else:
            keys = list(args) # args is a tuple
        return [self.__dict__[key] for key in keys]

Output will be a list of values from self.__dict__.

i alarmed alien
  • 9,412
  • 3
  • 27
  • 40
  • Your code returned a list every time even for one output. But @Levi Levi solved it for me. Thanks. – moctarjallo Aug 07 '18 at 21:46
  • 1
    Yes, it will do so -- see the return statement: `return [self.__dict__[key] for key in keys]`. I tend to prefer functions to return the same data type every time so that I can use the same code to handle the return without having to do another type-check. Specify your *input*, *problem*, and *expected output* more clearly, and people can help more effectively. – i alarmed alien Aug 07 '18 at 21:57