Pythonic style

Stavros Macrakis macrakis at alum.mit.edu
Sun Sep 20 18:34:52 EDT 2020


I'm trying to improve my Python style.

Consider a simple function which returns the first element of an iterable
if it has exactly one element, and throws an exception otherwise. It should
work even if the iterable doesn't terminate. I've written this function in
multiple ways, all of which feel a bit clumsy.

I'd be interested to hear thoughts on which of these solutions is most
Pythonic in style. And of course if there is a more elegant way to solve
this, I'm all ears! I'm probably missing something obvious!

Thanks,

              -s

def firsta(iterable):
    it = iter(iterable)
    try:
        val = next(it)
    except StopIteration:
        raise ValueError("first1: arg not exactly 1 long")
    try:
        next(it)
    except StopIteration:
        return val
    raise ValueError("first1: arg not exactly 1 long")

def firstb(iterable):
    it = iter(iterable)
    try:
        val = next(it)
    except StopIteration:
        raise ValueError("first1: arg not exactly 1 long")
    try:
        next(it)
    except StopIteration:
        return val
    else:
        raise ValueError("first1: arg not exactly 1 long")

def firstc(iterable):
    it = iter(iterable)
    try:
        val = next(it)
    except StopIteration:
        raise ValueError("first1: arg not exactly 1 long")
    try:
        next(it)
        raise ValueError("first1: arg not exactly 1 long")
    except StopIteration:
        return val

def firstd(iterable):
    it = iter(iterable)
    try:
        val = next(it)
    except StopIteration:
        raise ValueError("first1: arg not exactly 1 long")
    for i in it:
        raise ValueError("first1: arg not exactly 1 long")
    return val

def firste(iterable):
    it = iter(iterable)
    try:
        good = False
        val = next(it)
        good = True
        val = next(it)
        good = False
        raise StopIteration   # or raise ValueError
    except StopIteration:
        if good:
            return val
        else:
            raise ValueError("first1: arg not exactly 1 long")

def firstf(iterable):
    n = -1
    for n,i in enumerate(iterable):
        if n>0:
            raise ValueError("first1: arg not exactly 1 long")
    if n==0:
        return i
    else:
        raise ValueError("first1: arg not exactly 1 long")


More information about the Python-list mailing list