6

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.

10
  • Do you want (self.name, self.age) as a string, or as an actual tuple? Commented Aug 3, 2018 at 12:18
  • Yes. I want i as an actual tuple. Not a string. Commented Aug 3, 2018 at 12:21
  • Is that the full definition of your actual Person class, or does it also have other methods? If you don't need methods, you could use a namedtuple, or the new dataclass. Commented Aug 3, 2018 at 12:21
  • Well this is a simplified model of my problem. It is not specific to the tuple datatype but can be anything like a dataframe for example. The importance is the concept i want to discover: How to actually return attribute data when the object is called directly (rather than returning its memory address) Commented Aug 3, 2018 at 12:29
  • 1
    @mctrjalloh Ok but what do you mean by called directly, what is that ? Commented Aug 3, 2018 at 12:30

5 Answers 5

5

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)
Sign up to request clarification or add additional context in comments.

5 Comments

I want to return the tuple itself, or any data that is available in the object attributes. But not the string representation. That was just an attempt.
@mctrjalloh Just want to make sure I correctly understood your problem, could you please give more detail on what you mean by called directly. Do you want to return a tuple when you use p() ?
Now let's say rather than being a tuple it was a pandas dataframe i wanted to return...
@mctrjalloh You're still not answering what you mean by called directly.
NO. just by typing p without the parentheses
1

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

3 Comments

Alternatively, def __iter__(self): yield from (self.name, self.age)
Depends on what you mean. A Person iterator yields its name and age in succession; what you do with that is a separate issue.
@mctrjalloh If you want a dataframe, why use a class at all? Just make a function that takes the args you want and returns the desired dataframe.
1

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'>

Comments

0

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.

2 Comments

This proposal no longer holds as soon as a real method is required, like is_of_age().
Again, it depends what he's looking for. "Then hope to call object p directly to get the tuple (self.name, self.age)"
0

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

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.