Hettinger's HowTo Guide for Descriptors covers this well. Quoting from it:
Descriptor Protocol
descr.__get__(self, obj, type=None) --> value
descr.__set__(self, obj, value) --> None
descr.__delete__(self, obj) --> None
That is all there is to it.
So, you can name the arguments however you wish, but there's typically no argument named key to __get__ (no idea why you're trying to find it).
Again an example from that URL:
class RevealAccess(object):
"""A data descriptor that sets and returns values
normally and prints a message logging their access.
"""
def __init__(self, initval=None, name='var'):
self.val = initval
self.name = name
def __get__(self, obj, objtype):
print 'Retrieving', self.name
return self.val
def __set__(self, obj, val):
print 'Updating' , self.name
self.val = val
So normally you set self.something in __init__ (and/or __set__ if you define it), and return something based on self.something in __get__. Of course this example just prints the "something" on getting and setting, normally you'd do something more substantial;-).