Python 3: Calling a class function inside of __init__ - python

I have a little question about python 3.
I want to create a class, which is using a function from within of that class. Just like:
class Plus:
def __init__(self, x, y):
self.x = x
self.y = y
self.test()
def test(self):
return self.x + self.y
now I am doing something like
a = Plus(5,6)
print(a)
and python is giving me
<__main__.Plus object at 0x000000000295F748>
and not 11 as I want it. I know that I can get 11 by
a = Plus(5, 6).test()
print(a)
but that's not what I want. I want to call the class and getting the result without adding .test() to it.
Can you help me?

I would go for:
class Plus:
def __init__(self, x, y):
self.x = x
self.y = y
self.test()
def test(self):
res = self.x + self.y
self.__repr__ = lambda:str(res)
return res
>>> Plus(5,5)
10
>>> a = Plus(5,5)
>>> a
10
>>> a.test()
10
This way you are not recomputing the sum each time you call print, its updated when you call the test method.

You'd need to define a __str__ method for your Plus class:
class Plus:
def __init__(self, x, y):
self.x = x
self.y = y
def test(self):
return self.x + self.y
def __str__(self):
return str(self.test())

now I am doing something like
a = Plus(5,6)
print(a)
and python is giving me
<__main__.Plus object at 0x000000000295F748>
and not 11 as I want it. I know that I can get 11 by
a = Plus(5, 6).test()
print(a)
but that's not what I want. I want to call the class and getting the result without adding .test() to it.
I am not sure what do you mean by 'and not 11 as I want it'. If you want Plus(5, 6) to actually return 11 (int instance), you should make Plus a function that returns the sum. Alternatively you can override __new__ method and hook upon object creation -- but this is a bad idea.
What are you trying to achieve?
I doubt, that by 'and not 11 as I want it' you want something special to be printed (formatted, represented). If so, override __str__ or __unicode__ or __repr__ method.

Edit:
ignore this answer, it is a comment on a misinterpretation of the question
This is just wrong.
when you instantiate an object, you'd expect to get a reference to that object.
if you just want a global function returning a number, why even bother to make a class with an init?
in python you shouldn't want static class's like in C# for encapsulation. instead name the module something, and use that for encapsulation.

Related

How to check if an instance attribute exists in an method Python

I will get straight to the point. I have been trying to find different ways in which I can check if an instance attribute exists in a method of a class which has not been called from the instance of the class.
Consider the following example:
class Main:
def thing1(self):
self.x = 10
m = Main()
print(m.x)
This code above will not work, until I call the method, e.g:
class Main:
def thing1(self):
self.x = 10
m = Main()
m.thing1()
print(m.x)
or
class Main:
def __init__(self):
self.thing1()
def thing1(self):
self.x = 10
m = Main()
print(m.x)
I want to know if there is a way I can check if this instance attribute exists in the method without having to call it.
I have tried using:
hasattr()
dir()
__ dict __
None of them will show that I have a instance attribute called 'x' in thing1
As well as this, I would greatly appreciate it if you could show me how I could check if an instance attribute in a method exists through another method.
class Main:
def thing1(self):
self.x = 10
def check(self):
# Is there a way I can check if 'x' exists in the method names thing1, without having to call it.
m = Main()
Thank you for taking the time to read this question, and I hope that you have a great day!
Indeed hasattr() definitely works. See interactive example below:
>>> class Main:
... def thing1(self):
... self.x = 10
...
>>> m = Main()
>>> hasattr(m, 'x')
False
>>> m.thing1()
>>> hasattr(m, 'x')
True
>>> print(m.x)
10
It's worth noting, though, that attributes should be initialized in the constructor. It's good practice to use __slots__ to declare attributes, but they must still be initialized. Also, class variables (attributes) are initialized outside the constructor. See example below:
class Main:
c = 5
__slots__ = ('x', 'y')
def __init__(self):
self.y = 12
def thing1(self):
self.x = 10
m = Main()
print(hasattr(m, 'x'))
print(hasattr(m, 'y'))
print(m.c)
Output:
False
True
5
After reading the question again and additional comments, it seems that you want to access an attribute that is initalized in a method, without actually calling said method. This is not possible because the attribute won't actually exist until it is initialized.
The only way I can think of to determine if the attribute would exist after the method call, is to read the code of the function in your program and check for the presence of the attribute. This is one crude example, which by no means is guaranteed to always work:
import inspect
lines = inspect.getsource(Main.thing1)
print('self.x' in lines)
The above, would print True for the code in question. I cannot think of a use case where this would be useful and strongly discourage it, but it's good to know the capabilities of Python.

Using local variable within a function by another function in a class

Due to some circumstances I can only pass the argument to one function within a class.
Example:
class win1():
def __init__(self):
self.diction = dict()
self.x = self.wanted_touse()
#is it possible to make it here? If yes, it will be good to be like this
# self.X = X or self.y = Y (is this even possible without passing an argument in it?)
def fun(self, X,Y):
self.x = X
self.y = Y
def wanted_touse(self):
#I wanted to use X and Y here while at the same time I cannot pass the argument to this function because of some circumstances.
#Here with some functions to make the dictionary for self.x example for x in enumerate(self.x)
self.diction[something] = something
I would like to learn to see whether is it possible to use a variable within a function in win1 into want_touse function.
Define your attribute in the __init__(), and then modify it in your fun() function, like this:
class win1():
def __init__(self):
self.x = None
def fun(self, X,Y):
self.x = X
def wanted_touse(self):
pass
#do whatever you want with self.x here, so long as you've run your fun() function and changed self.x as you intended.
This example is just using a single variable. You can apply this to additional variables as needed.

Is there a way to run a method for all instances of a class in python?

Example code:
>>> class MyClass(object):
def __init__(self, x, y):
self.x = x
self.y = y
def power(self):
print(self.x**self.y)
def divide(self):
print(self.x/self.y)
>>> foo = MyClass(2, 3)
>>> bar = MyClass(4, 7)
>>>
>>> foo.power()
8
>>> bar.divide()
0.5714285714285714
Whenever I used classes in Python previously, I just ran the method for each instance separately (see above). I was just wondering If there was a way to run the same method for all the instances of that class at once, because it could get a bit annoying, if you have 20 or so instances. I'm thinking of something like this:
>>> allinstances.power()
8
16384
Is there a way of doing this?
class MyClass(object):
instancelist = []
def __init__(self, x, y):
self.x = x
self.y = y
MyClass.instancelist.append(self)
def power(self):
print(self.x ** self.y)
def divide(self):
print(self.x / self.y)
foo = MyClass(2, 3)
bar = MyClass(4, 7)
[instance.power() for instance in MyClass.instancelist]
will output:
8
16384
This way you do not need any global variables or placeholders that are stored outside of the class definition.
Not usually. You could make your class be capable of that, however:
GLOBAL_MYCLASS_LIST = []
class MyClass(object):
def __init__(self, x, y):
GLOBAL_MYCLASS_LIST.append(self)
self.x = x
self.y = y
def power(self):
print(self.x**self.y)
def divide(self):
print(self.x/self.y)
a = MyClass(2, 3)
b = MyClass(4, 7)
all_powers = [i.power() for i in GLOBAL_MYCLASS_LIST]
Of course, you could also do that without baking it into the class, which is probably cleaner for most cases where you might have different sets of MyClasses:
myclass_list = []
class MyClass(object):
def __init__(self, x, y):
self.x = x
self.y = y
def power(self):
print(self.x**self.y)
def divide(self):
print(self.x/self.y)
myclass_list.append(MyClass(2, 3))
myclass_list.append(MyClass(4, 7))
all_powers = [i.power() for i in myclass_list]
From your question, I believe you would want a bit of dynamism too. Something like below could help:
I have added a function called printBoth() for demonstration.
Note: Python 2.x code below
class MyClass(object):
def __init__(self, x, y):
self.x = x
self.y = y
def power(self):
print "power",self.x**self.y
def divide(self):
print "divide", self.x/self.y
def printBoth(self):
print "x: ", self.x
print "y: ", self.y
class Test:
def __init__(self, items):
self.items = items
def __getattr__(self, key):
def fn():
return [getattr(x,key)() for x in self.items]
return fn
foo = MyClass(2, 3)
bar = MyClass(4, 7)
t = Test([foo,bar])
t.power()
t.divide()
t.printBoth()
Output:
power 8
power 16384
divide 0
divide 0
x: 2
y: 3
x: 4
y: 7
Note: The code can break on many occasions, you neeed to perform additional checks in real implementation.
The important part is here:
def __getattr__(self, key):
def fn():
return [getattr(x,key)() for x in self.items]
return fn
The above function is invoked upon any function call on the Test instance. What is returned is function that takes no arguments. The function runs over all the instances, and invokes the same function on every item on self.items (which is the list of all the instances you want to invoke your function on). The results are returned as a list.
Sure. Put the instances in a list as you create them, then iterate over the list and call the method on each instance. Also, you should change your methods to return rather than print their results, as this is much more flexible. That way you can store the results in a list, write them to a file, do further calculations with them, or print them.
instances = [MyClass(2, 3), MyClass(4, 7)]
results = [x.power() for x in instances]
Just use a loop:
foo = MyClass(2, 3)
bar = MyClass(4, 7)
for i in [foo, bar]:
i.power()
If you are not sure that all instances will have the method, use a hasattr check:
for i in list_of_instances:
if hasattr(i, 'power'):
i.power()
I think all answers are valid, depending on the use case. I would argue that if this class is used in seperated parts of your app/program you wouldn't want to depend on the GLOBAL_MYCLASS_LIST declared some where before (as #amber suggested). You would want to be sure this variable exists and declare it as a Class Variable and have the compute_all as a Class method or even as a static method with #staticmethod decorator (which I think is less relevant to the specific use case.
Again, I would stress that this is a very specific use case, and not very common. so you should think about your design before doing that and not using the more straight pythonic ways offered in other answers.
I would also like to refer you to this nice video of a Pycon lecture about classes in python which does a nice job of explaining this (The decks are here.)

Call a method from a class on something created by a different method in the same class?

I would like to call a method from a class on something created by another method in the class. How would I do this?
For example, I've just created a class called call me, and would like to use the result of the subtract method in the add method.
class call_me(object):
def __init__(self, x, y):
self.x = 5
self.y = 10
def subtract(self):
difference = self.y - self.x
return difference
def add(self.subtract,second_number):
# code to add the difference returned by subtract to the second number.
How would I add a second number to the difference returned by subtract? Is there a way I could pass difference to add?
def add(self, second_number):
difference = self.substract()
return difference + second_number

Classes in Python

In Python is there any way to make a class, then make a second version of that class with identical dat,a but which can be changed, then reverted to be the same as the data in the original class?
So I would make a class with the numbers 1 to 5 as the data in it, then make a second class with the same names for sections (or very similar). Mess around with the numbers in the second class then with one function then reset them to be the same as in the first class.
The only alternative I've found is to make one aggravatingly long class with too many separate pieces of data in it to be readily usable.
A class is a template, it allows you to create a blueprint, you can then have multiple instances of a class each with different numbers, like so.
class dog(object):
def __init__(self, height, width, lenght):
self.height = height
self.width = width
self.length = length
def revert(self):
self.height = 1
self.width = 2
self.length = 3
dog1 = dog(5, 6, 7)
dog2 = dog(2, 3, 4)
dog1.revert()
Here's another answer kind of like pobk's; it uses the instance's dict to do the work of saving/resetting variables, but doesn't require you to specify the names of them in your code. You can call save() at any time to save the state of the instance and reset() to reset to that state.
class MyReset:
def __init__(self, x, y):
self.x = x
self.y = y
self.save()
def save(self):
self.saved = self.__dict__.copy()
def reset(self):
self.__dict__ = self.saved.copy()
a = MyReset(20, 30)
a.x = 50
print a.x
a.reset()
print a.x
Why do you want to do this? It might not be the best/only way.
Classes don't have values. Objects do. Is what you want basically a class that can reset an instance (object) to a set of default values?
How about just providing a reset method, that resets the properties of your object to whatever is the default?
I think you should simplify your question, or tell us what you really want to do. It's not at all clear.
I think you are confused. You should re-check the meaning of "class" and "instance".
I think you are trying to first declare a Instance of a certain Class, and then declare a instance of other Class, use the data from the first one, and then find a way to convert the data in the second instance and use it on the first instance...
I recommend that you use operator overloading to assign the data.
class ABC(self):
numbers = [0,1,2,3]
class DEF(ABC):
def __init__(self):
self.new_numbers = super(ABC,self).numbers
def setnums(self, numbers):
self.new_numbers = numbers
def getnums(self):
return self.new_numbers
def reset(self):
__init__()
Just FYI, here's an alternate implementation... Probably violates about 15 million pythonic rules, but I publish it per information/observation:
class Resettable(object):
base_dict = {}
def reset(self):
self.__dict__ = self.__class__.base_dict
def __init__(self):
self.__dict__ = self.__class__.base_dict.copy()
class SomeClass(Resettable):
base_dict = {
'number_one': 1,
'number_two': 2,
'number_three': 3,
'number_four': 4,
'number_five': 5,
}
def __init__(self):
Resettable.__init__(self)
p = SomeClass()
p.number_one = 100
print p.number_one
p.reset()
print p.number_one

Categories