When I try to allocate different function to different class members the last declared value gets overriden.
class Object:
def __init__(self, *args, **kwargs):
pass
class Service:
#staticmethod
def get_a_value():
return 1
#staticmethod
def get_b_value(*args, **kwargs):
return 2
def __init__(self, *args, **kwargs):
self.a = Object
self.b = Object
self.a.execute = self.get_a_value
self.b.execute = self.get_b_value
if __name__ == '__main__':
obj = Service()
print(obj.a().execute())
print(obj.b().execute())
The expected output is 1 & 2 but I'm getting both as 2. Not sure what I'm missing here. How can I make sure I can allocate different functions to a.execute and b.execute. Any help would be much appreciated.
what about creating specific objects for your a and b members, with a class deriving from Object:
class Object:
def __init__(self, *args, **kwargs):
pass
class Service:
#staticmethod
def get_a_value():
return 1
#staticmethod
def get_b_value(*args, **kwargs):
return 2
def __init__(self, *args, **kwargs):
class ObjectA(Object):
#staticmethod
def execute():
return Service.get_a_value()
class ObjectB(Object):
#staticmethod
def execute():
return Service.get_b_value()
self.a = ObjectA
self.b = ObjectB
if __name__ == '__main__':
obj = Service()
print(obj.a().execute())
print(obj.b().execute())
This prints
1
2
Of course this may become slightly more complex if the methods aren't static but this can be easily adapted in the example below where all methods are full non-static methods
class Service:
def get_a_value(self):
return self.__a_value
def get_b_value(self):
return self.__b_value
def __init__(self, *args, **kwargs):
self.__a_value = 1
self.__b_value = 2
class ObjectA(Object):
def execute(myself):
return self.get_a_value()
class ObjectB(Object):
def execute(myself):
return self.get_b_value()
You'll notice that self used in execute methods refer to instance of Service (hence the myself first argument in child classes). It works as well, even if no method is static, and can access values of the instance.
With that, you can create full-fledged object interfaces.
It is because obj.a and obj.b contain both a reference to the same class.
So everything you modify on obj.a will be reflected in obj.b.
What you probably wanted to do is :
def __init__(self, *args, **kwargs):
self.a = Object()
self.b = Object()
self.a.execute = self.get_a_value
self.b.execute = self.get_b_value
Related
Usually one initializes class members inside the class (not into the constructor) and the references them via MyClass.mymember instead of self.mymember.
However I noticed that I can actually reference the member later via self.mymember. Further, I can even overwrite it. This has the very curious effect, that the class member becomes an instance member.
This effect can be seen in the following code with property_cache of MyClass.
It is really helpful in this context, because now the object property_cache (not the class PropertyCache!) can be used as a decorator and it is a instance member of myclass(not a class member of MyClass!).
However, the effect that a class member is turned into an instance member after the declaration of MyClass is very unexpected. I did not even consider that such a thing is possible and I don't quite understand this mechanism.
Can someone shed some light on it and possible reference some literature on this? I did not find a description in the documentation of python.
class PropertyCache:
def __init__(self):
self.cache = {}
def reset(self):
self.cache = {}
def __call__(this, function):
def wrapper(self, *args, **kwargs):
if function.__qualname__ not in self.property_cache.cache:
self.property_cache.cache[function.__qualname__] = function(self, *args, **kwargs)
return self.property_cache.cache[function.__qualname__]
return wrapper
class MyClass:
property_cache = PropertyCache()
def __init__(self, parameter):
self.parameter = parameter
self.property_cache = PropertyCache()
def fit(self, data):
print('fit')
self.intermediate_data_ = data + self.parameter + 2
self.property_cache.reset()
return self
#property
#property_cache
def trans1(self):
print('trans 1')
return self.intermediate_data_ / self.parameter / 2
#property
#property_cache
def trans2(self):
print('trans 2')
return self.intermediate_data_ / self.parameter / 5
myclass = MyClass(2)
myclass.fit(10)
myclass.trans1
myclass.trans1
myclass.trans2
myclass.fit(15)
myclass.trans1
myclass.trans1
myclass.trans2
myclass2 = MyClass(3)
myclass2.fit(15)
myclass2.trans2
myclass2.trans2
myclass.trans2
I have a Cash class (derived from the Instrument class) which has a .manager class attribute. This class attribute (an instance of the Manager class), when it is initialized, needs to receive the class to which it is attached, as per below.
class Manager:
def __init__(self, instrument):
self.instrument = instrument #instrument is a class (a type)
def get(self, *args, **kwargs):
return self.instrument(30.99) #return an instance (e.g. ORM-like operation)
class Instrument:
pass
class Cash(Instrument):
manager = Manager(Cash) #this fails... as Cash isn't defined yet
def __init__(self, amount):
self.amount = amount
How do we achieve this, i.e. pass one's class to one of its own class attributes at definition?
If you have circular class/attributes, you can use functions that you call after instantiation, in my example add_A and add_B :
class A:
def __init__(self):
self.foo = 1
def add_B(self, b):
self.b = b
class B:
def __init__(self):
self.bar = 2
def add_A(self, a):
self.a = a
a = A()
b = B()
a.add_B(b)
print(a.b.bar)
# 2
b.add_A(a)
print(b.a.foo)
# 1
I would like to implement a parent class decorator in my child class whose functionality depends on the state of the child class instance. I've tried coming at this problem from three different angles, none of which have worked:
Parent method
If give_feedback is a static method, there's no self within the method. But if it's an instance method, there's no self within the namespace in which it's applied.
class Interface:
def __init__(self, quiet=False):
self.quiet = quiet
def echo(self, text):
if not self.quiet:
print(text)
def give_feedback(self, func):
def wrapper(*args):
print('Calling give_feedback.')
self.echo(func(*args))
return wrapper
class App(Interface):
#Interface.give_feedback # self not defined here.
def app_func(self, num):
feedback = 'Success with {num}'.format(num=num)
return feedback
if __name__ == '__main__':
a = App()
a.app_func(3)
Parent class using __call__ (cf. link example_1)
Can't access the object from within __call__.
class Interface:
# ...
class give_feedback:
def __init__(self, func):
self.func = func
def __call__(self, *args):
print(
'Calling {func}'.format(func=self.func)
)
instance = get_obj_instance(self.func) # What is this?
return instance.echo(self.func(instance, *args))
class App(Interface):
# ...
if __name__ == '__main__':
# ...
Parent descriptor (cf. link example_2)
Can access the object, but no arguments.
class Interface:
# ...
class give_feedback:
# ...
def __get__(self, instance, owner):
print(
'Getting {func} from {inst} of {ownr}'.format(
func=self.func, inst=instance, ownr=owner
)
)
num = 2 # How to get num???
return instance.echo(self.func(instance, num))
class App(Interface):
# ...
if __name__ == '__main__':
a = App()
a.app_func # No ability to pass parameters.
Is there a good way to do this?
Why not combine the 2nd and 3rd methods? Use __get__ to get the class instance, and __call__ to decorate with echo. Rather than returning app_func, return a new object that holds the instance and has the desired __call__ behavior.
class Interface:
def __init__(self, quiet=False):
self.quiet = quiet
def echo(self, text):
if not self.quiet:
print(text)
class give_feedback:
def __init__(self, func):
self.func = func
def __get__(self, instance, owner):
return self.InstHolder(instance, self.func)
class InstHolder:
def __init__(self, inst, func):
self.inst = inst
self.func = func
def __call__(self, *args):
return self.inst.echo(self.func(self.inst, *args))
class App(Interface):
#Interface.give_feedback
def app_func(self, num):
feedback = 'Success with {num}'.format(num=num)
return feedback
if __name__ == '__main__':
a = App()
a.app_func(3)
a.quiet = True
a.app_func(4)
I want to use a decorator to do some preparation job and record the status the function have, so I write something like that:
class Decorator:
def __init__(self, func):
self.count = 0
self.func = func
def __call__(self, *args, **kwargs):
self.count += 1 # Simply count the call times
return self.func(self, *args, **kwargs)
class Foo:
def __init__(self):
self.value = 0
#Decorator
def test(self, value):
self.value = value # change the value of instance
print(self.value)
f = Foo()
f.test(1)
print(f.value)
print(f.test.value)
But it's obvious that self in __call__(self, *args, **kwargs) corresponds to instance of Decorator instead of the instance of Foo , which will make f.value unchanged but f.test.value increase .
Is there any way I can pass the instance of Foo to Decorator instead of Decorator itself?
Or is there any way to implement this function much more clear?
As the decorator is only called once and replaces the method for all instance with one instance of the Decorator class. All it does is:
Foo.test = Decorator(Foo.test)
This makes it impossible to detect the instance called. One work-around would be to apply the decorator in the __init__ of Foo by hand:
class Foo:
def __init__(self):
self.value = 0
self.test = Decorator(self.test)
def test(self, value):
self.value = value # change the value of instance
print(self.value)
This way the decorator wraps the instance method, so you do not need to pass self in the __call__ of Decorator:
class Decorator:
def __init__(self, func):
self.count = 0
self.func = func
def __call__(self, *args, **kwargs):
self.count += 1 # Simply count the call times
return self.func(*args, **kwargs)
Now it works and you have to update you test method, as f.test.value no longer exists:
f = Foo()
f.test(1)
print(f.value)
It outputs two times a 1 as expected.
I got this here
import functools
class Decorator(object):
def __init__(self, func):
self.count = 0
self.func = func
def __call__(self, *args, **kwargs):
self.count += 1 # Simply count the call times
return self.func( *args, **kwargs)
def __get__(self, instance, instancetype):
"""Implement the descriptor protocol to make decorating instance
method possible.
"""
# Return a partial function with the first argument is the instance
# of the class decorated.
return functools.partial(self.__call__, instance)
class Foo:
def __init__(self):
self.value = 0
#Decorator
def test(self, value):
self.value = value # change the value of instance
f = Foo()
f.test(3)
print(f.value) # prints 3
g = Foo()
g.test(8)
print(g.value) # prints 8
or
May be this
def preJob(function):
def updateToDo(self, *args, **kwargs):
# do some recording
function(self, *args, **kwargs)
return updateToDo
class Foo(object):
def __init__(self):
self.value = 0
#preJob
def test(self, value):
self.value = value
f = Foo()
f.test(3)
print(f.value) # prints 3
g = Foo()
g.test(8)
print(g.value) # prints 8
class threadSafeGenerator(object):
"""docstring for threadSafeGenerator"""
class SafeGenerator(object):
"""docstring for SafeGenerator"""
def __init__(self, iterable):
self.iterable = iterable
self.lock = Lock()
def __iter__(self):
return self
def __next__(self):
with self.lock:
return next(self.iterable)
def __init__(self, func):
super(threadSafeGenerator, self).__init__()
self.func = func
def __call__(self, *args, **kwargs):
return self.SafeGenerator(self.func(self, *args, **kwargs))
I found using Priyesh Kumar's answer that you can simply pass the self argument from the call method to the function being decorated:
def __call__(self, *args, **kwargs):
return self.SafeGenerator(self.func(self, *args, **kwargs))
hope this helps!
EDIT:
Never mind only works if the function being passed through the decorator does not call class variables defined in the init method
I have an API class (it will be extended and used by other classes):
class A(object):
def __init__(self, **kwargs):
self.kwargs = kwargs
#classmethod
def create(cls, **kwargs):
return cls(**kwargs)
It is extended by:
class B(A):
pass
Now, this is what I want: if I instantiate class B like B(arg1=1, arg2=2) I would like to do some additional operations when initializing it, like validate the kwargs arguments (and this code should reside in class A, not in B). Then, if I do B.create(arg1=1, arg2=2), that validation should not occur.
In short, I would like to do extra operations when initializing an object only from the outside of the class it was defined; initalizing an object from a classmethod inside its class should not trigger any extra operation.
You can use additional argument to distinguish method of class initialisation:
class A(object):
def __init__(self, __a_validate=True, **kwargs):
self.kwargs = kwargs
if __a_validate:
print 'do validation'
#classmethod
def create(cls, **kwargs):
return cls(__a_validate=False, **kwargs)
Demo:
>>> B.create(arg1=1, arg2=2)
<__main__.B object at 0x9b82f4c>
>>> B(arg1=1, arg2=2)
do validation
<__main__.B object at 0x9b7bbcc>
update for comments:
This is another solution. You can modify class attribute in create method, for example set validate function to None, call constructor and then set validate back to original state:
class A(object):
def __init__(self, **kwargs):
self.kwargs = kwargs
if self.validate:
self.validate(kwargs)
def validate(self, kwargs):
print 'do validation'
#classmethod
def create(cls, **kwargs):
tmp = cls.validate
cls.validate = None
instance = cls(**kwargs)
cls.validate = tmp
return instance
If your "extra operations" are in the constructor then I'm afraid they'll always get run, regardless of whether you instantiate directly or through a factory. You could consider only allowing object creation through a set of factory methods (some with validation and some without).
class A(object):
def __init__(self, **kwargs):
self.kwargs = kwargs
#no extra stuff
#classmethod
def create_with_extra_stuff(cls, **kwargs):
c = cls(**kwargs)
c.extra_stuff()
return c
#classmethod
def create_withuot_extra_stuff(cls, **kwargs):
return cls(**kwargs)
#classmethod
def create(cls, with_extra_stuff = False, **kwargs):
if with_extra_stuff:
return cls.create_with_extra_stuff(**kwargs)
else:
return cls.create_without_extra_stuff(**kwargs)
Of course, I don't know your full use case but factory patterns are pretty much designed for this sort of thing.
This section was added after the comments were made:
class A(object):
def __init__(self, do_extra_stuff = True, **kwargs):
if do_extra_stuff:
self.do_extra_stuff(**kwargs)
self.kwargs = kwargs
#classmethod
def create(cls, **kwargs):
return cls(do_extra_stuff = False, **kwargs)
Further edit showing alternative:
class A(object):
def __init__(self, **kwargs):
#lightweight constructor
self.kwargs = kwargs
def validate(self):
#Does not alter class variables. That would be bad in this case
#Do stuff with self.kwargs
#classmethod
def create(cls, **kwargs):
return cls(**kwargs)
main():
a = A({...})
a.validate()
b = A.create({...})
#b.validate() not called
The point is that the constructor will be called on construction. The trick then is to decide what additional stuff needs to be selective called.