I need a Multi-level #property decorator.
I have a base class Base
I have a wrapper class Wrapper
Wrapper wraps Base and when Base is changed, it needs to be reflected to View
I want to ensure that the change is reflected
Example of what I need
class Base:
def __init__(self):
self.attribute = 0
#property
def attribute(self):
return self._attribute
#attribute.setter
def attribute(self, value):
self._attribute = value
class Wrapper:
def __init__(self, view: View, base: Base):
self.base = base
self.view = view
#property
def base.attribute(self):
return self.base.attribute
#base.attribute.setter
def base.attribute(self, value):
self.base.attribute = value
self.view.update(value)
I know I can simply do the following.
def base_attribute(self, value = None):
if value:
self.base.attribute = value
self.view.update(value)
return self.base.attribute
But since I used #property in Base, I wanted to keep that style.
Related
I want to create python class with read only properties.
Please see this example:
class ClassProperty(object):
def __init__(self, getter):
self.getter = getter
def __get__(self, instance, owner):
return self.getter(owner)
class Constants(object):
#ClassProperty
def version(cls):
return '1.0.11'
So under this (cls) word i have this message:
Usually first parameter of method is named self
So i wonder is i need to declare it this way:
class Constants(object):
#ClassProperty
def version(self):
return '1.0.11'
And in this way the message disappear
How to override an inherited class method, that needs to query for specific properties on the child class?
I'm not sure how to go about this. This is what I've got:
class base_class:
#classmethod
def a_method(cls, something):
return ndb.Query(kind=cls.__name__).fetch(keys_only=True)
#classmethod
def calls_a_method(cls, size=1, soemthing):
entity_keys = cls.a_method(something)
class child_class(base_class):
a_property = ndb.BooleanProperty()
def another_method():
stuff = child_class.calls_a_method() #?
How do I override a_method from the base_class, such that it will also filter out keys where a_property = False for the child_class?
I think that if you break up the query across the methods, you can construct a custom query in the child class:
class base_class:
#classmethod
def a_method(cls, something):
return ndb.Query(kind=cls.__name__)
#classmethod
def calls_a_method(cls, size=1, something):
entity_keys = cls.a_method(something).fetch(keys_only=True)
class child_class(base_class):
a_property = ndb.BooleanProperty()
#classmethod
def another_method(cls):
q = cls.a_method(something).filter(cls.a_property == False)
entity_keys = q.fetch(keys_only=True)
How about something like this?
class base_class(ndb.Model):
#classmethod
def a_method(cls, something):
return cls.Query().fetch(keys_only=True)
#classmethod
def calls_a_method(cls, something):
entity_keys = cls.a_method(something)
class child_class(base_class):
a_property = ndb.BooleanProperty()
#classmethod
def another_method(cls, value):
return cls.calls_a_method(value)
#classmethod
def a_method(cls, something):
return cls.query(cls.a_property==something).fetch(keys_only=True)
class Event(metaclass=ABCMeta):
def __init__(self):
self.type = self.get_full_type()
#classmethod
def get_full_type(cls):
return None
def as_dict(self):
return self.__dict__
class BaseEvent(Event, metaclass=ABCMeta):
SUB_TYPE = ''
#classmethod
def get_base_type(cls):
return super().get_full_type()
#classmethod
def get_full_type(cls):
base_type = cls.get_base_type()
if base_type:
return '.'.join([base_type, cls.SUB_TYPE])
else:
return cls.SUB_TYPE
Here you can see my attempt to make class that represents some abstract event. What is crucial here is the ability to distinguish event types. So every event has it's type and it's base type. Full type is base type + subtype.
This gives the ability to define new event type like this
class MockEvent(BaseEvent):
SUB_TYPE = 'mock'
def __init__(self, some_object):
super(self.__class__, self).__init__()
self.some_object = some_object
So the full type is mirroring the class hierarchy ClassA.ClassB.ClassC etc. I think you get the point.
Unfortunately this is not working with python 2
class Event(object):
__metaclass__ = ABCMeta
SUB_TYPE = None
def __init__(self):
self.type = self.get_full_type()
#classmethod
def get_base_type(cls):
return None
#classmethod
def get_full_type(cls):
base_type = cls.get_base_type()
if base_type:
return '.'.join([base_type, cls.SUB_TYPE])
else:
return cls.SUB_TYPE
def as_dict(self):
return self.__dict__
class BaseEvent(Event):
__metaclass__ = ABCMeta
SUB_TYPE = ''
#classmethod
def get_base_type(cls):
return super(cls.__class__, cls).get_full_type()
File "/opt/leos/code/event_service/events/EventBus.py", line 38, in
get_base_type
return super(cls.class, cls).get_full_type()
AttributeError: 'super' object has no attribute 'get_full_type'
How can I make this work?
class Event(object):
__metaclass__ = ABCMeta
def __init__(self):
self.type = self.get_full_type()
#classmethod
def get_full_type(cls):
return None
def as_dict(self):
return self.__dict__
class BaseEvent(Event):
__metaclass__ = ABCMeta
SUB_TYPE = None
#classmethod
def get_full_type(cls):
super_type = cls.get_super_type()
base_type = super_type.get_full_type()
if base_type:
return '.'.join([base_type, cls.SUB_TYPE])
else:
return cls.SUB_TYPE
#classmethod
def get_super_type(cls):
return cls.__base__
I needed to get the base type automatically. Without mentioning current class in super(currectClass, self) So I used cls.base and it's working ok.
I want a python class that is composed partly of specific methods from other classes which operates on self in the "composed class". How do I do that?
E.g. if I want to include specific methods from classA and classB in my new class "theClass":
# Some classes to "inherit" from
class classA(object):
def methA1(self, value):
self.attrib = value*1
def methA2(self, value):
self.attrib = value*2
class classB(object):
def methB1(self, value):
self.attrib = value*3
def methB2(self, value):
self.attrib = value*4
# The class I want to build
class theClass(object):
# WHAT TO DO HERE?
# -------------------
methA1 = classA.methA1
methB2 = classB.methB2
# -------------------
# /WHAT TO DO HERE
# add additional methods...
def methC(self, value):
self.attrib = value*5
# I want the following behavior
instance = theClass()
instance.methB2(5) # sets instance.attrib to 20
instance.methA2(5) # error, does not exist
You could use mixins:
class MixinA1(object):
def methA1(self, value):
self.attrib = value*1
class MixinB2(object):
def methB2(self, value):
self.attrib = value*4
class classA(MixinA1):
def methA2(self, value):
self.attrib = value*2
class classB(MixinB2):
def methB1(self, value):
self.attrib = value*3
# The class I want to build
class theClass(MixinA1, MixinB2):
def methC(self, value):
self.attrib = value*5
Mixins make sense if the Mixin class encapsulates some unit of functionality which you desire to add on to multiple classes.
If the methods don't naturally break down into units of functionality,
here is another alternative:
def methA1(self, value):
self.attrib = value*1
def methA2(self, value):
self.attrib = value*2
def methB2(self, value):
self.attrib = value*4
def methB1(self, value):
self.attrib = value*3
def methC(self, value):
self.attrib = value*5
class classA(object):
methA1 = methA1
methA2 = methA2
class classB(object):
methB1 = methB1
methB2 = methB2
class theClass(object):
methA1 = methA1
methB2 = methB2
methC = methC
This is very similar to the alternative you've already posted, except that it places except that it places all classes on an equal footing -- initially the methods are not associated with any particular class. This might be preferable so theClass is not "breaking encapsulation" by reaching in and nabbing a method from a class (such as classA) on which it does not explicitly depend.
I have a pattern that looks similar to the following:
class Foobar(object): # instances of this class will be referenced by others
def __init__(self, value):
self.value = value
class Foo(object):
def __init__(self, value, foobar)
self.value = value
if isinstance(foobar, Foobar):
self.foobar = foobar
else:
self.foobar = Foobar(foobar)
class Bar(object):
def __init__(self, value, foobar)
self.value = value
if isinstance(foobar, Foobar):
self.foobar = foobar
else:
self.foobar = Foobar(foobar)
This allows Foo and Bar to take either a new value (to create a Foobar) or an existing instance of Foobar as their foobar argument.
I would like to get rid of this redundant code:
# ...
if isinstance(foobar, Foobar):
self.foobar = foobar
else:
self.foobar = Foobar(foobar)
I considered the following, but it doesn't work due to infinite recursion in Foobar.__new__():
class Foobar(object):
def __new__(cls, value):
if isinstance(value, cls):
return value
else:
return Foobar(value)
def __init__(self, value):
self.value = value
class Foo(object):
def __init__(self, value, foobar)
self.value = value
self.foobar = Foobar(foobar)
class Bar(object):
def __init__(self, value, foobar)
self.value = value
self.foobar = Foobar(foobar)
What is the best way to allow classes to create new instances or use existing instances depending on the values passed to __init__?
You can get rid of the recursion by calling the base class __new__():
class Foobar(object):
def __new__(cls, value):
if isinstance(value, cls):
return value
else:
return object.__new__(cls, value)
def __init__(self, value):
self.value = value
Note that the first parameter to __new__() is a class, not self.
That said, I'm not convinced that this is a useful pattern. In general, I'd recommend to accept instances in the constructor and leave the object construction to the calling code. While magic that does the Right Thing often seems convenient, it usually causes more problems down the road than it is worth.
Another option would be to factor out the duplicated code with a mixin class...
class Foobar(object):
def __init__(self, value):
self.value = value
class FoobarMixin(object):
def __init__(self, **kwargs):
foobar = kwargs['foobar']
if isinstance(foobar, Foobar):
self.foobar = foobar
else:
self.foobar = Foobar(foobar)
class Foo(FoobarMixin):
def __init__(self, value, **kwargs):
super(Foo, self).__init__(**kwargs)
self.value = value
print self.value, self.foobar
class Bar(FoobarMixin):
def __init__(self, value, **kwargs):
super(Bar, self).__init__(**kwargs)
self.value = value
print self.value, self.foobar
foo = Foo('foo', foobar='foobar')
bar = Bar('bar', foobar=Foobar('foobar'))
...which prints...
foo <__main__.Foobar object at 0x7fa0fedf6050>
bar <__main__.Foobar object at 0x7fa0fedeaf10>