How do I introspect A's instance from within b.func() (i.e. A's instance's self):
class A():
def go(self):
b=B()
b.func()
class B():
def func(self):
# Introspect to find the calling A instance here
In general we don't want that func to have access back to the calling instance of A because this breaks encapsulation. Inside of b.func you should have access to any args and kwargs passed, the state/attributes of the instance b (via self here), and any globals hanging around.
If you want to know about a calling object, the valid ways are:
Pass the calling object in as an argument to the function
Explicitly add a handle to the caller onto b instance sometime before using func, and then access that handle through self.
However, with that disclaimer out of the way, it's still worth knowing that Python's introspection capabilities are powerful enough to access the caller module in some cases. In the CPython implementation, here is how you could access the calling A instance without changing your existing function signatures:
class A:
def go(self):
b=B()
b.func()
class B:
def func(self):
import inspect
print inspect.currentframe().f_back.f_locals["self"]
if __name__ == "__main__":
a = A()
a.go()
Output:
<__main__.A instance at 0x15bd9e0>
This might be a useful trick to know about for debugging purposes. A similar technique is even used in stdlib logging, here, so that loggers are able to discover the source code/file name/line number/function name without needing to be explicitly passed that context. However, in normal use cases, it would not usually be a sensible design decision to access stack frames in the case that B.func actually needed to use A, because it's cleaner and easier to pass along the information that you need rather than to try and "reach back" to a caller.
You pass it to b.func() as an argument.
Do this by refactoring your code to work like
class A():
def go(self):
b = B(self)
b.func()
class B():
def __init__(self, a):
self.a = a
def func(self):
# Use self.a
or
class A():
def go(self):
b = B()
b.func(self)
class B():
def func(self, a):
# a
I agree with Benjamin - pass it to b.func() as an argument and don't introspect it!!!!
If your life really depends on it, then I think you can deduce the answer from this answer.
Related
From a famous example, I learned the difference between method, classmethod and staticmethod in a Python class.
Source:
What is the difference between #staticmethod and #classmethod in Python?
class A(object):
def foo(self,x):
print "executing foo(%s,%s)"%(self,x)
#classmethod
def class_foo(cls,x):
print "executing class_foo(%s,%s)"%(cls,x)
#staticmethod
def static_foo(x):
print "executing static_foo(%s)"%x
# My Guesses
def My_Question(self,x):
self.foo(x)
A.class_foo(x)
A.static_foo(x)
a=A()
Now I am wondering, how to call a method, #classmethod, and #staticmethod inside the class.
I put my guesses in the My_Question function above, please correct me if I am wrong with any of these.
Yes, your guesses will work. Note that it is also possible/normal to call staticmethods and classmethods outside the class:
class A():
...
A.class_foo()
A.static_foo()
Also note that inside regular instance methods, it's customary to call the staticmethods and class methods directly on the instance (self) rather than the class (A):
class A():
def instance_method(self):
self.class_foo()
self.static_foo()
This allow for inheritance to work as you might expect -- If I create a B subclass from A, if I call B.instance_method(), my class_foo function will get B instead of A as the cls argument -- And possibly, if I override static_foo on B to do something slightly different than A.static_foo, this will allow the overridden version to be called as well.
Some examples might make this more clear:
class A(object):
#staticmethod
def static():
print("Static, in A")
#staticmethod
def staticoverride():
print("Static, in A, overrideable")
#classmethod
def clsmethod(cls):
print("class, in A", cls)
#classmethod
def clsmethodoverrideable(cls):
print("class, in A, overridable", cls)
def instance_method(self):
self.static()
self.staticoverride()
self.clsmethod()
self.clsmethodoverride()
class B(A):
#classmethod
def clsmethodoverrideable(cls):
print("class, in B, overridable", cls)
#staticmethod
def staticoverride():
print("Static, in B, overrideable")
a = A()
b = B()
a.instance_method()
b.instance_method()
...
After you've run that, try it by changing all of the self. to A. inside instance_method. Rerun and compare. You'll see that all of the references to B have gone (even when you're calling b.instance_method()). This is why you want to use self rather than the class.
As #wim said, what you have is right. Here's the output when My_Question is called.
>>> a.My_Question("My_Answer=D")
executing foo(<__main__.A object at 0x0000015790FF4668>,My_Answer=D)
executing class_foo(<class '__main__.A'>,My_Answer=D)
executing static_foo(My_Answer=D)
For a recursive function we can do:
def f(i):
if i<0: return
print i
f(i-1)
f(10)
However is there a way to do the following thing?
class A:
# do something
some_func(A)
# ...
If I understand your question correctly, you should be able to reference class A within class A by putting the type annotation in quotes. This is called forward reference.
class A:
# do something
def some_func(self, a: 'A')
# ...
See ref below
https://github.com/python/mypy/issues/3661
https://www.youtube.com/watch?v=AJsrxBkV3kc
In Python you cannot reference the class in the class body, although in languages like Ruby you can do it.
In Python instead you can use a class decorator but that will be called once the class has initialized. Another way could be to use metaclass but it depends on what you are trying to achieve.
You can't with the specific syntax you're describing due to the time at which they are evaluated. The reason the example function given works is that the call to f(i-1) within the function body is because the name resolution of f is not performed until the function is actually called. At this point f exists within the scope of execution since the function has already been evaluated. In the case of the class example, the reference to the class name is looked up during while the class definition is still being evaluated. As such, it does not yet exist in the local scope.
Alternatively, the desired behavior can be accomplished using a metaclass like such:
class MetaA(type):
def __init__(cls):
some_func(cls)
class A(object):
__metaclass__=MetaA
# do something
# ...
Using this approach you can perform arbitrary operations on the class object at the time that the class is evaluated.
Maybe you could try calling __class__.
Right now I'm writing a code that calls a class method from within the same class.
It is working well so far.
I'm creating the class methods using something like:
#classmethod
def my_class_method(cls):
return None
And calling then by using:
x = __class__.my_class_method()
It seems most of the answers here are outdated. From python3.7:
from __future__ import annotations
Example:
$ cat rec.py
from __future__ import annotations
class MyList:
def __init__(self,e):
self.data = [e]
def add(self, e):
self.data.append(e)
return self
def score(self, other:MyList):
return len([e
for e in self.data
if e in other.data])
print(MyList(8).add(3).add(4).score(MyList(4).add(9).add(3)))
$ python3.7 rec.py
2
Nope. It works in a function because the function contents are executed at call-time. But the class contents are executed at define-time, at which point the class doesn't exist yet.
It's not normally a problem because you can hack further members into the class after defining it, so you can split up a class definition into multiple parts:
class A(object):
spam= 1
some_func(A)
A.eggs= 2
def _A_scramble(self):
self.spam=self.eggs= 0
A.scramble= _A_scramble
It is, however, pretty unusual to want to call a function on the class in the middle of its own definition. It's not clear what you're trying to do, but chances are you'd be better off with decorators (or the relatively new class decorators).
There isn't a way to do that within the class scope, not unless A was defined to be something else first (and then some_func(A) will do something entirely different from what you expect)
Unless you're doing some sort of stack inspection to add bits to the class, it seems odd why you'd want to do that. Why not just:
class A:
# do something
pass
some_func(A)
That is, run some_func on A after it's been made. Alternately, you could use a class decorator (syntax for it was added in 2.6) or metaclass if you wanted to modify class A somehow. Could you clarify your use case?
If you want to do just a little hacky thing do
class A(object):
...
some_func(A)
If you want to do something more sophisticated you can use a metaclass. A metaclass is responsible for manipulating the class object before it gets fully created. A template would be:
class AType(type):
def __new__(meta, name, bases, dct):
cls = super(AType, meta).__new__(meta, name, bases, dct)
some_func(cls)
return cls
class A(object):
__metaclass__ = AType
...
type is the default metaclass. Instances of metaclasses are classes so __new__ returns a modified instance of (in this case) A.
For more on metaclasses, see http://docs.python.org/reference/datamodel.html#customizing-class-creation.
If the goal is to call a function some_func with the class as an argument, one answer is to declare some_func as a class decorator. Note that the class decorator is called after the class is initialized. It will be passed the class that is being decorated as an argument.
def some_func(cls):
# Do something
print(f"The answer is {cls.x}")
return cls # Don't forget to return the class
#some_func
class A:
x = 1
If you want to pass additional arguments to some_func you have to return a function from the decorator:
def some_other_func(prefix, suffix):
def inner(cls):
print(f"{prefix} {cls.__name__} {suffix}")
return cls
return inner
#some_other_func("Hello", " and goodbye!")
class B:
x = 2
Class decorators can be composed, which results in them being called in the reverse order they are declared:
#some_func
#some_other_func("Hello", "and goodbye!")
class C:
x = 42
The result of which is:
# Hello C and goodbye!
# The answer is 42
What do you want to achieve? It's possible to access a class to tweak its definition using a metaclass, but it's not recommended.
Your code sample can be written simply as:
class A(object):
pass
some_func(A)
If you want to refer to the same object, just use 'self':
class A:
def some_func(self):
another_func(self)
If you want to create a new object of the same class, just do it:
class A:
def some_func(self):
foo = A()
If you want to have access to the metaclass class object (most likely not what you want), again, just do it:
class A:
def some_func(self):
another_func(A) # note that it reads A, not A()
Do remember that in Python, type hinting is just for auto-code completion therefore it helps IDE to infer types and warn user before runtime. In runtime, type hints almost never used(except in some cases) so you can do something like this:
from typing import Any, Optional, NewType
LinkListType = NewType("LinkList", object)
class LinkList:
value: Any
_next: LinkListType
def set_next(self, ll: LinkListType):
self._next = ll
if __name__ == '__main__':
r = LinkList()
r.value = 1
r.set_next(ll=LinkList())
print(r.value)
And as you can see IDE successfully infers it's type as LinkList:
Note: Since the next can be None, hinting this in the type would be better, I just didn't want to confuse OP.
class LinkList:
value: Any
next: Optional[LinkListType]
It's ok to reference the name of the class inside its body (like inside method definitions) if it's actually in scope... Which it will be if it's defined at top level. (In other cases probably not, due to Python scoping quirks!).
For on illustration of the scoping gotcha, try to instantiate Foo:
class Foo(object):
class Bar(object):
def __init__(self):
self.baz = Bar.baz
baz = 15
def __init__(self):
self.bar = Foo.Bar()
(It's going to complain about the global name 'Bar' not being defined.)
Also, something tells me you may want to look into class methods: docs on the classmethod function (to be used as a decorator), a relevant SO question. Edit: Ok, so this suggestion may not be appropriate at all... It's just that the first thing I thought about when reading your question was stuff like alternative constructors etc. If something simpler suits your needs, steer clear of #classmethod weirdness. :-)
Most code in the class will be inside method definitions, in which case you can simply use the name A.
I want to pass a method foo of an instance of a class A to another function run_function. The method foo will use instance variables of its class A.
Here is a minimal example, in which the instance variable of A is simply self.a_var, and foo just prints that variable.
class A:
def __init__(self,a_var):
self.a_var=a_var
def foo(self):
print(self.a_var)
class B:
def __init__(self, A):
self.A=A
# EDIT (comment to compile)
self.A.do_something()
def run_function(self):
self.A.foo()
def run_function_2(self, bar):
bar()
myA = A(42)
myA.foo()
# Current implementation
myB=B(myA)
myB.run_function()
# Better(?) implementation
myB.run_function_2(myA.foo)
At the moment I pass the instance myA of class A to the instance of B and explicitly call self.A.foo(). This forces the name of the function of Ato be foo. Which is stupid.
The better (?) implementation passes the function of the instance to run_function2. This works, but I am not sure if this is "safe".
Question:
Are there any loopholes that I don't see at the moment?
The important part is, that the method foo, that is passed, needs to access instance variables of the (its) class instance. So, will foo that is called inside run_function_2 always have access to all instance variables of myA?
Is there a better way to implement this?
EDIT: I forgot to add, that class B will always have an instance of A, since it has to do_something with that instance. Maybe that will change something(?). Sorry!
For your second implementation, have you considered the following:
>>> myAa = A(42)
>>> myAb = A(43)
>>> myB = B(myAb)
>>> myB.run_function_2(myAa.foo)
42
This might not be what you want. How about using getattr() and just passing in the desired method name:
>>> class C:
... def __init__(self, A):
... self.A = A
... def run_fct(self, bar):
... fct = getattr(self.A, bar)
... fct()
...
>>> myC = C(myAa)
>>> myC.run_fct('foo')
42
To answer your questions:
Any function executed in the context of an object instance will have access to the instance variables.
There may be a better way to implement this, you could try defining an interface for class A and other classes that might be like it. The you know that the function will always be called foo(). If not, I'd question why it is you need to have some object call an arbitrary method on another object. If you can give more concrete examples about what you're trying to do it would help.
The main difference between run_function and run_function_2 is that the former calls foo on the object that was given to the B() constructor. run_function_2 is independent of what object is saved as self.A; it just calls the function/method you give it. For example
class A:
def __init__(self,a_var):
self.a_var=a_var
def foo(self):
print(self.a_var)
class B:
def __init__(self, A):
self.A=A
def run_function(self):
self.A.foo()
def run_function_2(self, bar):
bar()
myA = A(42)
myB = B(myA)
myA2 = A(3.14)
myB.run_function()
myB.run_function_2(myA.foo)
myB.run_function_2(myA2.foo)
Output
42
42
3.14
Are there any loopholes that I don't see at the moment?
These two ways of calling methods are fine. Though I agree that function_run_2 is more convenient since it doesn't fix the method name, it makes you ask... what's the purpose of giving an A object to the B constructor in the first place if it's never used?
The important part is, that the method foo, that is passed, needs to access instance variables of the (its) class instance. So, will foo that is called inside run_function_2 always have access to all instance variables of myA?
Yes. run_function_2 arguments requires a function. In this case, you pass myA.foo, an object myA's method defined in class A. When you call foo inside run_function_2, you are only dealing with attributes variables of the instance myA; this is the idea of encapsulation in classes.
Is there a better way to implement this?
Answering also your question on safety, it's perfectly safe. Functions and methods are objects in Python, and they can be passed around like values. You're basically leaning on the idea of function currying or partial functions. See How do I pass a method as a parameter in Python. These two ways are fine.
Consider this situation:
I get an object of type A which has the function f:
class A:
def f(self):
print 'in f'
def h(self):
print 'in h'
and I get an instance of this class, but I want to override the f function, yet save the rest of the functionality of A. So what I was thinking was something of the sort:
class B(A):
def __init__(self, a):
#something here
....
def f(self):
print 'in B->f'
and the usage would be:
def main(a):
b = B(a)
b.f() #prints "in B->f"
b.h() #print "in h"
What I want is a sort of copy constructor that gets a parent of the current class (A), and returns an instance of this class (B).
How do you do such a thing? How would the __init__ method look?
Note: this post has been edited by the original poster to incorporate changes suggested in the comments, which is why some of the suggestions look redundant or incorrect.
How you construct an object of subclass B "based on" one of class A depends exclusively on how the latter keeps state, if any, and how do you best get to that state and copy it over. In your example, instances of A are stateless, therefore there is absolutely no work you need to do in B's '__init__'. In a more typical example, say:
class A(object):
def __init__(self):
self._x = 23
self._y = 45
def f(self):
print 'in f,', self._x
def h(self):
print 'in h,', self._y
the state would be in the two instance attributes _x and _y, so those are what you need to copy over:
class B(A):
def __init__(self, a):
self._x = a._x
self._y = a._y
def f(self):
print 'in B->f,', self._x
This is the most common and normal approach, where the subclass accepts and directly implements its state-dependence on the superclass -- it's very straightforward and linear.
You normally look for A's instance state aspects in A's '__init__', because most normal, straightforward Python code establishes instance state at initialization (attributes might be added and removed later, or even from code outside of the class's body, but that's not common and generally not advisable).
It is possible to add a little touch of "magic" (introspection-based programming), e.g...:
class B1(A):
def __init__(self, a):
try: s = a.__getstate__()
except AttributeError: s = a.__dict__
try: self.__setstate__(s)
except AttributeError: self.__dict__.update(s)
getstate is a special method that classes may define -- if they do, it's used (e.g. by pickling) to "get the state" of their instances for serialization purpose (otherwise, the instance's __dict__ is deemed to be the instance's "state"). It may return a dict (in which case the .update call updates self's state), but it may also return anything else if the class also defines a __setstate__ that accepts it (so this code tries that route first, before falling back to the update possibility). Note that in this use case either or both of the special methods would be inherited from A -- I wouldn't define / override them in B (unless there are further subtle goals to be achieved that way of course;-).
Is it worth using these four lines of "magic" in lieu of the simple assignments I first suggested? Mostly, no -- simplicity is preferable. But if A does anything special or is subject to external code altering its state, this solution can be more powerful and general (that's what you're buying by accepting its complication). So, you have to know if the latter case applies (and then "go for the big guns" of the special state-related methods), or if A and its instances are "pretty normal vanilla ones", in which case I would strongly recommend choosing simplicity and clarity instead.
Try this:
class A:
def f(self):
print("in f")
def h(self):
print("in h")
class B(A):
def f(self):
print("in B:f")
def test(x):
x.f()
x.h()
test(A())
test(B())
Note, I'm using Python 3, which is the reason for print taking the arguments in parenthesis.
Output:
in f
in h
in B:f
in h
You need to put the self argument into the argument list for instance methods in python.
Once you've done that, it will just work, because all methods are virtual in python.
Assume you define a class, which has a method which does some complicated processing:
class A(object):
def my_method(self):
# Some complicated processing is done here
return self
And now you want to use that method on some object from another class entirely. Like, you want to do A.my_method(7).
This is what you'd get: TypeError: unbound method my_method() must be called with A instance as first argument (got int instance instead).
Now, is there any possibility to hack things so you could call that method on 7? I'd want to avoid moving the function or rewriting it. (Note that the method's logic does depend on self.)
One note: I know that some people will want to say, "You're doing it wrong! You're abusing Python! You shouldn't do it!" So yes, I know, this is a terrible terrible thing I want to do. I'm asking if someone knows how to do it, not how to preach to me that I shouldn't do it.
Of course I wouldn't recommend doing this in real code, but yes, sure, you can reach inside of classes and use its methods as functions:
class A(object):
def my_method(self):
# Some complicated processing is done here
return 'Hi'
print(A.__dict__['my_method'](7))
# Hi
You can't. The restriction has actually been lifted in Python 3000, but I presume you are not using that.
However, why can't you do something like:
def method_implementation(self, x,y):
# do whatever
class A():
def method(self, x, y):
return method_implementation(self, x, y)
If you are really in the mood for python abuse, write a descriptor class that implements the behavior. Something like
class Hack:
def __init__(self, fn):
self.fn = fn
def __get__(self, obj, cls):
if obj is None: # called staticly
return self.fn
else:
def inner(*args, **kwargs):
return self.fn(obj, *args, **kwargs)
return inner
Note that this is completely untested, will probably break some corner cases, and is all around evil.
def some_method(self):
# Some complicated processing is done here
return self
class A(object):
my_method = some_method
a = A()
print some_method
print a.my_method
print A.my_method
print A.my_method.im_func
print A.__dict__['my_method']
prints:
<function some_method at 0x719f0>
<bound method A.some_method of <__main__.A object at 0x757b0>>
<unbound method A.some_method>
<function some_method at 0x719f0>
<function some_method at 0x719f0>
It sounds like you're looking up a method on a class and getting an unbound method. An unbound method expects a object of the appropriate type as the first argument.
If you want to apply the function as a function, you've got to get a handle to the function version of it instead.
You could just put that method into a superclass of the two objects that need to call it, couldn't you? If its so critical that you can't copy it, nor can you change it to not use self, thats the only other option I can see.
>>> class A():
... me = 'i am A'
...
>>> class B():
... me = 'i am B'
...
>>> def get_name(self):
... print self.me
...
>>> A.name = get_name
>>> a=A()
>>> a.name()
i am A
>>>
>>> B.name = get_name
>>> b=B()
>>> b.name()
i am B
>>>
Why cant you do this
class A(object):
def my_method(self,arg=None):
if (arg!=None):
#Do Some Complicated Processing with both objects and return something
else:
# Some complicated processing is done here
return self
In Python functions are not required to be enclosed in classes. It sounds like what you need is utility function, so just define it as such:
def my_function(object):
# Some complicated processing is done here
return object
my_function(7)
my_function("Seven")
As long as your processing is using methods and attribute available on all objects that you pass to my_function through the magic of duck typing everything will work fine.
That's what's called a staticmethod:
class A(object):
#staticmethod
def my_method(a, b, c):
return a, b, c
However in staticmethods, you do not get a reference to self.
If you'd like a reference to the class not the instance (instance implies reference to self), you can use a classmethod:
class A(object):
classvar = "var"
#classmethod
def my_method(cls, a, b, c):
print cls.classvar
return a, b, c
But you'll only get access to class variables, not to instance variables (those typically created/defined inside the __init__ constructor).
If that's not good enough, then you will need to somehow pass a "bound" method or pass "self" into the method like so:
class A(object):
def my_method(self):
# use self and manipulate the object
inst = A()
A.my_method(inst)
As some people have already said, it's not a bad idea to just inherit one class from the other:
class A(object):
... methods ...
class B(A):
def my_method(self):
... use self
newA = B()