In my example below in Python, object x 'has-an' object y. I'd like to be able to invoke methods of x from y.
I'm able to achieve it using #staticmethod, however I'm discouraged to do that.
Is there any way(s) to reference the whole Object x from Object y?
class X(object):
def __init__(self):
self.count = 5
self.y = Y() #instance of Y created.
def add2(self):
self.count += 2
class Y(object):
def modify(self):
#from here, I wanna called add2 method of object(x)
x = X()
print x.count
>>> 5
x.y.modify()
print x.count
>>> # it will print 7 (x.count=7)
Thanks in advance.
You need to store a reference to the object which has the instance of a Y object:
class X(object):
def __init__(self):
self.count = 5
self.y = Y(self) #create a y passing in the current instance of x
def add2(self):
self.count += 2
class Y(object):
def __init__(self,parent):
self.parent = parent #set the parent attribute to a reference to the X which has it
def modify(self):
self.parent.add2()
Example usage:
>>> x = X()
>>> x.y.modify()
>>> x.count
7
Maybe it's possible for you to use class inheritance? For example:
class X(object):
def __init__(self):
self.count = 5
def add2(self):
self.count += 2
class Y(X):
def __init__(self):
super(Y, self).__init__()
def modify(self):
self.add2()
y = Y() # We now create an instance of Y which is a child class of 'super' class X
y.modify()
print(y.count) # 7
Related
I have a class like this
class Test:
def __init__(self, var):
self.var = var
def test(self):
x = self.var + 2
return x
And then I make a class like this
class Test:
def __init__(self, var):
self.var = var
def test(self):
self.x = self.var + 2
return self.x
I understand that I can use self to separate attribute values across various instances of this class. My question is, if I create many utility variables (like x) inside a method, should I always create them using self?
Can anyone explain how the above two classes behave differently (if they do)?
Let's see the difference between the two classes :
class Test:
def __init__(self, var):
self.var = var
def test(self):
x = self.var + 2
return x
Let's create a Test object:
t = Test(1)
And see what we can do
t.var # 1
t.x # Raises AttributeError : no such attribute in the class
t.test() #3
t.x # Still erroring
And with your second class
class Test:
def __init__(self, var):
self.var = var
def test(self):
self.x = self.var + 2
return self.x
Let's create a Test object:
t = Test(1)
And see what we can do
t.var # 1
t.x # Raises AttributeError : no such attribute in the class
t.test() #3
t.x # 3
So what ? Well we can see that any variables defined with self.VARNAME persist in the instance, while simple local variables, without self., dosen't.
However, if x needs to be accessible with t.x, i'd probably go for a property, like so
class Test:
def __init__(self, var):
self.var = var
#property
def x(self):
x = self.var + 2
return x
t = Test()
t.x # 3
From an existing code, I need to create instance from a class within another class while lots of information that are needed for initializing the called class, are contained in the caller one.
A way to pass some attributes of a caller class to the called class can be like in the following example passing self as argument and it does what exactly is expected, bu I wondered if it is the correct or whether is there a better way to do so?
class A:
def __init__(self):
self.x = 1
self.y = 10
self.myObj = B(self)
class B:
def __init__(self, Obj_from_A):
self.i = None
self.j = None
self.v= Obj_from_A.x
self.w = Obj_from_A.y
A_obj = A()
print(A_obj.myObj.v, A_obj.myObj.w)
Output:
1 10
Your class does what you think it is doing, except when it might not.
(btw your code does not run: you don't define B_Obj)
See the extra code I've added at the end:
class A:
def __init__(self):
self.x = 1
self.y = 10
self.myObj = B(self)
class B:
def __init__(self, Obj_from_A):
self.i = 0
self.j = 0
self.v= Obj_from_A.x
self.w = Obj_from_A.y
A_obj = A()
print(A_obj.myObj.v, A_obj.myObj.w)
A_obj.x = 2 # Now update the x member
print(A_obj.x, A_obj.myObj.v, A_obj.myObj.w)
Output:
1 10
2 1 10
Here A_obj.x has changed, but the instance of B has held onto the previous values.
I want local variable of a class to be changed by other class. My script is similar to the following :
import datetime
b = []
class P:
def __init__(self):
self.count = 1
self.create()
def create(self):
global b
a = C(self.count)
for i in range(10):
a.print_name()
print b
class C:
def __init__(self, *data):
self.test = data[0]
#staticmethod
def print_name():
global b
b.append(datetime.datetime.now())
o = P()
How to avoid use of a global variable . On web i found use of "super " can resolve the issue . Please help in this regard .
Make C constructor to accept P instance. And call the method of P to append item to instance attribute of P object.
class P:
def __init__(self):
self.count = 1
self.items = []
self.create()
def append(self, item):
self.items.append(item)
def create(self):
a = C(self, self.count) # <-- Pass P instance (self)
for i in range(10):
a.print_name()
print self.items
class C:
def __init__(self, p_instance, *data):
self.p_instance = p_instance # <-- Save P instance to use later
self.test = data[0]
def print_name(self):
self.p_instance.append(datetime.datetime.now()) # <-- Call p instance method
You are probably looking for a class attribute. If you add b as an attribute to the C class, it can be accessed as C.b and C().b, i.e. from a reference to the class or any instance.
class C(object): # classes in py2 should inherit from object!
b = [] # b inside C definition
#classmethod
def print_name(cls):
cls.b.append(datetime.datetime.now())
class P(object):
def __init__(self):
self.count = 1
self.create()
def create(self):
a = C(self.count)
for i in range(10):
a.print_name()
print C.b # or a.b
Of course, you can also place b on P. In this case, do
def print_name():
P.b.append(datetime.datetime.now())
Let's take a simple class as an example:
class Vector:
def __init__(self):
self.x = 1
self.y = 1
self.z = 1
What I would like is to give this class a variable called sum such that when I do
v = Vector()
v.sum
I am given the sum x+y+z (in this case 3). Of course I can easily just make a class method that does this, but then I would have to write v.sum() instead of v.sum. Is there any way to hide the fact that the class actually calls a function when asking for a variable?
Thanks in advance.
class Vector(object): # subclass object for new style class
def __init__(self):
self.x = 1
self.y = 1
self.z = 1
#property
def sum(self):
return self.x + self.y + self.z
>>> v = Vector()
>>> v.sum
3
http://docs.python.org/2/library/functions.html#property
class MyClass(Object):
def __init__(self, x=None):
if x:
self.x = x
def do_something(self):
print self.x
Now I have two objects
my_class1 = MyClass(x)
my_class2 = MyClass()
I want to use x when this my_class2 object is called
As other languages Support static variable like java,c++ etc.
Assign it as property to the class:
>>> class MyClass(object):
def __init__(self, x=None):
if x is not None:
self.__class__.x = x
def do_something(self):
print self.x # or self.__class__.x, to avoid getting instance property
>>> my_class1 = MyClass('aaa')
>>> my_class2 = MyClass()
>>> my_class2.do_something()
aaa
There are no static variables in Python, but you can use the class variables for that. Here is an example:
class MyClass(object):
x = 0
def __init__(self, x=None):
if x:
MyClass.x = x
def do_something(self):
print "x:", self.x
c1 = MyClass()
c1.do_something()
>> x: 0
c2 = MyClass(10)
c2.do_something()
>> x: 10
c3 = MyClass()
c3.do_something()
>> x: 10
When you call self.x - it looks first for instance-level variable, instantiated as self.x, and if not found - then looks for Class.x. So you can define it on class level, but override it on instance level.
A widely-used example is to use a default class variable with possible override into instance:
class MyClass(object):
x = 0
def __init__(self, x=None):
self.x = x or MyClass.x
def do_something(self):
print "x:", self.x
c1 = MyClass()
c1.do_something()
>> x: 0
c2 = MyClass(10)
c2.do_something()
>> x: 10
c3 = MyClass()
c3.do_something()
>> x: 0
You cannot. You can use a class attribute instead:
class Klass:
Attr = 'test'
# access it (readonly) through the class instances:
x = Klass()
y = Klass()
x.Attr
y.Attr
Read more about Python classes.