Reputation: 1012
Suppose I have this class:
class ClassA:
def __init__(self, callable):
self.name = "Hey!"
self.callable = callable
def call(self):
self.callable()
And I want to pass into callable
a function that can access name
:
def function_a():
print(f"{self.name}")
So that this
a = ClassA(function_a)
a.call()
Yields this:
Hey!
How should I go about this? Metaclassing? Class decoration? Or should I just overhaul my architecture so that I don't need to do such a thing?
Edit with a more clear example
The former example seems like I'm just trying to access that attribute, this is not the case. In a more sophisticated demo, consider this:
class ClassA:
def __init__(self, selection):
self.numbers = [randint(1, 100) for _ in range(10)]
self.selection = selection
def select(self):
return self.selection(self.numbers)
And then suppose I want the caller to be able to provide different strategies for selecting those numbers, like
a = ClassA(selection_strategy)
a.select()
In that architecture, selection_strategy
is a callable defined
outside of the class that needs to somehow have access to that
object attributes.
Aaaaand just as I was writing this, I realized that what I want
is actually really simple, I just have to make selection_strategy
accept the arguments I want from the class and call it within
select
. I'm sorry, SO, I've been working for a few hours
and this totally slipped by me.
Thanks!
Upvotes: 0
Views: 2136
Reputation: 4864
Since it is not clear what the point of any of this is, it is hard to know what answer will work. However, other than the obvious idea of the "callable" taking an argument, the simplest thing is to define a callable class
Class callable(object):
def __init__(self, otherclass):
self.name = otherclass.name
def _call__(self):
print(self.name)
then instantiate this with
foo = callable(ClassAInstance)
Upvotes: 1
Reputation: 77407
The callable can't officially be a method because methods must be defined on the class object itself. But does it really have to be a method? You could just define the callable as a regular function taking a single parameter that just happens to be an instance object's self
reference. Namespace resolution is different - you can't use class level variables - but if that's not a problem, this will work:
class ClassA:
def __init__(self, callable):
self.name = "Hey!"
self.callable = callable
def call(self):
self.callable(self)
def function_a(self):
print(f"{self.name}")
a = ClassA(function_a)
a.call()
Upvotes: 2
Reputation: 114108
this seems like a terrible idea but here you go
>>> def hello():
... print 'hello: '+name
...
>>> hello()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in hello
NameError: global name 'name' is not defined
>>> exec hello.func_code in {'name':'bob'}
hello: bob
>>>
Upvotes: 1
Reputation: 940
If you want the function to be able to use self, you must make it a method, like this:
class ClassA:
def __init__(self):
self.name = "Hey!"
self.callable = self.function_a
def call(self):
self.callable()
def function_a(self):
print(f"{self.name}")
Or, you can pass the name as a parameter:
class ClassA:
def __init__(self):
self.name = "Hey!"
self.callable = self.function_a
def call(self):
self.callable(self.name)
def function_a(name):
print(f"{name}")
a = ClassA(function_a)
a.call()
Hope this helps!
Upvotes: 0
Reputation: 43199
I wonder if this is of any real use, but you could use
...
def call(self):
self.callable(self)
def function_a(cls):
print(f"{cls.name}")
a = ClassA(function_a)
a.call()
# Hey!
Upvotes: 1