Python equivalent of Common Lisp Macros?

Discussion in 'Python' started by dpapathanasiou, Nov 26, 2008.

  1. I'm using the feedparser library to extract data from rss feed items.

    After I wrote this function, which returns a list of item titles, I
    noticed that most item attributes would be retrieved the same way,
    i.e., the function would look exactly the same, except for the single
    data.append line inside the for loop.

    In CL, I could simply write a macro, then replace the data.append line
    depending on which attribute I wanted.

    Is there anything similar in Python?

    Here's the function:

    def item_titles (feed_url):
    """Return a list of the item titles found in this feed url"""
    data = []
    feed = feedparser.parse(feed_url)
    if feed:
    if len(feed.version) > 0:
    for e in feed.entries:
    data.append(e.title.encode('utf-8'))
    return data
     
    dpapathanasiou, Nov 26, 2008
    #1
    1. Advertisements

  2. No, there are no macros. Yet it has - amongst other options, such as
    callbacks - decorators, that would allow you to write your code like this:

    def items (feed_url):
    feed = feedparser.parse(feed_url)
    if feed:
    if len(feed.version) > 0:
    for e in feed.entries:
    yield e


    titles = []
    other_things = []
    for item in items(url):
    titles.append(item.title.encode('utf-8'))
    other_things.append(item.other_thing)

    Diez
     
    Diez B. Roggisch, Nov 26, 2008
    #2
    1. Advertisements

  3. dpapathanasiou

    Chris Rebert Guest

    Yes, use higher-order functions. See below.
    Replace previous line with:
    def item_titles(feed_url, attr_getter):
    Replace previous line with:
    data.append(attr_getter(e))
    Example usage:

    def title_getter(entry):
    return entry.title.encode('utf-8')

    titles = item_titles("some feed url here", title_getter)

    As I'm not familiar with feedparser, you might want to move where the
    ..encode() takes place, but you get the idea.

    Cheers,
    Chris[/QUOTE]
     
    Chris Rebert, Nov 26, 2008
    #3
  4. Something like this?

    def item_attrs (feed_url, attr):
    """Return a list of the item titles found in this feed url"""
    data = []
    feed = feedparser.parse(feed_url)
    if feed:
    if len(feed.version) > 0:
    for e in feed.entries:
    data.append(getattr(e, attr).encode('utf-8'))
    return data

    You're not making it clear how the data.append... line changes so it's
    hard to know exactly.
     
    Arnaud Delobelle, Nov 26, 2008
    #4
  5. No macros -- need the whole "code as data" paradigm which doesn't exist
    in python.

    The pythonic way to create the sort of abstraction you're looking for
    would be to use the *attr functions and either a map of attribute
    identities or inspect the attributes from the objects.

    Some UNTESTED code...

    def extract_entry(e, attrs=['title', 'datetime', 'article']):
    out = []
    for attr in attrs:
    assert hasattr(e, attr)
    out.append(getattr(e, attr))
    return out

    Using the inspect module would give an even more generic function, but
    with more complex code of course.

    Then your code would look more like:

    def items(feed_url):
    feed = feedparser.feed(feed_url)
    if feed and len(feed) > 0:
    return [extract_entry(entry) for entry in feed.entries]

    Of course, I'm making liberal assumptions about what you're looking for
    in your ouput here... but it's just an example, not a full
    solution. YMMV. Hope it helps. :)
     
    J Kenneth King, Nov 26, 2008
    #5
  6. Thanks; this is exactly what I was looking for.
     
    dpapathanasiou, Nov 26, 2008
    #6
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.