2

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()?

6
  • Why not define it in the abstract class Behavior ? Commented Jul 20, 2015 at 14:14
  • 1
    "I want f1() to have access to objects and data inside run() without passing them as arguments." - why? Just instance attributes, or other local variables? Could you provide a less abstract example that demonstrates what you're actually trying to achieve? Commented Jul 20, 2015 at 14:16
  • It took me a long time to figure out what you meant. I'd recommend explicitly pointing out that you want f1() to be a C-style macro, not a function. Commented Jul 20, 2015 at 14:24
  • @iAdjunct Sure, actually f1(), f2(), ... are steps of a simulation. Data is partitioned and distributed using mpi and the method run() is implemented differently for each Behavior class. Finally steps f1(), f2(), ... need to access local variables produced by run() Commented Jul 20, 2015 at 14:25
  • No, I mean edit your post and explicitly mention that you want that function to be a macro. That is, of course, assuming that's what you actually mean. Commented Jul 20, 2015 at 14:26

2 Answers 2

2

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?).

Sign up to request clarification or add additional context in comments.

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.