Python Classes using __init and __repr__ methods - python

Iam trying to create a class that should accept two arguments, x and y, and be represented by a string 'Point(x, y)' with appropriate values for x and y
class Point(object):
def __init__(self, x, y):
self.x = 0
self.y = 0
def __repr__(self):
return "Point(%s,%s)"%(self.x, self.y)
Error:
Point(0,0) is not of type 'string'
Failed validating 'type' in schema['items']:
{'type': 'string'}
On instance[0]:
Point(0,0)

"self.x" is the value of the instance of your class. So, if you set "self.x = 0", it means whenever you create an object for that class, the "x" value of that object will always be 0 instead of what you pass in the parameter.
"x" is the value of what you pass in the parameter.
self.x = x
self.y = y

Code:
class MyClass():
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return "Point(%s,%s)"%(self.x, self.y)
thiss = MyClass(0, 0)
print(thiss.__repr__())
thiss = MyClass(20, 20)
print(thiss.__repr__())
Output:
daudn$ python3 point.py
Point(20,20)
daudn$ python3 point.py
Point(0,0)
When declaring your init function, you initialized self.x and self.y to always be 0. If you look at the code I've posted, whatever number you pass to the class will become the values or Point.

Related

Inheriting function data

I have a question about inheriting data from functions, defined inside another class. I have written an example script to clarify myself. In this script I define a class called Test. Here I define x and y in the __init__() function. Thereafter, I make a calculation and return x,y. I then create another class called Inherit_Test that inherits the x,y from Test. In this class I define z and make a calculation with the inherited values from Test. Afterwards, I call the class with Values. The problem arises when I want to access the data stored in Values. The type of this object is "Inherited_Values", while you would expect the type to be int and have the value 3*4*43. I hope I have explained myself well enough, thanks!
class Test():
def __init__(self, x , y ):
self.x = x
self.y = y
def Calculation(self):
self.x = 3*4 #self.x*self.x
self.y = 43 #self.y*self.y
return self.x, self.y
class Inherit_Test(Test):
def __init__(self,z ):
Test.__init__(self, x = Test.Calculation(self)[0],
y = Test.Calculation(self)[1])
self.z = z
def Inherit_Calculation(self):
self.z = self.x * self.y
return self.z
Value = Inherit_Test(0)
Value.Inherit_Calculation()
unfortunately, your question is not very clear defined and it is hard to assume what you exactly wanted to do. I'll try to help you with the following code :
class Test():
def __init__(self):
self.Calculation() # instantiation of the self.x and self.y; no init params needed
def Calculation(self):
self.x = 3*4 #self.x*self.x
self.y = 43 #self.y*self.y
#return self.x, self.y # do you need to return something here ?
class Inherit_Test(Test):
def __init__(self):
super().__init__() # instantiation of the parameters of your super class
#self.z = z # do you need this part ?
def Inherit_Calculation(self):
self.z = self.x * self.y
return self.z
Result:
Value = Inherit_Test()
print(type(Value.Inherit_Calculation()))
print(Value.x)
print(type(Value.x))
print(Value.y)
print(type(Value.y))
print(Value.z)
print(type(Value.z))
<class 'int'>
12
<class 'int'>
43
<class 'int'>
516
<class 'int'>

Why don't I get an error message for failing to initializing an inherited classes instance attribute in an instance of it's derived class?

When I initialize an instance of class B, shouldn't it raise an error for not attempting to supply a value for the x attribute in class A's init method? What if I want an error to be raised if x is not supplied a value?
Example:
class A:
def __init__(self, x):
self.x = x
class B(A):
def __init__(self, y):
self.y = y
z = B(4) #Shouldn't I be getting an error for not attempting to
#initialize x from the base class?
No.
What you are doing is initializing y, since in your init of B class, you are not calling your parents constructror
super.__init__()
If you wanted to use both x,y from B and having to initialize x from B, you should use this:
class A:
def __init__(self, x):
self.x = x
class B(A):
def __init__(self, x, y):
super().__init__(x)
self.y = y

Python: Unexpected identifier when calling method of class

I would like to write a class Calculator including:
a function called add that takes two parameters containing double values and returns their sum
a function called subtract that takes two parameters containing double values and returns their difference (subtract the second from the first)
a function called multiply that takes two parameters containing double values and returns their product
a function called divide that takes two parameters containing double values and returns the value of the first divided by the second. If the second number is a zero, do not divide, and return "You can't divide by zero!"
This is my attempt, but apparently it's not correct.
class Calculator:
def add(x,y):
return x+ y
def subtract(x,y):
return x - y
def multiply(x,y):
return x * y
def divide(x,y):
if y==0:
return "You can t divide by zero!"
else:
return x/y
From the results, I get unexpected identifier x and y.
Object methods in python need to explicitly define the 'this' parameter you know from 'C', or the argument referring to the object itself. In Python it is usually called 'self'. For example:
class Calc:
def add(self,x,y): return x+y
Since all your methods do not really need self, and the calculator is more of a container of methods, you can define them as class methods, so Calc.add(3,4) works without creating an object:
class Calc:
#staticmethod
def add(x,y): return x+y
If you're new to python please note indentation is very important as well.
This answer will be accepted by the programming lab system:
class Calculator:
def add(self, x, y):
self.x = x
self.y = y
a = self.x + self.y
return a
def subtract(self, x, y):
self.x = x
self.y = y
a = self.x - self.y
return a
def multiply(self, x, y):
self.x = x
self.y = y
a = self.x * self.y
return a
def divide(self, x, y):
self.x = x
self.y = y
if (y == 0):
a = "You can't divide by zero!"
else:
a = self.x / self.y
return a
There are more simple soutions but this will be accepted by the programming lab editor. It can be a bit picky at times.
class Calculator:
def add(self,num1,num2):
print(num1+num2)
def subtract(self,num1,num2):
print(num1-num2)
def multiply(self,num1,num2):
print(num1*num2)
def divide(self,num1,num2):
print(num1 / num2)
object1 = Calculator()
object2 = Calculator()
object3 = Calculator()
object4 = Calculator()
object1.add(100,200)
object2.subtract(50,30)
object3.multiply(10,3)
object4.divide(250,5)

special method for an object to override tuple expansion?

I will provide an example of the problem in question, in case the title was not clear enough.
Let's say that I have a class Point(object) that represent 2d coordinates.
Is it possible to create a "magic" method that will allow the following?
x, y = point
Maybe some hacks with iterators?
you can simply tap into the iterator protocol of the object and accomplish this
class Point(object):
def __init__(self, x,y):
self.x = x
self.y = y
self.points = (x,y)
def __iter__(self):
return iter(self.points)
p = Point(1,5)
x,y = p
print x,y
# 1,5
take a look at http://www.rafekettler.com/magicmethods.html#sequence on more information on how a custom object can be converted into an iterable; or more precisely how one would use an object like an iterable.
Just provide an __iter__ method.
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
def __iter__(self):
yield self.x
yield self.y
p = Point(1, 2)
x, y = p
assert (1, 2) == (x, y)
Be careful though. This means your class suddenly becomes safe to use in many other places where it might have previously thrown a type error.
eg.
def add_1(x):
return x + 1
l = list(map(add_1, p)) # works, because the point is iterable
Ergo, you may want to provide a method other than __iter__ that provides the iterator.
eg.
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
def coords(self):
yield self.x
yield self.y
p = Point(1, 2)
x, y = p.coords()
assert (1, 2) == (x, y)

Is it possible to instantiate an object of one class in two different ways?

Here is an example which creates a point as p=Point(x, y). Assume that I have some array ppp=(x, y) where x and y are numbers and I want to make it of class Point but in the way: p=Point(ppp). I can do either one or another way but not both simultaneously. Is it possible to have both ways?
There are two different ways to acquire the result, the first is to analyse arguments that you pass to __init__ and in dependence of their quantity and type - choose a decision what are you using to instantiate class.
class Point(object):
x = 0
y = 0
def __init__(self, x, y=None):
if y is None:
self.x, self.y = x, x
else:
self.x, self.y = x, y
The other decision is to use classmethods as instantiators:
class Point(object):
x = 0
y = 0
#classmethod
def from_coords(cls, x, y):
inst = cls()
inst.x = x
inst.y = y
return inst
#classmethod
def from_string(cls, x):
inst = cls()
inst.x, inst.y = x, x
return inst
p1 = Point.from_string('1.2 4.6')
p2 = Point.from_coords(1.2, 4.6)
If you know that you have a tuple/list while creating the instance, you can do: p = Point(*ppp), where ppp is the tuple.
class Point:
def __init__(self, x, y=None):
if isinstance(x, tuple):
self.x, self.y = x
else:
self.x = x
self.y = y
Yes:
class Point(object):
def __init__(self, x, y=None):
if y is not None:
self.x, self.y = x, y
else:
self.x, self.y = x
def __str__(self):
return "{}, {}".format(self.x, self.y)
print Point(1,2)
# 1, 2
print Point((1,2))
# 1, 2
I would guess that your looking for a way to overload your constructor, as is common in statically typed languages such as C++ and Java.
This is not possible in Python. What you can do is provide different keyword argument combinations, something like:
class Point(object):
def __init__(self, x=None, y=None, r=None, t=None):
if x is not None and y is not None:
self.x = x
self.y = y
elif r is not None and t is not None:
# set cartesian coordinates from polar ones
Which you would then use as:
p1 = Point(x=1, y=2)
p2 = Point(r=1, t=3.14)

Categories