moctarjallo
moctarjallo

Reputation: 1625

How to make a python object return attribute data when called directly

So i want to something like this in Python:

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

    def __repr__(self):
        return self.name, self.age

p = Person('A', 20)

Then hope to call object p directly to get the tuple (self.name, self.age)

But as you can see when you run this program, you get the problem:

TypeError: __repr__ returned non-string (type tuple)

How can have this behavior?

Thanks!

Note: The problem is not specific to the tuple data type; it can be anything, like a pandas dataframe for example. I just want to return some attribute data, whatever type it is.

Upvotes: 6

Views: 4078

Answers (5)

PM 2Ring
PM 2Ring

Reputation: 55499

Another option is to make the class instance callable, and return the desired tuple when called. Eg,

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

    def __repr__(self):
        return f'Person({self.name}, {self.age})'

    def __call__(self):
        return self.name, self.age

p = Person('A', 20)
print(p)
t = p()
print(t, type(t))

output

Person(A, 20)
('A', 20) <class 'tuple'>

Upvotes: 1

guidot
guidot

Reputation: 5333

Since __repr__is supposed to return something, which looks like a valid Python expression, you may choose to implement __str__ instead (even if this implementation would fit both purposes):

def __str__(self):
    return "Person({}, {})".format(self.name, self.age)

Update: If a tuple is actually desired, you simply have to use an non-predefined routine:

def get_attributes(self):
    return self.name, self.age

Upvotes: 0

scharette
scharette

Reputation: 10007

As the error suggest, your __repr__ must return a string

def __repr__(self):
    return self.name + str(self.age)

Now, if your goal is to write a custom way of representing your object as a tuple, what you are looking for is _iter__ instead,

def __iter__(self):
    yield self.name
    yield self.age

p = Person('A', 20)
print(tuple(p))
>>>>('A', 20)

Upvotes: 5

chepner
chepner

Reputation: 532268

You can make Person iterable:

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

    def __iter__(self):
        yield self.name
        yield self.age

name, age = p

Upvotes: 1

maor10
maor10

Reputation: 1794

Adding on, maybe you're looking for a namedtuple- it would give you exactly what you're looking for:

from collections import namedtuple
Person = namedtuple('Person', 'name, age')

So you'd basically get a tuple every time you created a person (you'd get unpacking and such)- however, the object person will be immutable, not sure if that's what you're shooting for here.

Upvotes: 0

Related Questions