0

I have the following:

class ComplicatedClass(object):
    def _init__(self):
        self.useful_member = ...

    def method(self):
        M = self.useful_member
        ...

    def method2(self):
        M = self.useful_member
        ...

    def method3(self):
        M = self.useful_member
        ...

I am using the useful member a lot in various methods, so instead of writing the long and cumbersome self.useful_member each time, I am assigning it to the short variable name M.

Is there a way to avoid re-doing M = self.useful_member for each method?

R S
  • 11,359
  • 10
  • 43
  • 50
  • can you post a more complete example please? are all the methods similar, or is the only similarity the first line? – Kos Mar 21 '18 at 13:05
  • Only the first line. – R S Mar 21 '18 at 13:06
  • Maybe you're looking for something like this [https://stackoverflow.com/questions/68645/static-class-variables-in-python?rq=1]? – Romzie Mar 21 '18 at 13:12
  • 1
    I have to wonder what the various methods are doing that they all make enough references to `self.useful_member` to make defining the local worthwhile in the first place? I don't think there is going to be a solution that is better than the boilerplate. – chepner Mar 21 '18 at 13:50
  • @Romzie - static variables still require me to prefix `M` with the class name or `self`, no? – R S Mar 21 '18 at 14:07
  • @RS indeed, not the best option. – Romzie Mar 21 '18 at 14:17

1 Answers1

0

I believe you are looking for something like

def quick_assignment(varName, varValue):
    def decorator(func):
        def wrapped_method(self, *args, **kwargs):
            func.__globals__[varName] = eval(varValue)
            return func(self, *args, **kwargs)
        return wrapped_method
    return decorator

def for_all_methods(decorator):
    def decorate(cls):
        for attr in cls.__dict__: # there's propably a better way to do this
            if callable(getattr(cls, attr)) and attr[:2] != '__':
                setattr(cls, attr, decorator(getattr(cls, attr)))
        return cls
    return decorate

@for_all_methods(quick_assignment('M', 'self.useful_member'))
class ComplicatedClass(object):
    def __init__(self):
      self.useful_member = 6

    def method(self):
        print(M) # Prints 6

However, as Aran-Fey suggests below, this is not ideal, but it answers your question.

Andrei Cioara
  • 3,404
  • 5
  • 34
  • 62
  • 1
    Keep in mind that this won't work if `method` calls another instance's method. That is, if you do something like `print(M); obj = ComplicatedClass(); obj.useful_member = 0; obj.method(); print(M)` you'll see that the value of `M` changes. And of course there are the usual problems with concurrency - global variables in a multithreaded program are a no-no. – Aran-Fey Mar 21 '18 at 13:22
  • Interesting, but I don't think I can reproduce. Does this have to do with the usage of `__globals__`? – Andrei Cioara Mar 21 '18 at 13:26
  • 1
    Yes, it's because all instances of `ComplicatedClass` share the same globals. [Here's](http://dpaste.com/3T0WSJP) a dpaste showcasing the problem for you. – Aran-Fey Mar 21 '18 at 13:30
  • One annoyance is that `M` is going to show up as an undefined name for things like `pyflakes`. – chepner Mar 21 '18 at 13:48
  • This solution pollutes the global (outside of the `ComplicatedClass`) `globals()` namespace with `M`, correct? – R S Mar 21 '18 at 14:04