[Tutor] Playing with generators

Mats Wichmann mats at wichmann.us
Wed Aug 10 13:12:52 EDT 2022


On 8/10/22 05:32, Leam Hall wrote:
> I'm wondering if there's a way to combine "make_person" with the
> generator in "for fname, peep in". Even if it can be done, should it be
> done? Or would the code be overly complex?
> 
> The goal is to parse a group of data, and create a dict where the value
> is an object created from the data, and the key is an attribute of the
> object itself.
> 
> 
> class Person():
>     def __init__(self, data = {}):

don't do this: don't use a mutable default argument

>         self.fname = data.get('fname', 'fred')
>         self.lname = data.get('lname', 'frank')
> 
> data = [
>     { 'fname':'Wilbur', 'lname':'Lefron' },
>     { 'fname':'Al', 'lname':'Lefron' },
>     { 'fname':'Jo', 'lname':'Franco' },
>     { 'fname':'Mon', 'lname':'Pascal' },
>     { 'fname':'Gray', 'lname':'Webb-Marston'},
>     ]
> 
> def make_person(data):
>     ps = ( Person(d) for d in data)
>     return ps
>         peeps = {}
> 
> for fname, peep in ( (p.fname, p) for p in make_person(data) ):
>     peeps[fname] = peep
> 
> 
> for person in peeps.values():
>     print(person.lname)
> 

Sorry, Leam, it's a little hard to figure out what you're looking for
here.  Yes, you can combine things - the key (IMHO) is to make
make_person return the right thing, so you don't get so convoluted
unpacking things.  I'd make make_person the generator, too, and use a
dict comprehension.  Here's a quick rewrite that I *think* does what I
think you are after. Using a dataclass gets you some stuff "for free"
and is useful here since as presented, it *is* only a data class.  "Nice
printing" is one of the things you get for free. The other "trick" in
here is that since each entry in data is a dict, you can use dict
unpacking when creating the dataclass instance, so the args will match
the attributes you define.


from dataclasses import dataclass

@dataclass
class Person():
    fname: str = "fred"    # assuming you really want these as the
defaults....
    lname: str = "frank"


data = [
    {"fname": "Wilbur", "lname": "Lefron"},
    {"fname": "Al", "lname": "Lefron"},
    {"fname": "Jo", "lname": "Franco"},
    {"fname": "Mon", "lname": "Pascal"},
    {"fname": "Gray", "lname": "Webb-Marston"},
]


def make_person(data):
    """ Creates Person instances, yielding a lookup key and the instance."""
    for d in data:
        p =  Person(**d)
        yield p.fname, p


peeps = {k: v for k, v in make_person(data)}

print(peeps)


More information about the Tutor mailing list