0

I am writing an extension to a library and I would like to register my new function with a dictionary of function pointers in the base class. My understanding is that the dictionary, since it is at the uppermost scope within a class, is static and should be update-able. However, when I try to update() the dictionary with the new function in the extended class it tells me that it is undefined. The following minimal example reproduces the error:

def somefunction1(v):
    return v

def somefunction2(v):
    return v

class SomeClass(object):
    dictionary = {'a':somefunction1}

class SomeExtensionClass(SomeClass):
    dictionary.update({'b':somefunction2})

Running it gives the following error

 9 
 10 class SomeExtensionClass(SomeClass):
 ---> 11         dictionary.update({'b':somefunction2})

NameError: name 'dictionary' is not defined

Since I cannot (reasonably) modify the original SomeClass is there any way around this?

Edit: The desired result is that SomeExtensionClass will have dictionary={'a':somefunction1, 'b':somefunction2}

tlnagy
  • 3,274
  • 4
  • 24
  • 37
  • Even if you could do `dictionary.update({'b':somefunction2})`, you would be modifying `SomeClass`. Specifically, `SomeClass.dictionary` would now have an entry for `'b'`. Is this what you want? – user2357112 Jun 04 '14 at 08:07
  • Yes. I updated the original question to reflect that. – tlnagy Jun 04 '14 at 08:11

2 Answers2

2

If you want to modify SomeClass.dictionary, just refer to it as SomeClass.dictionary:

SomeClass.dictionary.update(whatever)

Variable lookup within a class statement doesn't look through the superclasses' attributes.

If you want a new dictionary, so SomeExtensionClass.dictionary is different from SomeClass.dictionary, you'll want to copy the original and update the copy:

class SomeExtensionClass(SomeClass):
    dictionary = SomeClass.dictionary.copy()
    dictionary.update(whatever)
user2357112
  • 260,549
  • 28
  • 431
  • 505
  • This will also update the base class dictionary. That seems like it would be undesired behaviour. – ebarr Jun 04 '14 at 08:21
  • @ebarr: It's the behavior the OP says he wants. There may be a good reason; we don't entirely know what's going on. – user2357112 Jun 04 '14 at 08:22
  • Looks like I misread the question. I've deleted my answer as without the copy it is essentially the same as this. – ebarr Jun 04 '14 at 08:25
  • @user2357112 apparently I didn't know either. Is it possible to create a `SomeExtensionClass` dictionary? Otus' method gives me error a NameError. I'm updating the original question. Apologies. – tlnagy Jun 04 '14 at 08:42
  • @Higany: Looks like otus's comment should have cleared up that issue by now. The only case where class scope is checked for variable lookup is for statements written directly in class scope. Within a method, you have to use attribute references like `self.dictionary` or `SomeExtensionClass.dictionary`. – user2357112 Jun 04 '14 at 21:48
0

There are two reasonable ways to give SomeExtensionClass an updated dictionary:

  1. Update the original dictionary by referring to SomeClass.dictionary.
  2. Define a second dictionary variable for the derived class.

You can do the second like this:

class SomeExtensionClass(SomeClass):
    dictionary = dict(SomeClass.dictionary, b=somefunction2)

Which you should choose depends on who uses the dictionary and for what. If a SomeClass method uses the variable like this:

def foo(self):
    a = self.dictionary['a']()

The method will use the SomeExtensionClass dictionary for SomeExtensionClass objects. If OTOH it does:

def foo(self):
    a = SomeClass.dictionary['a']()

It will always use the dictionary defined in SomeClass.

otus
  • 5,572
  • 1
  • 34
  • 48
  • "You can't write general statements in class scope" - it's not clear what you mean by this. What's a "general statement"? You can write most kinds of statements in class scope. – user2357112 Jun 04 '14 at 08:14
  • @otus `class SomeExtensionClass(SomeClass): dictionary = dict(SomeClass.dictionary, b=somefunction2) def prints(self): print(dictionary) a = SomeExtensionClass() a.prints()` Gives me a `NameError: global name 'dictionary' is not defined` error. Any ideas? – tlnagy Jun 04 '14 at 08:37
  • @Higany, when referring to class variables you need to refer either through a class (`SomeExtensionClass.dictionary`) or an instance (`self.dictionary`). For the difference, see e.g. [this question](http://stackoverflow.com/questions/68645/static-class-variables-in-python). In your `prints` example you probably want `self.dictionary`. – otus Jun 04 '14 at 08:42