[Python-ideas] Mitigating 'self.' Method Pollution

Steven D'Aprano steve at pearwood.info
Sat Jul 11 03:34:13 CEST 2015


On Fri, Jul 10, 2015 at 07:28:14PM -0400, Joseph Jevnik wrote:
> How does this interact with descriptors, are they looked up everytime x and
> y are referenced or are they cached at the `this x, y` statement?

My understanding is that the actual execution of Python code does not 
change. Today, if you write:

def method(self):
    self.spam = self.eggs + 1


it compiles to something like this (in Python 2.7, different versions 
may use different bytecode):

  2           0 LOAD_FAST                0 (self)
              3 LOAD_ATTR                0 (eggs)
              6 LOAD_CONST               1 (1)
              9 BINARY_ADD
             10 LOAD_FAST                0 (self)
             13 STORE_ATTR               1 (spam)
             16 LOAD_CONST               0 (None)
             19 RETURN_VALUE

There's no caching of attribute look-ups, if spam or eggs are 
descriptors (methods, properties, etc.) the descriptor protocol gets 
called each time LOAD_ATTR or STORE_ATTR is called.

If you re-write that to:

def method(self):
    self spam, eggs
    spam = eggs + 1

it should compile to *exactly the same byte code*. It's just a compiler 
directive, telling the compiler to treat any "spam" and "eggs" tokens as 
if they were actually "self.spam" and "self.eggs".

That would, of course, mean that it's impossible to have a local 
variable with the same name as the declared attribute. I often write 
micro-optimized code like this:

    spam = self.spam = {}
    for x in big_loop:
        # avoid the repeated look-ups of ".spam"
        spam[x] = something

If I declared "self spam", this wouldn't work (or rather, it would work, 
but it wouldn't have the effect I am looking for). The solution is 
simple: don't declare "self spam" in this case.


-- 
Steve


More information about the Python-ideas mailing list