Is there anyway to do something like this:
class A:
def foo(self):
if isinstance(caller, B):
print "B can't call methods in A"
else:
print "Foobar"
class B:
def foo(self, ref): ref.foo()
class C:
def foo(self, ref): ref.foo()
a = A();
B().foo(a) # Outputs "B can't call methods in A"
C().foo(a) # Outputs "Foobar"
Where caller in A uses some form of introspection to determine the class of the calling method's object?
EDIT:
In the end, I put this together based on some of the suggestions:
import inspect
...
def check_caller(self, klass):
frame = inspect.currentframe()
current = lambda : frame.f_locals.get('self')
while not current() is None:
if isinstance(current(), klass): return True
frame = frame.f_back
return False
It's not perfect for all the reasons supplied, but thanks for the responses: they were a big help.
Assuming the caller is a method, then yes you can, by looking in the previous frame, and picking out self from the locals.
class Reciever:
def themethod(self):
frame = sys._getframe(1)
arguments = frame.f_code.co_argcount
if arguments == 0:
print "Not called from a method"
return
caller_calls_self = frame.f_code.co_varnames[0]
thecaller = frame.f_locals[caller_calls_self]
print "Called from a", thecaller.__class__.__name__, "instance"
Üglŷ as heck, but it works. Now why you would want to do this is another question altogether, I suspect that there is a better way. The whole concept of A isn't allowed to call B is likely to be a mistake.
The caller is always an instance of A. The fact that you're calling it inside a B method doesn't change that. In other words: Insiode B.foo, ref is an instance of A, so calling ref.foo() is a call on A, B is not involved on that call (it could happen top-level).
The only sane way is to pass a reference to self so A can check if it is B or not.
class A(object):
def foo(self, caller=None):
if isinstance(caller, B):
print "B can't call methods in A"
else:
print "Foobar"
class B(object):
def foo(self, ref): ref.foo(self)
class C(object):
def foo(self, ref): ref.foo(self)
a = A();
B().foo(a) # Outputs "B can't call methods in A"
C().foo(a) # Outputs "Foobar"
a.foo() # Outputs "Foobar"
Something like this may meet your needs better:
class A(object):
def foo(self):
# do stuff
class B(A):
def foo(self):
raise NotImplementedError
class C(A):
pass
...but it's difficult to say without knowing exactly what you're trying to do.
Related
Let say I have function a() which is called in many places and I am not able to trace it or change it.
I need some replacement of this function, with calls to it and also do some additional staff.
The old code has many calls a() function so I need some redefinition a=b.
However, example below cause infinite recursion
def a():
return "hello" #do not edit!
def b():
prefix = a() # get something from a
return prefix+" world"
a=b
#...somewhere
a()
Is there any possibility to do this?
You do it with monkey-patching, by using a different variable to hold the old definition.
original_a = a
def b():
prefix = original_a()
return prefix + " world"
a = b
use inheritance
class a:
value=9
def __init__(self):
print("I'm a parent")
def fnc():
print("parent fnc")
class b(a):
def __init__(self):
#super().__init__()
print("I'm a child!")
#classmethod
def fnc(cls):
super().fnc()
print("child fnc")
#classmethod
def getValue(cls):
return super().value
output:
I'm a child!
parent fnc
child fnc
9
make a the Parent and b the SuperChild
b can now access the methods and attributes of a
your wrapping b with the functionality of a
I have following classes in python:
QueryElement as a root class
ElemMatch and GT which inherit from the root.
I have a list in ElemMatch class which is supposed to have instances of QueryElement.
My problem is in invoking a method called compute from the instances inside the list, in ElemMatch class(compute method). The type of object inside the list is not identified by Python, and I do not know how to assign a type to the list. I do not have such a problem in Java since I could 'cast' to a type I like, but here I do not know how to solve it.
I appreciate if you could help.
class QueryElement(object):
__metaclass__ = abc.ABCMeta
#abc.abstractmethod
def addQueryElement(self, queryElement):
raise NotImplementedError( "Should have implemented this" )
#abc.abstractmethod
def compute(self):
raise NotImplementedError( "Should have implemented this" )
class ElemMatch(QueryElement):
def __init__(self):
self._queryElements = []
def addQueryElement(self, queryElement):
self._queryElements.append(queryElement)
def compute(self):
elemMatch = {}
if len (self._queryElements) > 0:
elemMatch['e'] = self._queryElements[0].compute()
return elemMatch
class GT(QueryElement):
def __init__(self):
print 'someThing'
def addQueryElement(self, queryElement):
return None
def compute(self):
print 'compute GT!'
class PALLAS(object):
def foo(self):
gt = GT()
elemMatch = ElemMatch()
elemMatch.addQueryElement(gt)
elemMatch.compute()
p = PALLAS()
p.foo()
In Python, the objects, not the names referring to them, are typed. If the object has a compute method, you can call it, regardless of what the type of the object is.
A quick example:
class A(object):
def foo(self):
print "I'm an A"
class B(object):
def foo(self):
print "I'm a B"
lst = [A(), A(), B(), A(), B()]
for l in lst:
l.foo()
Each element of lst is either an instance of A or of B. Since both have a method named foo, you don't have to know the type of the object referenced by l each time through the loop; the lookup of foo will find the correct method.
This is commonly referred to as duck typing; if l looks like a duck and acts like a duck (i.e., if it has a method foo), then it is a duck (i.e., then we can call the method foo).
>>> class Class:
... def method(self):
... print 'I have a self!'
...
>>> def function():
... print "I don't..."
...
>>> instance = Class()
>>> instance.method()
I have a self!
>>> instance.method = function
>>> instance.method()
I don't...
Okay the book quotes 'The self parameter (mentioned in the previous section) is, in fact, what distinguishes methods
from functions. Methods (or, more technically, bound methods) have their first parameter
bound to the instance they belong to: you don’t have to supply it. So while you can certainly
bind an attribute to a plain function, it won’t have that special self parameter:'
I am not able to understand what the author is trying to convey here ! I am new to oop in python . Please explain me .
Methods only exist on the class; assigning the function to the instance attribute as your example does creates an instance attribute containing the function, and not a method.
It means that affect of
class A:
def a(self):
print 'a'
def b(self, arg):
print arg
can be roughly represented by:
def A_a(self):
print a
def A_b(self, arg):
print arg
class A:
def __init__(self):
self.a = lambda: A_a(self)
self.b = lambda arg: A_b(self, arg)
So instance.a is not original function a which is written in class A, but another function which calls original with additional self argument.
This code throws an exception, AttributeError, "wtf!", because A.foo() is calling B.foo1(), shouldn't it call A.foo1()? How can I force it to call A.foo1() (and any method call inside A.foo() should call A.*)
class A(object):
def foo(self):
print self.foo1()
def foo1(self):
return "foo"
class B(A):
def foo1(self):
raise AttributeError, "wtf!"
def foo(self):
raise AttributeError, "wtf!"
def foo2(self):
super(B, self).foo()
myB = B()
myB.foo2()
In class A instead of calling self methods you need to call A methods and pass in self manually.
This is not the normal way of doing things -- you should have a really good reason for doing it like this.
class A(object):
def foo(self):
print A.foo1(self)
def foo1(self):
return "foo"
class B(A):
def foo1(self):
raise AttributeError, "wtf!"
def foo(self):
raise AttributeError, "wtf!"
def foo2(self):
super(B, self).foo()
myB = B()
myB.foo2()
In the code:
def foo2(self):
super(B, self).foo()
self is an instance of B.
When a method derived from A is called by an instance of B it will start looking in the namespace from B, and only if the method is not found (e.g. is not overridden by B) the implementation from A is used, but always with self referring to B. At no point self is an instance of A.
It is working as intended, as 100% of world programming languages work. Subclass overrides ALL methods of parent class.
However if you really really want to call the A.foo1() you might be able to do it like this (I cannot guarantee). And in any case you must not do this as this is against all principles of good programming.
class A(object):
def foo(self):
A.foo1(self)
One can see what Python is doing here, but the manner of overriding is a bit extreme. Take the case when class A defines 100 attributes and class B inherits these and add 1 more attribute. We want to be able to have the __init__() for B call the __init__() for A and let B's code define only its single attribute. Similarly, if we define a reset() method in A to set all attributes to zero, then the corresponding reset() method for B should be able just to call the reset() method for A and then zero out the single B attribute instead of having to duplicate all of A's code. Python is making difficult what is supposed to be a major advantage of object-oriented programming; that is, the reuse of code. The best option here is avoid overriding of methods that we really want to reuse. If you want to get a sense of the complications with Python here, try this code:
class X(object):
def __init__ ( self ):
print "X"
self.x = 'x'
self.reset()
print "back to X"
def reset ( self ):
print "reset X"
self.xx = 'xx'
class Y(X):
def __init__ ( self ):
print "Y"
super(Y,self).__init__()
self.y = 'y'
self.reset()
print "back to Y"
def reset ( self ):
print "reset Y"
super(Y,self).reset()
print "back to reset Y"
self.yy = 'yy'
aY = Y()
(To make this work properly, remove the self.reset() call in __init__() for class Y.)
I want to implement the decorator pattern in Python, and I wondered if there is a way to write a decorator that just implements the function it wants to modify, without writing boiler-plate for all the functions that are just forwarded to the decorated object. Like so:
class foo(object):
def f1(self):
print "original f1"
def f2(self):
print "original f2"
class foo_decorator(object):
def __init__(self, decoratee):
self._decoratee = decoratee
def f1(self):
print "decorated f1"
self._decoratee.f1()
def f2(self): # I would like to leave that part out
self._decoratee.f2()
I would like to have calls to foo_decorator.f2 forwarded to decoratee.f2 automatically. Is there a way to write a generic method that forwards all unimplemented function-calls to decoratee?
You could use __getattr__:
class foo(object):
def f1(self):
print "original f1"
def f2(self):
print "original f2"
class foo_decorator(object):
def __init__(self, decoratee):
self._decoratee = decoratee
def f1(self):
print "decorated f1"
self._decoratee.f1()
def __getattr__(self, name):
return getattr(self._decoratee, name)
u = foo()
v = foo_decorator(u)
v.f1()
v.f2()
As an addendum to Philipp's answer; if you need to not only decorate, but preserve the type of an object, Python allows you to subclass an instance at runtime:
class foo(object):
def f1(self):
print "original f1"
def f2(self):
print "original f2"
class foo_decorator(object):
def __new__(cls, decoratee):
cls = type('decorated',
(foo_decorator, decoratee.__class__),
decoratee.__dict__)
return object.__new__(cls)
def f1(self):
print "decorated f1"
super(foo_decorator, self).f1()
u = foo()
v = foo_decorator(u)
v.f1()
v.f2()
print 'isinstance(v, foo) ==', isinstance(v, foo)
This is a bit more involved than strictly necessary for your example, where you know the class being decorated in advance.
This might suffice:
class foo_decorator(foo):
def __init__(self, decoratee):
self.__dict__.update(decoratee.__dict__)
def f1(self):
print "decorated f1"
super(foo_decorator, self).f1()
It's arguably not the best practice, but you can add functionality to instances, as I've done to help transition my code from Django's ORM to SQLAlachemy, as follows:
def _save(self):
session.add(self)
session.commit()
setattr(Base,'save',_save)
The UML diagram in the linked Wikipedia article is wrong and so is your code.
If you follow the "decorator pattern", the decorator class is derived from the base decorated class. (In the UML diagram an inheritance arrow from the WindowDecorator to Window is missing).
with
class foo_decorator(foo):
you don't need to implement undecorated methods.
BTW: In strong typed languages there is one more reason, why the decorator must be derived from the decorated class: Otherwise you wouldnt be able to chain decorators.
In one of my projects, I also needed to do one particular thing, that is that even the underlying object should actually execute the method that was reimplemented in the decorator. It is actually quite easy to do if you know where to target it.
The use case is:
I have an object X with methods A and B.
I create a decorator class Y that overrides A.
If I instantiate Y(X) and call A, it will use the decorated A as expected.
If B calls A, then if I instantiate Y(X) and call B on the decorator, the call from within B then goes to the old A on the original object which was undesirable. I want the old B to call the new A as well.
It is possible to reach this behaviour like this:
import inspect
import six # for handling 2-3 compatibility
class MyBaseDecorator(object):
def __init__(self, decorated):
self.decorated = decorated
def __getattr__(self, attr):
value = getattr(self.decorated, attr)
if inspect.ismethod(value):
function = six.get_method_function(value)
value = function.__get__(self, type(self))
return value
class SomeObject(object):
def a(self):
pass
def b(self):
pass
class MyDecorator(MyBaseDecorator):
def a(self):
pass
decorated = MyDecorator(SomeObject())
This may not work out of the box as I typed everything else apart from the getattr method from top of my head.
The code looks up the requested attribute in the decorated object, and if it is a method (doesn't work for properties now, but the change to support them should not be too difficult), the code then pulls the actual function out of the method and using the descriptor interface invocation it "rebinds" the function as a method, but on the decorator. Then it is returned and most likely executed.
The effect of this is that if b ever calls a on the original object, then when you have the object decorated and there is any method call coming from the decorator, the decorator makes sure that all methods accessed are bound to the decorator instead, therefore looking up things using the decorator and not the original object, therefore the methods specified in the decorator taking precedence.
P.S.: Yes I know it looks pretty much like inheritance, but this done in the sense of composition of multiple objects.
To complement #Alec Thomas reply. I modified his answer to follow the decorator pattern. This way you don't need to know the class you're decorating in advance.
class Decorator(object):
def __new__(cls, decoratee):
cls = type('decorated',
(cls, decoratee.__class__),
decoratee.__dict__)
return object.__new__(cls)
Then, you can use it as:
class SpecificDecorator(Decorator):
def f1(self):
print "decorated f1"
super(foo_decorator, self).f1()
class Decorated(object):
def f1(self):
print "original f1"
d = SpecificDecorator(Decorated())
d.f1()
In Python 3, Philipp's accepted answer raised RuntimeError: maximum recursion depth exceeded.
The way that worked for me:
class Foo(object):
def f1(self):
print("original f1")
def f2(self):
print("original f2")
class FooDecorator(object):
def __init__(self, decoratee):
self._decoratee = decoratee
def f1(self):
print("decorated f1")
return self._decoratee.f1()
def __getattr__(self, name):
if name in ['f1', '_decoratee']:
raise AttributeError()
return getattr(self._decoratee, name)
f = FooDecorator(Foo())
f.f1()
# decorated f1
# original f1
f.f2()
# original f2
The workaround is inspired by Ned Batchelder's blog