Reputation: 183909
I want to assign a callable class as a function on another class, and then reference the owner class from the owned function:
class DoIt(object):
def __call__(self):
print "%s did it" % self.name
class Doer(object):
def __init__(self, name):
self.name = name
doSomething = DoIt()
doer = Doer("Bob")
doer.doSomething()
In the code above, I want the doSomething()
function to print "Bob did it", but with this code I'll get a
AttributeError: 'DoIt' object has no attribute 'name'
Because self references the DoIt instance, not the Doer instance. Is it possible to reference the Doer instance?
Upvotes: 0
Views: 683
Reputation: 799230
class DoIt(object):
def __get__(self, instance, owner):
def done():
print "%s did it" % instance.name
return done
class Doer(object):
def __init__(self, name):
self.name = name
doSomething = DoIt()
doer = Doer("Bob")
doer.doSomething()
Explanation: (This is the asker explaining this answer as best he can)
Python offers you descriptor classes, which are classes that act as attributes (in contrast to attributes as instance variables or properties). The __get__
method of a descriptor class dictates what's returned when that class is assigned and accessed as an attribute on another class. And __get__
lets you access both the owning instance and owning class (See method signature).
By having __get__
return a function, you essentially create a callable that has access to its owner.
For more on descriptors, see Attributes, Properties and Descriptors- Building Skills in Python
Upvotes: 4
Reputation: 183909
This is purely another example for Ignacio's answer- I wanted to show the same concept when a parameter is required for the "callable".
class DoIt(object):
def __get__(self, instance, owner):
def done(what):
print "%s did something %s" % (instance.name, what)
return done
class Doer(object):
def __init__(self, name):
self.name = name
doSomething = DoIt()
doer = Doer("Bob")
doer.doSomething("cool")
prints:
Bob did something cool
Upvotes: 0
Reputation: 208635
Here is one way to accomplish this:
class DoIt(object):
def __init__(self, obj):
self.obj = obj
def __call__(self):
print "%s did it" % self.obj.name
class Doer(object):
def __init__(self, name):
self.name = name
self.doSomething = DoIt(self)
doer = Doer("Bob")
doer.doSomething() # prints 'Bob did it'
Upvotes: 2