I have a class and I want to reassign a certain method to an hidden one of the same class.
In my case I have a generic filter that I want to assign to a specific implementation.
I'd like to have the func_map as a class attribute instead of an instance attribute because it seems more logic. How should I do that?
class MyClass:
func_map = {"eq" : __eq_filter}
def set_filter(self, func):
self.filter = MyClass.func_map[func]
def filter(self, value):
raise NotImplementedError
def __eq_filter(self, value):
return self.attribute == value
Maybe use the built-in #staticmethod decorator, which, according to the docs, allows to bound a method to the class instead of to the instance (Transform a method into a static method):
class MyClass:
func_map = {"eq" : __eq_filter}
def set_filter(self, func):
self.filter = func_map[func]
def filter(self, value):
raise NotImplementedError
#staticmethod
def __eq_filter(self, value):
return self.attribute == value
Check the docs for more info: https://docs.python.org/3/library/functions.html#staticmethod
Related
I'm trying to add extra decorator for magic method (__get__) in descriptor class.
I'm able to do it when I use #property but not when I use descriptor class.
I check range because my object set registers on the bus and some registers can take only specific range of values:
import functools
def check_range(min, max):
def decorator(f):
#functools.wraps(f)
def wrap(self, value):
if value not in range(min, max+1):
return
return f(self, value)
return wrap
return decorator
This works:
class Foo:
def __init__(self):
self.device.init_smth('my_object')
#property
def my_object(self):
return self.device.get_value('my_object')
#my_object.setter
#check_range(0,1)
def my_object(self, value):
self.device.set_value('my_object', value)
a = Foo()
print(a.my_object)
a.my_object = 1
print(a.my_object)
a.myobject = -1
And in this example everything works the same but check_range is not invoked:
class Register:
def __init__(self, name, device):
self.name = name
device.init_smth(name)
def __get__(self, instance, owner):
return instance.device.get_value(self.name)
#check_range(0,1)
def __set__(self, instance, value):
instance.device.set_value(self.name, value)
class Foo:
def __init__(self):
self.my_object = Register('my_object', self.device)
a = Foo()
print(a.my_object)
a.my_object = 1
print(a.my_object)
a.myobject = -1
I may be wrong, but most probably your descriptor not invoked at all, decorator is not the problem. Descriptors meant to be used like
class Foo2:
my_object = Register('my_object', 'init_value')
— you're defining it like class attribute. And python will execute all machinery with __get__/__set__/__del__ if your class attribute supports it (i.e. it is descriptor).
This is why there is an "instance" argument in descriptor methods — you're defining descriptor as class variable, but i.e. __set__ method will receive actual instance of your class, so you can manage per-instance data, like your device
I want to write abstract class that will force inheriting classes to implement all methods AND properties in my abstract class.
Additionally I want to use of setters and getters for my abstract property to make my code uncluttered and looking nicely
However, current implementation:
import abc
class Component(metaclass=abc.ABCMeta):
#property
#abc.abstractmethod
def status(self):
pass
#property
#status.setter
#abc.abstractmethod
def status(self, value):
pass
does enforce inheriting class to implement getter for my abstract property getter, but does not enforce creating a property setter (what is exactly what I want)
How can I achieve this behavior without loosing all benefits from application of further mentioned method (aka writing new methods and executing them in my abstract class setter) ?
from abc import ABCMeta, abstractmethod
class Base(object):
__metaclass__ = ABCMeta
def __init__(self, val):
self._foo = val
#abstractmethod
def _doStuff(self, signals):
print ('Base does stuff')
#abstractmethod
def _get_foo(self):
return self._foo
#abstractmethod
def _set_foo(self, val):
self._foo = val + 'r'
foo = property(_get_foo, _set_foo)
class floor_1(Base):
__metaclass__ = ABCMeta
def __init__(self, val):
self._foo = val
super(floor_1, self).__init__(val)
def _doStuff(self, signals):
print ('floor_1 does stuff')
def _get_foo(self):
return self._foo
def _set_foo(self, val):
#self._foo = val + 'r'
super()._set_foo(val + 'r')
foo = property(_get_foo, _set_foo)
class floor_2(floor_1):
#property
def foo(self):
return self._foo
#foo.setter
def foo(self, val):
self._foo = val + 'r'
#super()._set_foo(val + 'r')
b1 = floor_1('bar')
# b1 = floor_2('bar')
print(b1.foo)
b1.foo = 'bar'
print(b1.foo)
The problem is that neither the getter nor the setter is a method of your abstract class; they are attributes of the property, which is a (non-callable) class attribute. Consider this equivalent definition:
def status_getter(self):
pass
def status_setter(self, value):
pass
class Component(metaclass=abc.ABCMeta):
# status = property(...)
# status.__isabstractmethod__ = True
status = abstractmethod(property(status_getter, status_setter))
Inheriting a property is quite different from inheriting a method. You are basically replacing the property, because your class itself does not have a reference to either the getter or the setter. Despite the name, abstractmethod does not actually make the property a method; it really does nothing more than add an attribute to whatever it is applied to and return the original value.
So, to ensure that a subclass provides a read/write property, what are you to do? Skip the decorator syntax, define the getter and setter as explicit abstract methods, then define the property explicitly in terms of those private methods.
class Component(metaclass=abc.ABCMeta):
#abstractmethod
def _get_status(self):
pass
#abstractmethod
def _set_status(self, v):
pass
status = property(lambda self: self._get_status(), lambda self, v: self._set_status(self, v))
Or, you can make use of __init_subclass__ (which postdates abc; its purpose is to allow class initialization that is otherwise only possible via a metaclass).
class Component:
def __init_subclass(cls, **kwargs):
super().__init_subclass__(**kwargs)
try:
p = cls.status
except AttributeError:
raise ValueError("Class does not define 'status' attribute")
if not isinstance(p, property):
raise ValueError("'status' is not a property")
if p.fget is None:
raise ValueError("'status' has no getter")
if p.fset is None:
raise ValueError("'status' has no setter")
This is actually an improvement over abc, in my opinion. If a subclass fails to define a read/write status property, an exception will be raised when the class is defined, not just when you attempt to instantiate the class.
In a class, I want to define N persistent properties. I can implement them as follow:
#property
def prop1(self):
return self.__prop1
#prop1.setter
def prop1(self, value):
self.__prop1 = value
persistenceManagement()
#property
def prop2(self):
return self.__prop2
#prop2.setter
def prop2(self, value):
self.__prop2 = value
persistenceManagement()
[...]
#property
def propN(self):
return self.__propN
#propN.setter
def propN(self, value):
self.__propN = value
persistenceManagement()
Of course, the only different thing between these blocks is the property name (prop1, prop2, ..., propN). persistenceManagement() is a function that has to be called when the value of one of these property changes.
Since these blocks of code are identical except for a single information (i.e., the property name), I suppose there must be some way to replace each of these blocks by single lines declaring the existence of a persistent property with a given name. Something like
def someMagicalPatternFunction(...):
[...]
someMagicalPatternFunction("prop1")
someMagicalPatternFunction("prop2")
[...]
someMagicalPatternFunction("propN")
...or maybe some decorating trick that I cannot see at the moment. Is someone has an idea how this could be done?
Properties are just descriptor classes and you can create your own and use them:
class MyDescriptor(object):
def __init__(self, name, func):
self.func = func
self.attr_name = '__' + name
def __get__(self, instance, owner):
return getattr(self, self.attr_name)
def __set__(self, instance, value):
setattr(self, self.attr_name, value)
self.func(self.attr_name)
def postprocess(attr_name):
print 'postprocess called after setting', attr_name
class Example(object):
prop1 = MyDescriptor('prop1', postprocess)
prop2 = MyDescriptor('prop2', postprocess)
obj = Example()
obj.prop1 = 'answer' # prints 'postprocess called after setting __prop1'
obj.prop2 = 42 # prints 'postprocess called after setting __prop2'
Optionally you can make it a little easier to use with something like this:
def my_property(name, postprocess=postprocess):
return MyDescriptor(name, postprocess)
class Example(object):
prop1 = my_property('prop1')
prop2 = my_property('prop2')
If you like the decorator # syntax, you could do it this way (which also alleviates having to type the name of the property twice) -- however the dummy functions it requires seem a little weird...
def my_property(method):
name = method.__name__
return MyDescriptor(name, postprocess)
class Example(object):
#my_property
def prop1(self): pass
#my_property
def prop2(self): pass
The property class (yes it's a class) is just one possible implementation of the descriptor protocol (which is fully documented here: http://docs.python.org/2/howto/descriptor.html). Just write your own custom descriptor and you'll be done.
I have a class LabelMapper (a boost::python class), which implements the dictionary protocol. I would like to have a proxy class which will use attributes for accessing that dicionary. I've seen many posts for overriding __setitem__ and __getitem__ but I can't seem to get it right.
The naive approach (below) leads to infinite recursion due to self.mapper invoking LabelMapperProxy.__getattr__, which in turn needs self.mapper and so on.
class LabelMapper(object):
def __init__(self): self.map={}
def __getitem__(self,key): return self.map[key]
def __setitem__(self,key,val): self.map[key]=val
def __delitem__(self,key): del self.map[key]
class LabelMapperProxy(object):
def __init__(self,mapper): self.mapper=mapper
def __getattr__(self,key): return self.mapper[key]
def __setattr__(self,key,val): self.mapper[key]=val
def __delattr__(self,key): del self.mapper[key]
lm=LabelMapper()
lm['foo']=123
# construct the proxy
lmp=LabelMapperProxy(mapper=lm)
print lmp.foo # !!! recursion
lmp.bar=456
print lmp.bar,lm['bar']
What is the solution? Perhaps is there such a proxy pre-cooked in the standard library?
You are trying to set a new attribute on your Proxy instance:
class LabelMapperProxy(object):
def __init__(self, mapper): self.mapper = mapper
This triggers a __setattr__, which tries to access the non-existent self.mapper attribute, so __getattr__ is consulted (which is called for all missing attributes). And __getattr__ tries to access self.mapper....
The solution is to set mapper directly in self.__dict__:
class LabelMapperProxy(object):
def __init__(self, mapper): self.__dict__['mapper'] = mapper
Alternatively, use the original baseclass __setattr__ just for the mapper attribute:
class LabelMapperProxy(object):
def __init__(self, mapper): self.mapper = mapper
def __setattr__(self, key, val):
if key == 'mapper':
return super(LabelMapperProxy, self).__setattr__(key, val)
self.mapper[key] = val
Here is the trap:
class LabelMapperProxy(object):
def __init__(self, mapper):
# This will not assign this object's attribute
# since __setattr__ is overriden.
# Instead, it will do self.mapper['mapper'] = mapper
self.mapper=mapper
def __getattr__(self, key):
# And this won't find `self.mapper` and resort to __getattr__
# (which is itself)
return self.mapper[key]
def __setattr__(self, key, val):
self.mapper[key]=val
def __delattr__(self, key):
del self.mapper[key]
I've written the following wrapper class. I want to define __setattr__ such that it redirects all attributes to the wrapped class. However, this prevents me from initializing the wrapper class. Any elegant way to fix this?
class Wrapper:
def __init__(self, value):
# How to use the default '__setattr__' inside '__init__'?
self.value = value
def __setattr__(self, name, value):
setattr(self.value, name, value)
You are catching all assignments, which prevents the constructor from assigning self.value. You can use self.__dict__ to access the instance dictionary. Try:
class Wrapper:
def __init__(self, value):
self.__dict__['value'] = value
def __setattr__(self, name, value):
setattr(self.value, name, value)
Another way using object.__setattr__:
class Wrapper(object):
def __init__(self, value):
object.__setattr__(self, 'value', value)
def __setattr__(self, name, value):
setattr(self.value, name, value)
A way to disable the __setattr__ until after initialization without changing the self.value = value syntax in the __init__ method is covered here. In short, embed knowledge of initialization in the object and use it in the __setattr__ method. For your Wrapper:
class Wrapper:
__initialized = False
def __init__(self, value):
self.value = value
self.__initialized = True
def __setattr__(self, name, value):
if self.__initialized:
# your __setattr__ implementation here
else:
object.__setattr__(self, name, value)
With __getattr__ overridden as well::
class Wrapper:
def __init__(self,wrapped):
self.__dict__['wrapped'] = wrapped
def __setattr__(self,name,value):
setattr(self.__dict__['wrapped'],name,value)
def __getattr__(self,name):
return getattr(self.__dict__['wrapped'],name)
class A:
def __init__(self,a):
self.a = a
wa = Wrapper(A(3))
#wa.a == wa.wrapped.a == 3
As suggested in other answers, one idea is to directly access the object dictionary to bypass setattr resolution.
For something easy to read, I suggest the following:
def __init__(self,wrapped1, wrapped2):
vars(self).update(dict(
_wrapped1=wrapped1,
_wrapped2=wrapped2,
))
Using vars is optional, but I find it nicer than directly accessing self.__dict__, and the inline dict() notation allows for grouping all instance variable initialization in a visible block with minimum boilerplate code overhead.