I am trying to access the object of class b (self.variable) inside another class a, after class b has been inherited by class c and calls an instance of class a. I don't know how to access the instance of class b that was created during the inheritance init. Additionally, a needs to inherit from class k.
Optimal would be if I could access self.variable inside class a and further pass it on without explicitly referring to the instance of class b (namely, just calling it with self.variable instead of b.variable) and without changing the values I already assigned to the variables in class c (so no re-initializing it)
I'd appreciate any help, I've been at this for hours.
class k(object):
def __init__(self):
pass
class b(object):
def __init__(self):
self.variable = 1
class c(b):
def __init__(self):
b.__init__(self)# b is inherited from & initialized
# alternative for inheritance
#super(c,self).__init__()
print("init(): " + str(self.variable))
def run(self):
self.variable = 2
print("run(): " + str(self.variable))
a()# here I need to pass the instance of b
class a(k):
def __init__(self):
k.__init__(self)# a() needs to inherit from k()
# ERROR: cannot access variables of b()
print("a(): " + str(self.variable))
if __name__ == "__main__":
c().run()
I think I figured out how to do it.
If passing the instance is enough, this would work:
class k(object):
def __init__(self):
pass
class b(object):
def __init__(self):
self.bb = self.bb()
class bb:
def __init__(self):
self.variable = 1
class c(b):
def __init__(self):
b.__init__(self)# b is inherited from & initialized
# alternative for inheritance
#super(c,self).__init__()
print("init(): " + str(self.bb.variable))
def run(self):
self.bb.variable = 99
print("run(): " + str(self.bb.variable))
a(self)# pass instance of b
class a(k):
def __init__(self, bInstance):
k.__init__(self)# a() needs to inherit from k()
print("a(): " + str(bInstance.bb.variable))
if __name__ == "__main__":
c().run()
As I understand it, if I want to get there via self I'd need class a to inherit from class c and class c inherits and initializes class b, the call at the end is just a() (which does what I need it to do, since a inherits everything I need):
class k(object):
def __init__(self):
pass
class b(object):
def __init__(self):
self.bb = self.bb()
class bb:
def __init__(self):
self.variable = 1
class c(b):
def __init__(self):
b.__init__(self)# b is inherited from & initialized
# alternative for inheritance
#super(c,self).__init__()
print("init(): " + str(self.bb.variable))
def run(self):
self.bb.variable = 99
print("run(): " + str(self.bb.variable))
class a(k,c):
def __init__(self):
k.__init__(self)# a() needs to inherit from k()
c.__init__(self)
print("a(): " + str(self.bb.variable))
self.run()
print("a() #2: " + str(self.bb.variable))
if __name__ == "__main__":
a()
Related
I have two classes that inherit from the same base class, and they have some common methods (in fact, properties). I will need to do this:
input: an int and an object from either class;
output: the result of one of the methods (determined by the int) of the corresponding class.
I think I can use a dictionary to do this, as the following code:
class ChangeInt(object):
def bar(self, i):
print(i)
class PlusOne(ChangeInt):
def bar(self, i):
print(i+1)
class PlusTwo(ChangeInt):
def bar(self, i):
print(i+2)
methods_dict = {0:ChangeInt.bar}
print(methods_dict[0](PlusOne(), 0))
print(methods_dict[0](PlusTwo(), 0))
I expect the output to be 1,2, but I actually get this:
0
None
0
None
I would like to know how these results are generated and what should I do to fix it up. Thanks in advance.
I totally mess up the format in the comment, so I'll paste it here.
thanks to Ryan Haining in Dynamic Method Call In Python 2.7 using strings of method names, I've found another way to do this:
class ChangeInt(object):
def bar(self, i):
print(i)
class PlusOne(ChangeInt):
def bar(self, i):
print(i+1)
class PlusTwo(ChangeInt):
def bar(self, i):
print(i+2)
methods_dict = {0:'bar'}
getattr(PlusOne(), methods_dict[0])(0)
getattr(PlusTwo(), methods_dict[0])(0)
This may not be the best way to do it, but it produces the expected result:
class ChangeInt(object):
def bar(self, i):
if not ('ChangeInt' in str(self.__class__)):
self.bar(i)
else:
print(i)
class PlusOne(ChangeInt):
def bar(self, i):
print(i+1)
class PlusTwo(ChangeInt):
def bar(self, i):
print(i+2)
methods_dict = {0:ChangeInt.bar}
methods_dict[0](ChangeInt(), 0)
methods_dict[0](PlusOne(), 0)
methods_dict[0](PlusTwo(), 0)
and prints:
0
1
2
The bar() function in the base class calls the method associated with given self instance or the base class implementation if it's an instance of base class itself (just print(i)). This is important, without it the code will be calling self.bar(i) infinitely if you invoke it on the base class (i.e. until it reaches max allowable recursion call number).
The check if not ('ChangeInt' in str(self.__class__)): is necessary since issubclass will return True for the parent class too,
issubclass(class, classinfo)
Return true if class is a subclass
(direct, indirect or virtual) of classinfo. A class is considered a
subclass of itself. classinfo may be a tuple of class objects, in
which case every entry in classinfo will be checked. In any other
case, a TypeError exception is raised.
And the point is to distinguish between the base/parent class and any subclasses.
Finally, since your function calls don't return anything explicitly, they actually return None. That None is what you are printing when enclosing the calls in an additional print,
print(methods_dict[0](PlusOne(), 0))
I removed the extra print so you only print the (assuming) intended content.
I want to use jitclass to speed up my code. I defined a class B, has 2 member variables. One is a dict, the other is a object of class A. How to define spec? I've been stuck here for a while. Thank you.
I've got this:
TypeError: spec values should be Numba type instances, got
Below is the code:
class A(object):
pass
spec = [
('x', dict), # ------ how to write this line ?
('y', A), # ------ how to write this line ?
]
#jitclass(spec)
class B(object):
def __init__(self):
self.x = dict()
self.y = A()
You cannot specify members of a jitclass that do not have an explicit numba type. You can make this work, however if A is also a jitclass and the dict is not a standard python dict, but instead is a numba typed dict (numba.typed.Dict). The typed dict is only supported in numba version 0.43 and later:
import numba as nb
#nb.jitclass([('x', nb.float64)])
class A(object):
def __init__(self, x):
self.x = x
a_type = nb.deferred_type()
dict_type = nb.deferred_type()
spec = [
('x', dict_type),
('y', a_type),
]
a_type.define(A.class_type.instance_type)
dict_type.define(nb.typeof(nb.typed.Dict.empty(key_type=nb.int64, value_type=nb.float64)))
#nb.jitclass(spec)
class B(object):
def __init__(self, x, y):
self.x = x
self.y = y
a = A(3.0)
d = nb.typed.Dict.empty(key_type=nb.int64, value_type=nb.float64)
d[1] = 1.1
b = B(d, a)
print(b.y.x) # => 3.0
print(b.x[1]) # => 1.1
Whether or not you want to or are able to use a jitclass for A or a nb.typed.Dict in place of a python dict will depend on your specific use-case.
python class's instance is behaving inconsistently.
Code.1
class A():
def __init__(self, x):
self.x = x
def update(self, x):
self.x = x
a = A(3)
a.update(5)
print a.x # prints 5
Code.2
class A():
def __init__(self, x):
self.x = x
def update(self, x):
self = A(x)
a = A(3)
a.update(5)
print a.x # prints 3
Why is 'x' attribute getting updated in the first snippet and is not getting updated in 2nd one?
Assigning to self does not change the current object. It just assigns a new value to the (local) self parameter variable.
The only special treatment that the self gets is during invocation, in the sense that
a.update(x)
is equivalent to
A.update(a, x)
Assigning to self just overrides the value of the local parameter:
def update(self, x):
# overwrite the value of self with a different instance of A
# This has no effect outside of update().
self = A(x)
a = A(3)
a.update(5)
In this case a is still the same instance from A(3). You created a new instance of A inside update() and assigned it to the self parameter, but that modification does not carry over outside of update().
I'm getting this error:
unbound method hello() must be called with A instance as first argument(got nothing instead)
import B
class A():
#staticmethod
def newHello():
A.oldHello() # Here the error
print ' world'
def inject(self):
A.oldHello = B.hello
B.hello = A.newHello
A().inject()
B.hello()
B.py contain only a function "hello" that print "hello"
def hello():
print 'hello'
Thanks in advance
A.oldhello() is not static. So in B's hello function is referencing A's nonstatic oldhello statically. A does in fact need an instance. I'm not too good with the decorators and how they work but maybe try declaring oldhello in the class before the function and calling it #staticmethod. I don't know if the staticness carries over if you override the method.
Try this:
class B():
def hello(self):
print "hello"
class A():
#staticmethod
def newHello(self):
A.oldHello(self) # Here the error
print ' world'
def inject(self):
A.oldHello = B.hello
B.hello = A.newHello
A().inject()
B().hello()
I have several classes. The desired behavior on an instance creation is that an instance is assigned an ID. For simplicity, let us assume that IDs should start at 0 and increase by 1 with every instance creation. For each of these several classes, the IDs should be incremented independently.
I know how to do this in C++. I have actually also done that in Python, but I do not like it as much as the C++ solution, and I am wondering whether it is due to my limited knowledge of Python (little more than 6 weeks), or whether there is a better, more Pythonic way.
In C++, I have implemented this both using inheritance, and using composition. Both implementations use the Curiously Recurring Template Pattern (CRPT) idiom. I slightly prefer the inheritance way:
#include <iostream>
template<class T>
class Countable{
static int counter;
public:
int id;
Countable() : id(counter++){}
};
template<class T>
int Countable<T>::counter = 0;
class Counted : public Countable<Counted>{};
class AnotherCounted: public Countable<AnotherCounted>{};
int main(){
Counted element0;
Counted element1;
Counted element2;
AnotherCounted another_element0;
std::cout << "This should be 2, and actually is: " << element2.id << std::endl;
std::cout << "This should be 0, and actually is: " << another_element0.id << std::endl;
}
to the composion way:
#include <iostream>
template<class T>
class Countable{
static int counter;
public:
int id;
Countable() : id(counter++){}
};
template<class T>
int Countable<T>::counter = 0;
class Counted{
public:
Countable<Counted> counterObject;
};
class AnotherCounted{
public:
Countable<AnotherCounted> counterObject;
};
int main(){
Counted element0;
Counted element1;
Counted element2;
AnotherCounted another_element0;
std::cout << "This should be 2, and actually is: " << element2.counterObject.id << std::endl;
std::cout << "This should be 0, and actually is: " << another_element0.counterObject.id << std::endl;
}
Now, in python, there are no templates which would give me different counters for each class. Thus, I wrapped the countable class to a function, and obtained the following implementation: (inheritance way)
def Countable():
class _Countable:
counter = 0
def __init__(self):
self.id = _Countable.counter
_Countable.counter += 1
return _Countable
class Counted ( Countable() ) :
pass
class AnotherCounted( Countable() ):
pass
element0 = Counted()
element1 = Counted()
element2 = Counted()
another_element0 = AnotherCounted()
print "This should be 2, and actually is:", element2.id
print "This should be 0, and actually is:", another_element0.id
and the composition way:
def Countable():
class _Countable:
counter = 0
def __init__(self):
self.id = _Countable.counter
_Countable.counter += 1
return _Countable
class Counted ( Countable() ) :
counterClass = Countable()
def __init__(self):
self.counterObject = Counted.counterClass()
class AnotherCounted( Countable() ):
counterClass = Countable()
def __init__(self):
self.counterObject = self.counterClass()
element0 = Counted()
element1 = Counted()
element2 = Counted()
another_element0 = AnotherCounted()
print "This should be 2, and actually is:", element2.counterObject.id
print "This should be 0, and actually is:", another_element0.counterObject.id
What troubles me is this. In C++, I have a good idea what I am doing, and e.g. I see no problems even if my classes actually inherit multiply (not just from Countable<> templated class) - everything is very simple.
Now, in Python, I see the following issues:
1) when I use composition, I instantiate the counting class like that:
counterClass = Countable()
I have to do this for every class, and this is possibly error-prone.
2) when I use inheritance, I will bump to further troubles when I will want to ihnerit multiply. Note that above, I have not defined the __init__'s of Counted nor of AnotherCounted, but if I inherited multiply I would have to call base class constructors explicitly, or using super(). I do not like this (yet?) I could also use metaclasses, but my knowledge is limited there and it seems that it adds complexity rather than simplicity.
In conclusion, I think that composition way is probably better for Python implementation, despite the issue with having to explicitly define the counterClass class attribute with Countable().
I would appreciate your opinion on validity of my conclusion.
I would also appreciate hints on better solutions than mine.
Thank you.
I would use __new__, that way you don't have to remember doing anything in __init__:
class Countable(object):
counter = 0
def __new__(cls, *a, **kw):
instance = super(Countable, cls).__new__(cls, *a, **kw)
instance.id = cls.counter + 1
cls.counter = instance.id
return instance
class A(Countable):
pass
class B(Countable):
pass
print A().id, A().id # 1 2
print B().id # 1
I might use a simple class decorator ...
import itertools
def countable(cls):
cls.counter = itertools.count()
return cls
#countable
class Foo(object):
def __init__(self):
self.ID = next(self.__class__.counter)
#countable
class Bar(Foo):
pass
f = Foo()
print f.ID
b = Bar()
print b.ID
If you really want to do this the "fancy" way, you could use a metaclass:
import itertools
class Countable(type):
def __new__(cls,name,bases,dct):
dct['counter'] = itertools.count()
return super(Countable,cls).__new__(cls,name,bases,dct)
class Foo(object):
__metaclass__ = Countable
def __init__(self):
self.ID = next(self.__class__.counter)
class Bar(Foo):
pass
f = Foo()
print f.ID
b = Bar()
print b.ID