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.
Related
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.
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)
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>
I have a class that contains a static dictionary:
class MyClass:
my_dict = {}
def __init__(self, name):
self.name = name
MyClass.my_dict[self.name] = []
def __call__(self, data):
MyClass.my_dict[self.name].append(data)
Whenever I want to update the dictionary, I have to use MyClass.my_dict[key], but I'd like the class itself to support item assignment so I can just use MyClass[key] to do the same thing. Is there a way to do this? I'm using Python 2.7.
So, here's what I ended up doing:
class MyClassType(type):
my_dict = {}
def __getitem__(cls, key):
return cls.my_dict[key]
def __setitem__(cls, key, value):
cls.my_dict[key] = value
def __str__(cls):
return cls.my_dict.__str__()
def iteritems(cls):
return cls.my_dict.iteritems()
class MyClass(object):
__metaclass__ = MyClassType
def __init__(self, name):
self.name = name
MyClass[self.name] = []
def __call__(self, data):
MyClass[self.name].append(data)
I have some classes:
class Window(object):
def __init__(self, name):
self.wind_name = name
def getWindowName(self):
return 'wnd' + self.wind_name
class Control(object):
def __init__(self, name, wnd):
self.contrl_name = name
setattr(self, 'getWindowName', wnd.getWindowName)
setattr(self, 'wind_name', wnd.wind_name)
def getControlName(self):
return (self.getWindowName(), 'unk' + self.contrl_name)
class Button(Control):
def __init__(self, name, wnd):
super(Button, self).__init__(name, wnd)
def getControlName(self):
return (self.getWindowName(), 'btn' + self.contrl_name)
wnd = Window('MyApp')
btnOK = Button('OK', wnd)
btnOK.getControlName() # work ok., return ('wndMyApp', 'btnOK')
btnOK.wind_name = 'NewApp'
btnOK.getControlName() # does not work properly., return ('wndMyApp', 'btnOK')
How can I extend the class Control|Button from the object of class Window to access the functions getWindowName and field wind_name in objects btnOK?
Is there a way without creating a field self.wnd = wnd in class Control, or add method setWindowName in Window...?
I can not inherit class Control from the class Window! This is not logical.
Python allows inheriting from multiple classes, i.e.
class Button(Control, Window):
...
But in this case you should know exactly what you are doing (speaking of Pythons Method Resolution Order (MRO)). I'd recommend reading this small book: Python Attributes and Methods.
You can use property for attributes
class Window(object):
def __init__(self, name):
self.wind_name = name
def getWindowName(self):
return 'wnd' + self.wind_name
class Control(object):
def __init__(self, name, wnd):
self.contrl_name = name
self.wnd = wnd
setattr(self, 'getWindowName', wnd.getWindowName)
def get_wind_name(self):
return self.wnd.wind_name
def set_wind_name(self, v):
self.wnd.wind_name = v
wind_name = property(get_wind_name, set_wind_name)
def getControlName(self):
return (self.getWindowName(), 'unk' + self.contrl_name)
class Button(Control):
def __init__(self, name, wnd):
super(Button, self).__init__(name, wnd)
def getControlName(self):
return (self.getWindowName(), 'btn' + self.contrl_name)
wnd = Window('MyApp')
btnOK = Button('OK', wnd)
print btnOK.getControlName() # work ok., return ('wndMyApp', 'btnOK')
btnOK.wind_name = 'NewApp'
print btnOK.getControlName()