I am starting to work with classes in Python, and am learning how to create functions within classes. Does anyone have any tips on this sample class & function that I am testing out?
class test:
def __init__(self):
self.a = None
self.b = None
self.c = None
def prod(self):
return self.a * self.b
trial = test
trial.a = 4
trial.b = 5
print trial.prod
Ideally the result would be to see the number 20.
You need to:
Create an instance of test.
Invoke the prod method of that instance.
Both of these can be accomplished by adding () after their names:
trial = test()
trial.a = 4
trial.b = 5
print trial.prod()
Below is a demonstration:
>>> class test:
... def __init__(self):
... self.a = None
... self.b = None
... self.c = None
... def prod(self):
... return self.a * self.b
...
>>> trial = test()
>>> trial.a = 4
>>> trial.b = 5
>>> print trial.prod()
20
>>>
Without the parenthesis, this line:
trial = test
is simply assigning the variable trial to class test itself, not an instance of it. Moreover, this line:
print trial.prod
is just printing the string representation of test.prod, not the value returned by invoking it.
Here is a reference on Python classes and OOP.
Ideally you could also pass in the values to a, b, c as parameters to your object's constructor:
class test:
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
def prod(self):
return self.a * self.b
Then, constructing and calling the function would look like this:
trial = test(4, 5, None)
print trial.prod()
Related
There are three classes :
A, B and C
The __init__ of B creates an object of A. Using the mutators, I will be able to change the attributes of A from B for the instance created.
However, I am not unable to find any way to use that instance of A created by B to be used in C without passing the Object explicitly to the __init__ method [ not C.__init(self, object: A) ]
Is there any way to implicitly allow C to use that instance of A ?
I am new to python and not sure if this a valid question. I have looked at other sources where it explicitly passes the object to class C
class A:
def __init__(self):
x = []
y = []
class C :
def __init__(self):
#[get obj1 without passing the instance in init]
self.value = None
def method1():
self.value = len([]) #len(obj1 of A.x)
class B:
def __init__(self):
obj1 = A()
obj1.x = [1,2,3,4]
obj1.y = [1,2,3]
obj2 = B()
print(obj2.value) #this should be the length of x in the instance A created above
Here is a simple example:
class A:
def __init__(self, i = ""):
self.item = i
class B:
def __init__(self):
self.a = A("hello")
class C:
def __init__(self):
b = B()
print(b.a.item)
c = C()
Output:
hello
Let's say we have classes A and B:
class A:
def hello_world(self):
print("hello world")
class B:
def __init__(self):
self.a = A()
def hello_world(self):
self.a.hello_world()
You create an instance of class B (which will create an instance of class A inside):
b = B()
You can then pass a reference to either b or b.a to any function of an instance of class C (either a constructor or not)
class C:
def hello_world(self, a):
a.hello_world()
c = C()
c.hello_world(b.a)
You can also use global variables:
class C:
def hello_world(self):
b.a.hello_world()
c = C()
c.hello_world()
Here the instances of class C will rely on variable b to be in place and just use its a attribute.
Using global variables in classes is generally considered to be hard to maintain and a bad practice. If your class depends on a value or an instance of some class you should pass the reference in the constructor (__init__ function) or in the function that's using it.
If these classes are in different different python files then you can also use these classes by importing the class name and creating an object of that class:
eg:
file1.py
class A:
def __init__(self):
x = []
y = []
file2.py
from file1 import A
class C :
def __init__(self):
[get obj1 without passing the instance in init]
self.value = None
self.obj_a = A()
def xyz(self):
print "in class c"
file3.py
from file2 import C
from file1 import A
Class B:
def __init__(self):
self.obj_a = A()
self.obj_c = C()
def another_func(self):
print self.obj_c.xyz()# it will print "in class c"
How can I set the variable I want to change as a function argument? I want to define only one function, and not set_a(value), set_b(value), set_c(value), ...
class MyVarClass:
def __init__(self):
self.a = 1
self.b = 2
self.c = 3
# this works, but I don't want to write n functions
def set_a(myvar_object, value):
myvar_object.a = value
# this is what I actually want:
def set_vars(myvar_object, var_name, value):
myvar_object.var_name = value
myvar = MyVarClass()
# I want to do the same as myvar.a = 4
set_a(myvar, 4) # works as intended, now myvar.a is 4
set_vars(myvar, a, 4) # error, a is not defined
What you usually do is to create a method to the class like this:
class MyVarClass:
def __init__(self):
self.a = 1
self.b = 2
self.c = 3
def set_a(self, value):
self.a = value
If, for some reason, can't do it like this and you only have the name of the attribute as string, then you can use setattr:
setattr(myvar_object, 'a', value)
But usually what you do is just this line:
myvar_object.a = 4
This is done with setattr.
def set_vars(myvar_object, var_name, value):
setattr(myvar_object, var_name, value)
This isn't necessarily the best way of doing this. It often suggests a different data structure would be better, but in case that isn't the case here.
You'll note if you go this route, there isn't much reason to have a def rather than just call setattr directly, unless you think you'll change things in the future.
what about using a dict:
class MyVarClass:
def __init__(self):
self.vars = {"a": 1, "b": 2, "c": 3}
def set_vars(myvar_object, var_name, value):
myvar_object.vars[var_name] = value
**
var_name = ''
class MyVarClass:
def __init__(self):
self.a = 1
self.b = 2
self.c = 3
# this is what I actually want:
def set_vars(myvar, var_name, value):
myvar.var_name = value
print (myvar.var_name)
myvar = MyVarClass()
set_vars(myvar, "b", 6)
**
I'm having a hard time summarizing my question so I apologize if this is a duplicate.
I have a class like such:
class MyClass:
timer = 60
I want timer to represent an integer but also extend some custom methods. For example:
>>> c = MyClass()
>>> c.timer
60
>>> c.timer.wait() # This would wait 60 seconds
True
>>> c.timer
0
How can I do this in Python?
Not sure what you are trying to achieve, but your MyClass can be implemented as follows:
class MyClass:
def __init__(self):
self.a = 0
self.b = 0
def do_some_operation(self):
# do something using a and b
# and return True if success
self.a += 100;
return True
c = MyClass()
print(c.do_some_operation()) # True
print(c.a) # 100
Maybe you should try to make a class that simulates the integers:
class Integer:
value = 0
def __init__(self, value):
self.value = value
def __add__(self, other):
return Integer(self.value + other.value)
#Would need to do the other basic arithmetic things. I'll leave that to you...
def __str__(self):
return str(self.value)
def do_some_operation(self):
return True
class MyClass:
a = Integer(0)
b = Integer(0)
c = MyClass()
print c.a
print c.b
print c.a + c.b
print c.a.do_some_operation()
Gives:
0
0
0
True
I would be careful about doing this though. There may be another more suitable way.
Suppose I have two Python classes, A and B, and that B is an attribute of A. Can a method of B modify a property of A? for example, I would like to be able to call
A.B.setXinA(1)
A.x
>>> 1
One way around it would be embed a reference to A in B:
A.B.reftoA = A
But that's rather ugly... Is there a way to access the higher-level class directly? Below is a working example using the second method:
class A:
def __init__(self, b):
b.parent = self
setattr(self, b.name, b)
class B:
def __init__(self, name):
self.name = name
b = B('abc')
a = A(b) # b is now a.abc
abc.parent.x = 1
a.x
>>> 1
What about a method in B like this:
class B:
def __init__(self, name):
self.name = name
def setXinA(self, x):
self.parent.x = x
Then:
>>> b = B('abc')
>>> a = A(b)
>>> b.setXinA(19)
>>> print(A.x)
19
This way requires that setXinA is called by an instance of B rather than just B.setXinA(42) for example. Also, it sets x as an attribue of the class A, rather than any particular instance of A.
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