Reputation: 329
I have created a class foo
as below:
class foo():
def __new__(cls, a, b, c, add=True):
return cls.sum(a, b, c) if add else cls.subtract(a, b, c)
def sum(a, b, c):
return a + b + c
def subtract(a, b, c):
return c - b - a
print(foo(1, 2, 3, True))
This program returns the required result as 6
. However, I needed to get the clarity of a few concepts:
sum
and subtract
are instance methods, how can they be called without instantiating an object as in the above example i.e., print(...)
?I have observed many python APIs and frameworks returning an object or a value through class instantiation.
I am trying to understand the core concepts of OOPs in python please help.
Upvotes: 1
Views: 234
Reputation: 40791
The way you have it now, sum
and subtract
are indeed instance methods.
>>> foo_obj = object.__new__(foo) # This will actually create a foo object to demonstrate
>>> foo_obj.sum
<bound method foo.sum of <__main__.foo object at 0x0000000000000000>>
>>> type(foo_obj.sum)
<class 'method'>
But that's just because when you access them through an instance, Python dynamically creates a method (Basically just binds the first argument to the object, usually self
)
But, you can access the wrapped function through the class:
>>> foo_obj.sum.__func__
<function foo.sum at 0x0000000000000001>
>>> foo.sum
<function foo.sum at 0x0000000000000001>
>>> foo_obj.sum.__func__ is foo.sum
True
So in your __new__
function, it won't bind the first argument, and they call the underlying function instead of making them an instance method.
To fix the warnings, you can make them classmethod
s or staticmethod
s. But it is generally bad practice to not return an object that is an instance of the class from the __new__
. If you really wanted to use OOP, either subclass int
or make a wrapper, so you can have:
>>> class Foo:
__slots__ = 'value',
def __init__(self, a, b, c, add=True):
self.value = self.sum(a, b, c) if add else self.subtract(a, b, c)
@staticmethod
def sum(a, b, c):
return a + b + c
@staticmethod
def subtract(a, b, c):
return c - b - a
>>> foo = Foo(1, 2, 3, True)
>>> foo
<__main__.foo object at 0x0000000000000002>
>>> foo.value
6
or
>>> class Foo(int):
__slots__ = ()
def __new__(cls, a, b, c, add=True):
value = cls.sum(a, b, c) if add else cls.subtract(a, b, c)
return super().__new__(cls, value)
@staticmethod
def sum(a, b, c):
return a + b + c
@staticmethod
def subtract(a, b, c):
return c - b - a
>>> foo = Foo(1, 2, 3, True)
>>> foo
6
>>> type(foo)
<class '__main__.Foo'>
Upvotes: 2