Hi I want to define an object value as a sum of values of two objects of the same class before I know what the value of those 2 objects is.
I need to do something like:
`A=: B+C
B=10
C=20
print A`
I have a class Set and I'm trying something like:
class Set(object):
def __init__(self, w):
self.value=w
a=Set
c=a
a(10)
print c
But c is still class instead of object instance. Can somebody help me?
a is a class Set and so is c. a(10) generates an instance but discards it right away. You need to create instances and assign values later. Something like that:
class Sum(object):
def __init__(self, *values):
self.values = values
#property
def value(self):
return sum(v.value for v in self.values)
class Value(object):
def __init__(self, value=0):
self.value=value
b = Value()
c = Value()
a = Sum(b,c)
b.value = 10
c.value = 20
print a.value
Related
Is it possible to access superclass's attributes during class construction?
Here's my code:
class A:
x = 1
class B(A):
x += 1 # <- error
The increment line x += ... is not valid, because x is not defined at this moment. You may suggest doing it in __init__, but I need to initialize the values before the constructor and want to minimize the code.
The code x = A.x + 1 will not work in my case because the A is generated in run-time. So the real code for B looks like
class A:
x: int
def class_gen(params):
class SubA(A):
x = 1
return SubA
class B(class_gen(some_params)):
x += 1
I've found a weird workaround:
x = A.__subclasses__()[-1].x + 1 (indeed the last subclass of A will be the generated super), but it looks too dirty and unstable.
Another workaround is declaring the a 'stub' class variable:
...
_Stub = class_gen(some_params)
class B(_Stub):
x = _Stub.x + 1
but is it also looks urgly. Is there a better way for a perfectionist?
I think you can accomplish it by using __new__ in the subclass.
class A:
x = 1
class B(A):
def __new__(cls, *args, **kwargs):
cls.x += 1
return super().__new__(cls, *args, **kwargs)
b = B()
print(b.x) # 2
There's no easy way to do this. Probably the best is to give your B class a metaclass that handles incrementing of the x attribute for you:
class XIncrementerMeta(type):
def __new__(mcls, name, bases, namespace):
namespace['x'] = bases[0].x + 1
return super().__new__(mcls, name, bases, namespace)
class B(class_gen("some_params"), metaclass=XIncrementerMeta):
pass
print(B.x) # prints 2
If you need each B-like class to have its own kind of manipulation of the x value, you could put it in a classmethod and have an inherited metaclass call it. Or you could even have an __init_subclass__ method in A that calls methods to set the value on its subclasses:
class A:
def __init_subclass__(cls):
cls.set_X()
class SubA(A):
#classmethod
def set_X(cls):
cls.x = 1
class B(SubA):
#classmethod
def set_X(cls):
super().set_X() # get SubA to set an initial value
cls.x += 1 # then update it
print(B.x) # prints 2
I have a class A object method which uses another class B object's method, which the argument is class A object.
class A():
def calculate(self):
B = B.calculator(A)
class B():
def calculator(self, A):
...do something with A.attributes
It is possible to just pass attributes into the object, but I would see this possibility as the last priority. I am definitely a bit oversimplify my case, but I am wondering if there is a way to pass the entire class
Edit:
Sorry for the confusion. At the end I am trying to call class A object and A.calculate(), which will call class B obj and calculator function.
class A():
def __init__(self, value):
self.value = value
def calculate(self):
Bobj = B()
Bobj.calculator(A)
class B():
def calculator(self, A):
...do something with A.value
def main():
Aobj = A(value)
Aobj.calculate()
Your scenario does not currently indicate that you want to use any information from B when calculating A. There are a few ways of getting the functionality that you want.
Scenario: B stores no information and performs calculation. B should be a function
def B(value):
```do something with value```
return
class A():
def __init__(self, value):
self.value = value
def calculate(self):
return B(self.value)
def main():
Aobj = A(value)
Aobj.calculate()
Scenario: B stores some other information, but internal B information is not needed for the calculation. B should have a static method
class B():
#staticmethod
def calculate(value):
```do something with value```
return
class A():
def __init__(self, value):
self.value = value
def calculate(self):
return B.calculate(self.value)
def main():
Aobj = A(value)
Aobj.calculate()
I want to create a proxy in Python because of function and attributes access (something like private). I create the proxy with references to functions in the source object. But I have a problem, that functions have no problem with changing attributes but property yes. Here is an example:
A working example
class A:
def __init__(self):
self.value = 1
def get_value(self):
return self.value
class Proxy:
def __init__(self, cls):
self.get_value = cls.get_value
# del cls
a = A()
p = Proxy(a)
print(a.get_value(), p.get_value())
a.value = 2
print(a.get_value(), p.get_value())
Output:
1 1
2 2
Not working:
class A:
def __init__(self):
self.value = 1
#property
def get_value(self):
return self.value
class Proxy:
def __init__(self, cls):
self.get_value = cls.get_value
# del cls
a = A()
p = Proxy(a)
print(a.get_value, p.get_value)
a.value = 2
print(a.get_value, p.get_value)
Output:
1 1
2 1
Can someone explain me where the problem is and if there is any solution for this? I could use functions, but I think #property is more Python solution. And I really want to know what is the difference. Thank you
In Proxy.__init__, you end up executing:
self.get_value = a.get_value
and very different things happen in your two examples.
In the first case, a.get_value is a method of a. So, calling p.get_value() is the same as calling a.get_value(). You get identical results.
In the second case, you have already defined a.get_value as a property, so self.get_value = a.get_value is basically self.get_value = 2, it is just an int attribute of p.
Let's say I have a class. I want this class to have attribute x so that whenever I use the class without instantiating, I can both call the current value of x and when I change the value of x, to run a method that takes the value I put in x and does something else with it.
"Example" is a class:
[IN]: Example(y).x
[OUT]: 0
[IN]: Example(y).x=2
[OUT]: x(2)=6
[IN]: Example(y).x
[OUT]: 6
Sorry if this turns out to be banal. I tried searching and didn't come up with anything.
Example's x value must have a paired y value that belongs to the particular class.
You can override the __setattr__ method on your class:
class Test(object):
def foo(self, v):
return v + 1
def __setattr__(self, attribute, v):
return super(Test, self).__setattr__(attribute, self.foo(v))
t = Test()
t.a = 1 # t == 2
Here's how you do this:
values = {}
class Example(object):
def __init__(self,y):
self.y=y
#property
def value(self):
values[self.y]=some_data_object_method(self.y)
return some_data_object_method(self.y)
#value.setter
def value(self,new_value):
if new_value not in values.itervalues():
some_data_object_method(self.y) = new_value
Simple as that. Probably ended up being banal after all.
Assume that we have an object k of type class A. We defined a second class B(A). What is the best practice to "convert" object k to class B and preserve all data in k?
This does the "class conversion" but it is subject to collateral damage. Creating another object and replacing its __dict__ as BrainCore posted would be safer - but this code does what you asked, with no new object being created.
class A(object):
pass
class B(A):
def __add__(self, other):
return self.value + other
a = A()
a.value = 5
a.__class__ = B
print a + 10
a = A() # parent class
b = B() # subclass
b.value = 3 # random setting of values
a.__dict__ = b.__dict__ # give object a b's values
# now proceed to use object a
Would this satisfy your use case? Note: Only the instance variables of b will be accessible from object a, not class B's class variables. Also, modifying variables in a will modify the variable in b, unless you do a deepcopy:
import copy
a.__dict__ = copy.deepcopy(b.__dict__)
class A:
def __init__(self, a, b):
self.a = a
self.b = b
class B(A):
def __init__(self, parent_instance, c):
# initiate the parent class with all the arguments coming from
# parent class __dict__
super().__init__(*tuple(parent_instance.__dict__.values()))
self.c = c
a_instance = A(1, 2)
b_instance = B(a_instance, 7)
print(b_instance.a + b_instance.b + b_instance.c)
>> 10
Or you could have a sperate function for this:
def class_converter(convert_to, parent_instance):
return convert_to(*tuple(parent_instance.__dict__.values()))
class B(A):
def __init__(self, *args):
super().__init__(*args)
self.c = 5
But using the 2nd method, I wasn't able to figure out how to pass additional values