There's no easy way to do this.
The concept of a pivot table (already mentioned by another answer) is basically what you are looking for, except that pivot tables require you to know the names of the columns you wish to use. Clearly this is a problem when you want to exploit the power of such a table design!
In my previous life, I just settled on X number of columns, like 20-30, and if they didn't exist, then the row set included a bunch of null values. No big deal.
select piv.name,
max(case piv.a_name when 'Gender' then piv.a_value else null end) as Gender,
max(case piv.a_name when 'Age' then piv.a_value else null end) as Age,
max(case piv.a_name when 'Hobby' then piv.a_value else null end) as Hobby
from
(select p.name as name, pa.name as a_name, pa.value as a_value
from person p, personattribute pa
where p.id = pa.personid) piv
group by piv.name
This would generate output like so:
name | gender | age | hobby
-----------+--------+-----+---------
Bob Swift | Male | | Reading
John Doe | Male | 30 |
(2 rows)
Which is pretty damned close to what you are looking for. I would leave the rest of it up to your application-layer.
I also highly recommend that you include the attribute NAME as part of the return value, to provide context to the VALUEs.
These types of so-called Entity-Attribute designs often end up having to rely on a combination of server-specific functions, stored procedures, and hard-coded queries.