EDIT: I assure you that everything is correctly indented when I run this through python. I assume the problem has to do with how I call p._x and p._y but I'm not sure why?
This is a problem I am having crazy amounts of difficulty with. It just doesn't make sense. I have to submit this through a program checker, so it checks the code and makes sure its correct. If its not correct it gives out a useless error report.
Ok so this is what I want to do:
I need to calculate the distance between two vectors(x,y).
This is the test case that the program will run:
foo = Point(1,2)
bar = Point(3,4)
foo.dist_to_point(bar) = 2.8...
This is the code I have:
import math
class Point:
def __init__(self, x, y):
self._x = x
self._y = y
def dist_to_point(self, p):
a = self._x - p._x
b = self._y - p._y
c = math.sqrt(a**2+b**2)
return c
and it doesn't work. The error it gives me is this "you are trying to index into a point object. They are not lists or tuples - for point object p use p._x and p._y to access the required variables.
Any ideas?
Python requires all of your indentation to be the same. I see you're using a mixture of tabs and spaces, so your code won't even compile correctly. Here is the same code you have above, just with all of the indentation being two spaces instead of a mixture of tabs and spaces (it compiles and works!):
import math
class Point:
def __init__(self, x, y):
self._x = x
self._y = y
def dist_to_point(self, p):
a = self._x - p._x
b = self._y - p._y
c = math.sqrt(a**2+b**2)
return c
foo = Point(1,2)
bar = Point(3,4)
print(foo.dist_to_point(bar))
Pick tabs or spaces - don't use both. :)
Wild guesses:
Elsewhere, in code not shown, you are supposed to use a collection of points, but you use a single point.
You are supposed to implement indexed access to point coordinates.
You should review the assignment.
Related
I'm studying operator overloading in Python and came accross with this chunk of code. It is not clear to me, why do we return Point(x,y) in add function instead of just returning x and y.
class Point:
def __init__(self, x=0 , y=0):
self.x = x
self.y = y
def __str__(self):
return("({0},{1})" .format(self.x, self.y))
def __add__(self , other):
x = self.x + other.x
y = self.y + other.y
return Point(x, y) // here if we remove Point object and use return(x,y) it does not cause any errors
p1 = Point(1,5)
p2 = Point(2,5)
print(p1 + p2)
The (x,y) syntax creates a tuple object, while Point(x,y) creates an instance of the Point class and sets it's x and y properties.
There is a difference between these two types of python objects. A tuple is a sequence type object, which is formal talk for a list of values. A tuple, by itself, only has the two values, and the methods that apply for that type of collection. You can read more about tuples here: https://docs.python.org/3.3/library/stdtypes.html?highlight=tuple#tuple
On the other hand, while your Point class is still quite simple, can have much additional functionality via other methods. For example, the tuple will probably not have the add() method you are creating in your point class, or it may have another add() method which does something else. Hope this clears this up.
Just learning python and I write simple code along the way.
Overriding the print method in the derived class, can I print both classes in the same line, without changing the base class?
i.e. I want pointA.print() to print
"x = 10 and y = 10 and z = 10"; not x = 10 and y = 10 and z = 10
I know in C# this can be done easily as the WriteLine method starts with a new line (as opposed to ending with it), and so, the Write method does what I expected it to.
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def print(self):
print(f"x = {self.x} and y = {self.y}")
class PointWithZAxis(Point):
def __init__(self, x, y, z):
Point.__init__(self, x, y)
self.z = z
def print(self):
Point.print(self)
print(f"and z = {self.z}")
pointA = PointWithZAxis(10, 10, 10)
pointA.print()
Change the print in the parent class to this:
print(f"x = {self.x} and y = {self.y}", end = "")
BTW, it is cleaner in my opinion to overwrite the __str__ method of the classes than to make a print() method. The __str__ method of an object is automatically called when you print the object (like: print(object)). The code then becomes:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f"x = {self.x} and y = {self.y}"
class PointWithZAxis(Point):
def __init__(self, x, y, z):
Point.__init__(self, x, y)
self.z = z
def __str__(self):
return super().__str__() + f"and z = {self.z}"
pointA = PointWithZAxis(10, 10, 10)
print(pointA)
You can add end="" to print
print("something", end="")
Adding the end argument to the print function lets you specify the ending of you print statement, so:
print(..., end='')
By default it is set to end='\n', which indicates a new line.
P.S. be careful with naming funcions print as they shadow already existing functions and may cause confusion.
There are a couple other people who are responding with print(..., end=""). This is a quick-fix, sure. But there's something else I'd like to point out.
Since you're a beginner, I'd say you've encountered a good example that teaches why you should think a little about the kind of APIs/interfaces you're designing. Take a step back and ask yourself this question: "Who are the consumers (callers) of def print(self)? And what do they want." The point here is, you can have different callers each wanting a different thing. These problems arise when you're not able to find the common denominator across all that they want. Introducing parameters to the function is one way. In other words: your derived class can send in a additional parameter asking to not append a newline, while those that call from outside of PointWithZAxis.print(..) need not know about this parameter.
Here's an average solution:
class Point:
....
def print(self, include_newline=True):
print(..., end=("\n" if include_newline else ""))
class PointWithZAxis:
def print(self):
Point.print(self, include_newline=False)
print(....)
Here's a good solution (Don't print. How about making the job just to construct a string? Actual printing can be the callers job).
class Point:
....
def get_print_string(self):
return f"x = {self.x} and y = {self.y}"
class PointWithZAxis:
def get_print_string(self):
return super().get_print_string() + f" and z = {self.z}"
# You can then do:
p = PointWithZAxis()
print(p.get_print_string())
Pythonic solution (recommended): Use __str__(..). This is the recommended way of doing what get_print_string() does.This function indirectly gets called when you do print(AnyClass()). Refer to #Bram Dekker's solution.
To get to the point I'm learning how to work classes and list comprehension and I'm running into this problem:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def are_in_first_quadrant(listPoint):
newListPoint = filter(lambda pnt: pnt.x > 0 and pnt.y > 0, listPoint)
return newListPoint
pList = [Point(-3,7), Point(2,3), Point(7,0), Point(6,-9), Point(7,9)]
newList = are_in_first_quadrant(pList)
So you can see the goal of this is to spew out a list of points that are in the first quadrant, but when I try to print 'newList' I get:
[<objects.Point instance at 0x0293FA08>, <objects.Point instance at 0x0293FA80>]
Instead of:
[Point(2,3) , Point(7.9)]
Looking over this post: Filters in Python3
I understand the print out is the memory location but I don't really gain much more from that.
So question is how exactly do I fix this?
I'm guessing it probably has to do with how I used lambda but again not too sure.
I'm using Python 2.7
Thanks in advance.
Edit:
Also just tried
def are_in_first_quadrant(listPoint):
newListPoint = [pnt for pnt in listPoint if pnt.x > 0 and pnt.y > 0]
return newListPoint
and it throws up the same thing.
You need to provide a __repr__() method for your Point class:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return "Point({}, {})".format(self.x, self.y)
This method will be called for each element when the list is printed.
Just a remark: a function called are_... (or is_...) is supposed to return True or False. A more suitable name would be points_in_first_quadrant().
For a comparison between __str__() and __repr__(), see this question.
I have a general question on the class definition and its use..THe below code from one of the book works fine but I have a general questions.
Here we have defined a class Point and creating 2 instance Point1 & Point2. When calculating the distance for point2, how can we pass the point1 object?
Isn't point1 the point object, whereas the other_point is reprented as a variable.
Im little confused.
Code:
import math
class Point:
def move(self, x, y):
self.x = x
self.y = y
def reset(self):
self.move(0, 0)
def calculate_distance(self, other_point):
print("Inside calculating distance")
return math.sqrt(
(self.x - other_point.x)**2 +
(self.y - other_point.y)**2)
point1 = Point()
point2 = Point()
point1.reset()
point2.move(5,0)
print(point2.calculate_distance(point1))
When you create a Point object, several things happen.
point1 = Point()
point2 = Point()
One of the things that happens is that any methods belonging to the Point class are bound. What this means is that one of the arguments in the method is fixed, so that it always refers to the instance created. Let's look at the definition of calculate_distance.
def calculate_distance(self, other_point):
print("Inside calculating distance")
return math.sqrt(
(self.x - other_point.x)**2 +
(self.y - other_point.y)**2)
You can probably guess which argument is fixed. When Point() is called and an instance is created, the self parameter of calculate_distnace is fixed so that it always refers to that instance. So whenever you do this:
point1.calculate_distance(x)
You're doing the equivalent of this:
Point.calculate_distance(point1, x)
And whenever you do this:
point2.calculate_distance(point1)
You're doing the equivalent of this:
Point.calculate_distance(point2, point1)
That's what the self variable does. So when you are inside the definition of a class, you can use self to identify the object whose data you are trying to manipulate.
For example, suppose you have a class called human (which has a member variable named age), and every year, you want to increase the age of that human by calling the increment_age function. Then, you could write the following code:
class Human:
def __init__(self):
self.age = 0
def increment_age(self):
self.age += 1
>>> h = Human()
>>> print h.age
0
>>> h.increment_age()
>>> print h.age
1
So you see, by calling self, you are referring to the object itself. In your example, this would translate to self referring to point1.
Now, suppose that in the Human class, we want to add a function that allows two humans to fight. In this case, one human would have to fight another human (suppose that fighting another human increases your life by one and decreases the other human's life by one). In that case, you could write the following function within the Human class:
def fight(self, other_human):
self.age += 1
other_human.age -= 1
Now:
>>> h1 = Human()
>>> h2 = Human()
>>> h1.age = 5
>>> h2.age = 3
>>> print h1.age
5
>>> print h2.age
3
>>> h1.fight(h2)
>>> print h1.age
6
>>> print h2.age
2
Thus you can see in this example that h2 is the other_human in the fight function.
Hope that helps
Given your code, point2.calculate_distance(point1) calls calculate_distance with the object referred to by point2 as self, and the object referred to by point1 as other_point.
A good way to learn about these sorts of things is to use a visual debugger, and inspect the values in stack frames as the calls are made.
Inside calculate_distance, other_point is the name used to refer to whatever object is passed as an argument.
Let's say I've got a variable A that is the result of a function/expression F. F in it's turn has a number of other variables in it, let's say X,Y and Z.
Is it possible to bind A to F so that whenever X,Y or Z changes, A will be updated automatically?
What I want to avoid is that everytime X,Y and Z changes, I have to remember to update A explicitly in the code. I also don't want to call the function everytime I want to use the A.
Example (as per requested): I've got the following function:
def calcHits():
return sum(hitDiceRolls,level*modList['con'])
and in my program (outside of the function), I've got a variable called hitPoints (yes, it's a roleplaying game program). Whenever the variables that's used in the function is changed, I want hitPoints to change as well.
The typical way to do this in Python would be to use a class:
class ExpressionBinder:
def __init__(self, f):
self.f = f
self.x = 0
self.y = 0
self.z = 0
#property
def result(self):
return self.f(self.x, self.y, self.z)
You can use it like this:
def f(x, y, z):
return x**3 + y**2 + z
b = ExpressionBinder(f)
b.x = 1
b.y = 2
b.z = 3
print(b.result)
There is no way in Python to automatically rebind a name in global or local scope in response to other names being rebound. However, it should be possible to make a class that can keep track of some values and have a member function that returns the value you called A. And, as #Alok pointed out, you can use property descriptors to make a member name that implicitly calls a function to return its value, so you can hide the function and treat the name like a plain old name.
class Trk(object):
"""Track some values and compute a function if any change"""
def __init__(self, name, fn, **objects_to_track):
def _trk_fn(self):
if any(self.__dict__[x] != self.original_objects[x] for x in self.original_objects):
self.value = self.saved_fn(self.__dict___)
# now that self.value is updated, also update self.original_objects
for x in self.original_objects:
self.original_objects[x] = self.__dict__[x]
return self.value
self.original_objects = objects_to_track # make reference copy
self.__dict__.update(objects_to_track)
self.name = name
self.saved_fn = fn
self.fn = self._trk_fn()
self.value = self.fn()
I'm sorry but I am very tired right now, and I canot finish this example. I didn't test it either. But this shows one way to track values, and if they are different, do something different. You use it like this:
# want to track x, y, z
trk = Trk(x, y, z)
trk.fn() # returns up-to-date value
trk.x = new_value
trk.fn() #detects that trk.x changed and computes new trk.value
If the above works, you can use the property descriptor stuff to bind a name such that an attempt to read a value from the name will call self.fn()
EDIT: Oh, it's important that when self.value is updated, self.original_objects should be updated. I've added code to do that.
And now I'm going to sleep!