ilciavo
ilciavo

Reputation: 3494

How to include macros in Python?

This is a similar question but my goal is not performance but readability.

Let's say I have different Behaviours, and they share a repeated function f1().

from abc import ABCMeta, abstractmethod

class Behavior:
    __metaclass__ = ABCMeta
    @abstractmethod 
    def run(self):
        pass

class Behavior1(Behavior):
    def __init__(self, data):
        self.data = data

    def run(self):
        def f1():
            print(self.data*localVar)

        localVar = 1.
        f1()

class Behavior2(Behavior):
    def __init__(self, data):
        self.data = data

    def run(self):
        def f1():
            print(self.data*localVar)

        localVar = 2.
        f1()

class Behavior3(Behavior):
    def __init__(self, data):
        self.data = data

    def run(self):
        def f1():
            print(self.data*localVar)

        localVar = 3            
        f1()

I want f1() to have access to instance attributes and local variables inside run() without passing them as arguments.

Probably I can implement that inside Behavior but I don't have access to localVar.

from abc import ABCMeta, abstractmethod

class Behavior:
    __metaclass__ = ABCMeta
    @abstractmethod 
    def run(self):
        pass

    def f(self):
        print(self.data*localVar)

class Behavior1(Behavior):
    def __init__(self, data):
        self.data = data

    def run(self):
        def f1():
            print(self.data*localVar)

        localVar = 1.
        f1()
        self.f()

class Behavior2(Behavior):
    def __init__(self, data):
        self.data = data

    def run(self):
        def f1():
            print(self.data*localVar)

        localVar = 2.
        f1()
        self.f()

class Behavior3(Behavior):
    def __init__(self, data):
        self.data = data

    def run(self):
        def f1():
            print(self.data*localVar)

        localVar = 3            
        f1()
        self.f()

Is there any pythonic or OOP way of writting a C-Style macro for f1()?

Upvotes: 2

Views: 593

Answers (2)

Slava
Slava

Reputation: 160

What you actually want sounds like "access to outer scope variables" which is not global.

If you use python3.x, you should look up the nonlocal keyword.

If you use python2.x, try using a mutable object as a wrapper to your object.

Actually my answer is based on this one.

Upvotes: 0

iAdjunct
iAdjunct

Reputation: 2979

Macros are not an inherent construct in python since there's no preprocessor like in C++ to use.

As such, anything you do to allow you to only write the code once will have to be done...

  • Outside of python (i.e. you manually use gcc's preprocessor); or

  • By using debugging information in python (i.e. you deconstruct the callstack)

The former is a pain in the butt, but is doable.

The latter is also a pain in the butt, but is also doable.

However, since your goal is to increase readability, neither of these options are good because anybody accustomed to python will have absolutely no idea what you're doing. Be very careful when porting language constructs from other languages into python.

If your function needs to modify local variables, then you'll have to write the same lines of code in every place.

If it just needs to use them, I strongly recommend just passing arguments - or rethinking your design and need for many derived classes all doing roughly the same thing in one function (i.e. what if you broke that "function" into several pieces of the function and let derived classes only override the ones they want?).

Upvotes: 2

Related Questions