Suppose I have classes which have a common method (add), and I want to create a new class RandomPair which would contain a pair of objects of the same class and dispatch add to a random one.
E.g.,
class C1 (object):
def __init__ (self, title, plus = True):
self.title = title
self.plus = plus
self.acc = 0
def add (self, x):
if self.plus:
self.acc += x
else:
self.acc -= x
def __str__ (self):
return "C1(%s,%g)" % (self.title,self.acc)
class C2 (object):
def __init__ (self, title):
self.title = title
self.all = list()
def add (self, x, pos = None):
if pos:
self.all.insert(pos,x)
else:
self.all.append(x)
def __str__ (self):
return "C2(%s,%s)" % (self.title,self.all)
import random
class RandomPair (object):
def __init__ (self, klass, title, **kwargs):
self.objects = [klass(title + "#" + str(i), kwargs) for i in range(2)]
def add (self, *args, **kwargs):
self.objects[random.randint(0,1)].add(args,kwargs)
def __str__ (self):
return "\n".join([str(o) for o in self.objects])
Now, I want to be able to do
rp1 = RandomPair(C1,"test")
rp1.add(1)
rp1.add(2)
rp2 = RandomPair(C2,"test")
rp2.add(1)
rp2.add(2, pos=0)
but I get
TypeError: add() got multiple values for keyword argument 'self'
in self.objects[random.randint(0,1)].add(args,kwargs).
You need to apply the args and kwargs, using similar notation as when you defined the arguments. You need to do this in two places; in both RandomPair.__init__() and in RandomPair.add():
self.objects = [klass(title + "#" + str(i), **kwargs) for i in range(2)]
and
self.objects[random.randint(0,1)].add(*args, **kwargs)
otherwise you are just passing in two arguments, a tuple and a dictionary.
Your next problem is in C2.add(); you are using pos if it is empty; you want to inverse that test. Better still, test explicitly for None:
def add(self, x, pos=None):
if pos is None:
self.all.append(x)
else:
self.all.insert(pos,x)
Related
I am trying to inherit Python Class dict to modify its functionality. I would like it to return a self-determined value when the key is not present (i.e. override get rather than return None). I can do it using the following snippet but there is a problem:
class xDict(dict):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.__dict__ = self
self.out = 0
def reap(self, qw): #instead of *dict.get()*
if qw not in self.keys(): return self.out
else: return self.get(qw)
def modify(self, qw):
self.out = qw
l = xDict({'c':2,'x':1})
When I call l, it contains the the 'out' variable associated with the instance: {'c': 2, 'x': 1, 'out': 0}
I would like to avoid this being contained in the dictionary - is it possible?
I also tried using a class variable solution:
class xDict(dict):
#class variable
out = 0
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.__dict__ = self
def reap(self, qw):
if qw not in self.keys(): return xDict.out
else: return self.get(qw)
#classmethod #class method
def set_out(cls, x): #USE cls (equivalent to self)
cls.out = x
l1 = xDict({'c':2,'x':1})
l2 = xDict({'r':2, 'd':2})
But here I cannot set separate return values for each instance. For, example: l1.set_out("NA") causes any request to l2 to also return 'NA'
I want a self variable within init to update every time it is called e.g. every time I execute Data(10).plot, self.plot should reinitialise by parsing the self.n to the Plot class.
class Data(object):
def __init__(self, n):
self.n = n
self.plot = Plot(self.n)
def minus(self, x):
self.n -= x
return self.n
class Plot(object):
def __init__(self, n):
self.n = n
def double(self):
return self.n * 2
Another example: When I execute the following code, I want the answer variable to equal 16. Instead it equals 20. How do I implement this behaviour within the above classes?
data = Data(10)
data.minus(2)
answer = vcf.plot.double())
What you want is a property. This is a special type of attribute that calls a custom getter function when getting the value, so you can make it dynamically return the correct plot.
class Data(object):
def __init__(self, n):
self.n = n
#property
def plot(self):
return Plot(self.n)
def __sub__(self, x):
return Data(self.n - x)
As a side note, look at the data model to override python operators.
data = Data(10)
data -= 2
answer = data.plot.double() # Calls the `plot()` function to get a value for `data.plot`.
print(answer) # 16
Another way would be to link the Plot to the data, so when the data changes, the plot does to. A way to do it would be just to have it as an attribute, so when it changes, the attribute does too.
class Plot(object):
def __init__(self, data):
self.data = data
#property
def n(self):
return self.data.n
#n.setter
def n(self, x):
self.data.n = x
def double(self):
return self.n * 2
data = Data(10)
plot = Plot(data)
data.minus(2)
answer = plot.double() # 16
You don't need n in the Data-object:
class Data(object):
def __init__(self, n):
self.plot = Plot(n)
def minus(self, x):
self.plot.n -= x
class Plot(object):
def __init__(self, n):
self.n = n
def double(self):
return self.n * 2
I am trying Overloading an operator forcing it to return an object of the same instance of the current class not the parent class where the method was overloaded.
class Book:
def __init__(self,name,pages):
self.name=name
self.pages=pages
def __add__(self,other):
return Book(self.name,(self.pages + other.pages))
class Encyclopedia(Book):
def __init__(self,name,pages):
Book.__init__(self,name,pages)
a=Encyclopedia('Omina',234)
b=Encyclopedia('Omnia2',244)
ab=a+b
print ab
Out: <__main__.Book instance at 0x1046dfd88>
For instance in this case I would like to return an Encycolpedia instance (not a Book instance) without overloading another time the operator __add__ with the same line with Encyclopedia instead of Book I have tried:
return self(self.name,(self.pages + other.pages))
But it doesn't work.
What if the Class Enclcopedia has another attribute:
class Encyclopedia(Book):
def __init__(self,name,pages,color):
Book.__init__(self,name,pages)
self.color=color
You could utilize self.__class__ instead of casting to Book. Your original add function should look like:
def __add__(self,other):
return self.__class__(self.name,(self.pages + other.pages))
You would need to do it something like this, which overloads the base class's methods (in this case, generally by calling them first and then doing additional processing on the result — although that's not a requirement):
class Book(object):
def __init__(self, name, pages):
self.name = name
self.pages = pages
def __add__(self, other):
return Book(self.name, self.pages+other.pages)
def __str__(self):
classname = self.__class__.__name__
return '{}({}, {})'.format(classname, self.name, self.pages)
class Encyclopedia(Book):
def __init__(self, name, pages, color):
Book.__init__(self, name, pages)
self.color = color
def __add__(self, other):
tmp = super(Encyclopedia, self).__add__(other)
return Encyclopedia(tmp.name, tmp.pages, self.color+other.color)
def __str__(self):
classname = self.__class__.__name__
return '{}({!r}, {}, {!r})'.format(classname, self.name, self.pages,
self.color)
a = Encyclopedia('Omina', 234, 'grey')
b = Encyclopedia('Omnia2', 244, 'blue')
ab = a+b
print(ab) # -> Encyclopedia('Omina', 478, 'greyblue')
Lets assume I've a class A which has a bunch of methods, but I want it to run certain lines before and after each method is called.
For example: I want my class Dog here to run before() and after() every time bark() or run() are been called.
class Dog():
def __init__(self, sound, speed):
self.sound = sound
self.speed = speed
def before(self):
check_some_things(self)
def after(self):
do_some_things(self)
def bark(self):
sound(self.sound)
def run(self):
move(self.speed)
You could encapsulate this in a decorator; the following decorator will call before and after if these are available on self:
import inspect
from functools import wraps
def before_and_after(f):
#wraps(f)
def wrapper(self, *args, **kw):
if hasattr(self, 'before') and inspect.ismethod(self.before):
self.before()
result = f(self, *args, **kw)
if hasattr(self, 'after') and inspect.ismethod(self.after):
self.after()
return result
return wrapper
then simply apply to the methods that should be wrapped:
class Dog():
def __init__(self, sound, speed):
self.sound = sound
self.speed = speed
def before(self):
check_some_things(self)
def after(self):
do_some_things(self)
#before_and_after
def bark(self):
sound(self.sound)
#before_and_after
def run(self):
move(self.speed)
The decorator assumes it is used on methods, e.g. the produced wrapper expects self as a first argument.
If this needs to apply to all methods that are not before or after, perhaps a metaclass is in order:
class BeforeAfterMeta(type):
def __new__(mcs, classname, bases, body):
for name, value in body.items():
if not inspect.isfunction(value):
continue
if name in ('before', 'after') or name[:2] + name[-2:] == '_' * 4:
# before or after hook, or a special method name like __init__.
continue
body[name] = before_and_after(value)
return super(BeforeAfterMeta, mcs).__new__(mcs, classname, bases, body)
which you then can apply to your class:
class Dog(metaclass=BeforeAfterMeta):
def __init__(self, sound, speed):
self.sound = sound
self.speed = speed
def before(self):
check_some_things(self)
def after(self):
do_some_things(self)
def bark(self):
sound(self.sound)
def run(self):
move(self.speed)
You could also use a decorator function to inspect your class Dog if the pre and post methods exists and override the run method:
def PrePostMethod(inputClass):
mainRun = inputClass.run
beforeFunc = inputClass.before if "before" in inputClass.__dict__ else None
afterFunc = inputClass.after if "after" in inputClass.__dict__ else None
def new_run(self, *args, **kwargs):
# you could inspect the given arguments if you need
# to parse arguments into before and the after methods
if beforeFunc:
self.before()
mainRun(self)
if afterFunc:
self.after()
inputClass.run = new_run
return inputClass
#PrePostMethod
class Dog(object):
def __init__(self, sound, speed):
self.sound = sound
self.speed = speed
def before(self):
print "Do stuff before"
def after(self):
print "Do stuff after"
def run(self):
print "Do main process"
Dog(1,2).run()
To parse arguments and keywords arguments from run into before and after, use the class inspect and loop through the args and kwargs to parse the right ones.
from inspect import getargspec
def argHandler(method, *args, **kwargs):
method = getargspec(method)
mArgs = method.args
mKwargs = method.keywords
rArgs = args[:len(mArgs)-1]
rKwargs = { k:v for k,v in kwargs.iteritems() if k in mKwargs }
leftArgs = len(mArgs)-len(rArgs)
if len(rKwargs):
rKwargs = [ rKwargs[k] for k in mArgs[:leftArgs-1]]
rArgs += rKwargs
return rArgs
def PrePostMethod(inputClass):
mainRun = inputClass.run
beforeFunc = inputClass.before if "before" in inputClass.__dict__ else None
afterFunc = inputClass.after if "after" in inputClass.__dict__ else None
def new_run(self, *args, **kwargs):
if beforeFunc:
nargs = argHandler(self.before, *args, **kwargs)
if nargs: self.before( *nargs)
else: self.before()
nargs = argHandler(mainRun, *args, **kwargs)
if nargs: mainRun(self, *nargs)
else: mainRun(self)
if afterFunc:
nargs = argHandler(self.after, *args, **kwargs)
if nargs: self.after( *nargs)
else: self.after()
inputClass.run = new_run
return inputClass
You can use many different ways to do this. But I think the best way is, to define a class with the Pre- and Post-Methods and redefine it's object hidden methods: __enter__ and __exit__. To use them, just call the class with the compound statement with.
class pre_post(object):
def __enter__(self):
print "Enter check method.."
def __exit__(self, type, value, tb):
print "Exit check method.."
class dog(object):
def run(self, checkups=True):
if checkups:
with pre_post() as pp:
print "My stuff.."
else:
print "My stuff.."
dog().run(True)
This will give you the following result:
Enter check method..
My stuff..
Exit check method..
I hope that will help you.
I'm trying to design a descriptor class which I can use through other class which is a subclass of a class which is a subclass of a class.
class MyDescriptorClass(object):
def __init__(self, owner, name, activates = 0):
self.value = None
self.name = name
self.owner = owner
self.activates = 0
self.connects = []
def __set__(self, obj, val):
self.set(val)
def __get__(self, instance, owner):
return self.value
def set(self, value):
if self.value == value:
return 0
self.value = value
if self.activates:
self.owner.evaluate()
def connect(self, inputs):
if not isinstance(inputs, list):
inputs = list(inputs)
for input in inputs:
self.connects.append(input)
class ParentClass(object):
def __init__(self, name):
self.states = {}
self.name = name
self.A = MyDescriptorClass(self, name, activates = 1)
self.B = MyDescriptorClass(self, name, activates = 1)
self.states.setDefault('A', self.A)
self.states.setDefault('B', self.B)
class ChildClass1(ParentClass):
def __init__(self, name)
super(ChildClass1, self).__init__(name)
self.ans = None
def evaluate(self):
self.ans = self.A.value + self.B.value
class ChildClass2(ParentClass):
def __init__(self, name)
super(ChildClass1, self).__init__(name)
self.ans = None
def evaluate(self):
self.ans = self.A.value * self.B.value
self.A = MyDescriptorClass() will not work according to the python docs
so the only way is that I declate A = MyDescriptorClass() in the ParentClass as
class ParentClass(object):
A = MyDescriptorClass() # here I am unable to pass the owner
And since, I'm using a child class, super call skips this part and starts directly with __init__
Is there any way in which I can modify the design so as to set the value of ChildClass1.A instance directly?
c = ChildClass1("c1")
c.A = 10 # I directly want to set this value instead of using c.A.set(10)
c.B = 20
c.evaluate()
print c.ans # 30
c.B = 40
print c.ans # 50
Try not to put information which is specific to instances in the descriptor. Keep information specific to instances in instance attributes, and keep information specific to the descriptor (like activates) in the descriptor:
class MyDescriptorClass(object):
def __init__(self, activates = 0):
self.value = None
self.activates = activates
self.connects = []
def __set__(self, instance, val): # 1
if self.value == val:
return 0
self.value = val
if self.activates:
instance.evaluate()
def __get__(self, instance, instcls): # 1
return self.value
Note that the __set__ and __get__ methods are passed the
instance which is accessing the descriptor. Therefore, you do not
need to store the owner in MyDescriptor. The instance is the
owner.
Given the clarification of the problem in the comments below, here is how I would implement the descriptor.
class GateInput(object):
def __init__(self, index):
self.index = index # 4
def __get__(self, inst, instcls):
return inst.inputs[self.index].ans # 5
def __set__(self, inst, val):
if isinstance(val, (float, int)):
inst.inputs[self.index] = Constant(val)
else:
inst.inputs[self.index] = val
class Constant(object):
def __init__(self, val):
self.ans = val
class Gate(object):
A = GateInput(0) # 1
B = GateInput(1) # 1
def __init__(self, name):
self.name = name
self.inputs = [Constant(0), Constant(0)] # 2
class Adder(Gate):
#property
def ans(self):
result = 0
for gate in self.inputs:
result += gate.ans # 3
return result
class Multiplier(Gate):
#property
def ans(self):
result = 1
for gate in self.inputs:
result *= gate.ans
return result
b = Multiplier('b1')
b.A = 2
b.B = 3
print(b.A)
# 2
print(b.ans)
# 6
c = Adder('c1')
c.A = 10
print(c.ans)
# 10
# This connects output of b to an input of c
c.B = b
print(c.ans)
# 16
Descriptors have to be defined as class attributes, not instance
attributes. Since the descriptor is accessed by all instances, you
probably do not want the descriptor to change merely because an
instance is being created. Therefore, do not instantiate the
descriptor in __init__.
Each instance of Gate has a list of inputs. The items self.inputs
are instances of Constant or Gate.
Here we see the purpose of the Constant class. For every gate,
gate.ans needs to return a value.
The index records which item in inst.inputs the GateInput is
connected to.
inst is an instance of Gate. For example, c.A causes Python to
call GateInput.__get__(self, c, type(c)). Thus, inst is c
here.
As it is int he comments:
descriptors must be class attributes, not instance attributes in order to work -
so, to start with:
class ParentClass(object):
A = MyDescriptorClass()
B = MyDescriptorClass()
def __init__(self, name):
self.states = {}
self.name = name
self.A.configure(self, name, activates = 1)
self.B.configure(self, name, activates = 1)
self.states.setDefault('A', self.A)
self.states.setDefault('B', self.B)
And then you fix your Descriptor class accordingly:
either have then keeping all data refering to an instance in the instance itself
(that is why __get__ and __set__ receive the object itself) - or have
each descriptor instance have a dictionary where they can annotate data related
to the instances of the class they belong too, by, for example, object ID.
Your descriptor class could be more or less along these lines:
class MyDescriptorClass(object):
def __init__(self):
self.data = defaultDict(dict)
def configure(self, owner, name, activates = 0):
container = self.data(id(owner))
container["value"] = None
container["name"] = name
...
def __set__(self, owner, value):
# implemnt your previous "set" method straight here
...
...