The class body is executed just like a function is, and the local namespace is then turned into the class attributes.
As such normal naming order requirements apply; you cannot reference get_username()
because it is not yet defined.
Moreover, you'd get the unbound classmethod
object even if you moved the map
definition down below the get_username()
definition.
As such, you'd add the method to the mapping after creating the class:
class UU(object):
@classmethod
def get_username(cls):
pass
UU.map = {
'username': UU.get_username
}
Note that this means than from there on out UU.map['username']
is using a classmethod
bound to the UU
class. You'll not get the version on a subclass if you have ever subclassed UU
and provided an override of that method.
You'd have to jump through a lot more hoops to make this work for subclasses; you'd have to make map
a descriptor object so you can bind class methods when looking up values in the mapping, not when defining the mapping:
class BindingMap(dict):
def __get__(self, instance, cls=None):
return {k: v.__get__(instance, cls) if hasattr(v, '__get__') else v for k, v in self.items()}
class UU(object):
@classmethod
def get_username(cls):
pass
map = BindingMap({
'username': get_username,
})
The map will then produce bound class methods on demand, extending to subclasses:
>>> class BindingMap(dict):
... def __get__(self, instance, cls=None):
... return {k: v.__get__(instance, cls) if hasattr(v, '__get__') else v for k, v in self.items()}
...
>>> class UU(object):
... @classmethod
... def get_username(cls):
... pass
... map = BindingMap({
... 'username': get_username,
... })
...
>>> UU.map
{'username': <bound method type.get_username of <class '__main__.UU'>>}
>>> UU.map['username']
<bound method type.get_username of <class '__main__.UU'>>
>>> UU.map['username']()
>>> class UU(object):
... @classmethod
... def get_username(cls):
... print('Username for class {}'.format(cls.__name__))
... map = BindingMap({
... 'username': get_username,
... })
...
>>> UU.map
{'username': <bound method type.get_username of <class '__main__.UU'>>}
>>> UU.map['username']
<bound method type.get_username of <class '__main__.UU'>>
>>> UU.map['username']()
Username for class UU
>>> class Foo(UU):
... pass
...
>>> Foo.map
{'username': <bound method type.get_username of <class '__main__.Foo'>>}
>>> Foo.map['username']
<bound method type.get_username of <class '__main__.Foo'>>
>>> Foo.map['username']()
Username for class Foo