Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python generator function/object naming convention

I have a few logical processes implemented in the same class. A class instance get a generator for each process, and run() advances said generators. In my case generators don't end.

How would you call foo_function and foo_object in the code below

class C(threading.Thread):
    def foo_function(self):
        """ generator *function*,
            logical process foo """
        while True:
            # some state checks
            if self.some_attr:
                # side-effects here
                pass
            yield

    def __init__(self):
        # generator *object*
        # i.e. process instance
        self.foo_object = self.foo_function()  # <- here

    def run(self):
        while True:
            next(self.foo_object)
            next(self.another_object)
            if xxx:
                next(self.yet_another_object)

Typical processes are discovery, authentication, watchdog, etc.

How can I name function that defines the generator and the attribute that contains generator object in a sensible way?

Finally just for the kicks, same name name would be insane, right?

class C:
    def foo(self):
        yield 1; yield 2
    def __init__(self):
        self.foo = self.foo()

c = C()            
type(C.foo) is function
type(c.foo) is generator
like image 296
Dima Tisnek Avatar asked Nov 05 '14 10:11

Dima Tisnek


People also ask

What are generator objects in Python?

Python generators are a simple way of creating iterators. All the work we mentioned above are automatically handled by generators in Python. Simply speaking, a generator is a function that returns an object (iterator) which we can iterate over (one value at a time).

Why should function names be lowercase?

Function names should be lowercase, with words separated by underscores as necessary to improve readability.

How do you access the generator object in Python?

You need to call next() or loop through the generator object to access the values produced by the generator expression. When there isn't the next value in the generator object, a StopIteration exception is thrown. A for loop can be used to iterate the generator object.


2 Answers

You could make the members containing generators be created automatically from the function's name, using some kind of covention designed by your self. For instance, in my convention all generators will be contained by a member called: <function_name>_gen.

I would call the function name as its responsability: discovery, authentication and watchdog are good names. So you only need a way to automatically set: self.discovery_gen, self.authentication_gen and self.watchdog_gen.

Code sample:

class C:

    def discovery(self):
        yield 1; yield 2

    # Register all the functions for wich you want to have a generator
    # object.
    REGISTERED_GEN_FUNCTIONS = [discovery]

    def __init__(self):

        for func in self.REGISTERED_GEN_FUNCTIONS:
            name = func.__name__
            # All generators objects will be called <function_name>_gen.
            setattr(self, "{0}_gen".format(name), getattr(self, name)())

a = C()
for i in a.discovery_gen:
    print(i)

Ouput

>>> 1
>>> 2 
like image 149
Raydel Miranda Avatar answered Oct 16 '22 09:10

Raydel Miranda


If the generators are only accessed inside the run method you can do something like this:

class C:
    def a_process(self):
        while True: yield

    def another_process(self):
        while True: yield

    def run(self):
        # Use itertools.izip in python 2
        for _ in zip(a_process(), another_process()):
            pass

Here, zip and the for loop will create and advance the generators automatically. This way, you don't need to keep track of them.

If you need access to the generators outside the run method, you can create an ordered dictionary of generators (in case the generators need to be advanced in a defined order):

from collections import OrderedDict

class C:
    # Processes here

    def __init__(self):
        self.generators = OrderedDict()
        for gn in ('a_process', 'another_process'):
            self.generators[gn] = getattr(self, gn)()

    def run(self):
        while True:
            for g in self.generators.values():
                next(g)
like image 38
parchment Avatar answered Oct 16 '22 10:10

parchment