Printing a class attribute - python

Hi there I have the following code and I'm trying to print the object position, I am completely new to python & coding so need a bit of help! This is the code I have;
class object:
def __init__(self, x, y, z, vx, vy, vz):
self.x = x
self.y = y
self.z = z
self.vx = vx
self.vy = vy
self.vz = vz
def position(self):
return '{} {} {}'.format(self.x, self.y, self.z)
obj_1 = object(random.random(), random.random(), random.random(), 0, 0, 0)
print(obj_1.position())
I get the following error message:
AttributeError: 'object' object has no attribute 'position'

Is the indentation causing you a problem? I ran your code after fixing the indentation and it worked fine. Your __init__ function just needed indenting.
import random
class object:
def __init__(self, x, y, z, vx, vy, vz):
self.x = x
self.y = y
self.z = z
self.vx = vx
self.vy = vy
self.vz = vz
def position(self):
return '{} {} {}'.format(self.x, self.y, self.z)
obj_1 = object(random.random(), random.random(), random.random(), 0, 0, 0)
print(obj_1.position())

With fixed indentation:
class object:
def __init__(self, x, y, z, vx, vy, vz):
self.x = x
self.y = y
self.z = z
self.vx = vx
self.vy = vy
self.vz = vz
def position(self):
return '{} {} {}'.format(self.x, self.y,self.z)
obj_1 = object(random.random(), random.random(),random.random(), 0, 0, 0)
print(obj_1.position())

Related

Creating multiple class objects using a loop

I have the following code:
N=200
class Nbody:
num_of_bodies = 0
def __init__(self, x, y, z, vx, vy, vz):
self.x = x
self.y = y
self.z = z
self.vx = vx
self.vy = vy
self.vz = vz
Nbody.num_of_bodies +=1
def position(self):
return '{}{}{} {}{} {}{}'.format('(',self.x,',', self.y,',', self.z,')')
nbody_1 = Nbody(random.random(), random.random(), random.random(), 0, 0, 0)
nbody_2 = Nbody(random.random(), random.random(), random.random(), 0, 0, 0)
print(nbody_1.position())
print(nbody_2.position())
print(Nbody.num_of_bodies)
I want to use a loop to create N number of n bodies instead of having to create them manually i.e where nbody_1 and nbody_2 are.
So for instance a loop that for N=200 creates 200 nbody_(i), where i is an integer step between and including 1 and 200.
You can use a list comprehension:
nbodies = [Nbody(random.random(), random.random(), random.random(), 0, 0, 0)
for i in range(N)]

Operating with Python class and objects

I want to create both a Vector class and a Point class and have a function inside the Vector class that is able to add a Vector object and a Point object, but I don't understand how I have to operate with the internal variables of the classes. This is the code I have right now:
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def AddVector(self, point):
point2 = Point(0, 0)
point.x + self.x = point2.x
point.y + self.y = point2.y
return point2
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
p1 = Point(2,3)
v1 = Vector(4,7)
def main():
Vector.AddVector(p1,v1)
print(point2.x, point2.y)
main()
First, don't use global variables. It is a bad habit. Move them into main.
Then, the main problem, call method on the instances (p1 and v1) and not on classes (Vector and Point). Third, use the returned variable. Therefore:
def main():
p1 = Point(2,3)
v1 = Vector(4,7)
p2 = p1.AddVector(v1)
print(p2.x, p2.y)
The next problem is, this is invalid syntax:
point.x + self.x = point2.x
The correct way to assign is the other way around:
point2.x = point.x + self.x
Then, you have AddVector method on Vector. It should be on a Point and it should receive a Vector as argument.
All together:
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def AddVector(self, v):
point2 = Point(0, 0)
point2.x = self.x + v.x
point2.y = self.y + v.y
return point2
def main():
p1 = Point(2,3)
v1 = Vector(4,7)
p2 = p1.AddVector(v1)
print(p2.x, p2.y)
main()
Of course, it could be nicer, this is more advanced, but here it is for completeness:
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return 'Vector({}, {})'.format(self.x, self.y)
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, v):
return Point(self.x + v.x, self.y + v.y)
def __repr__(self):
return 'Point({}, {})'.format(self.x, self.y)
def main():
p1 = Point(2,3)
v1 = Vector(4,7)
p2 = p1 + v1
print(p2)
main()

Move points and check specific start value, using classes python

I need to be able to move points and check a specific point value. This is the code:
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
def move(self)
#Here I want to move my points
Next class is a linestring. It must be able to handle x set of points
class LineString(Point):
def __init__(self, *points):
self.points = []
for point in points:
if not isinstance(point, Point):
point = Point(*point)
self.points.append(point)
def __getitem__(self):
#Here I want to inspect the value of the specific
# e.g. y value for the start point after it has been moved
I'm a bit unsure of how to get the __getitem__ to work and whether it's in the right position. Should it be under class Point? Could this be done in another way?
Edited code;
from numpy import sqrt
import math
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
def dist(self, point):
return math.hypot(self.x - point.x, self.y - point.y)
def move(self, dx, dy):
self.x = self.x + dx
self.y = self.y + dy
class LineString(Point):
def __init__(self, *points):
self.points = []
for point in points:
if not isinstance(point, Point):
point = Point(*point)
self.points.append(point)
def length(self):
return sum(p1.dist(p2) for p1, p2 in zip(self.points[1:], self.points[:-1]))
def move (self, x, y):
for p in self.points:
p.move(x, y)
def __getitem__(self, key):
return self.points[key]
I think this is roughly what you want:
You don't seem to actually need a dictionary (for a line, I think a list makes more sense anyway). So the Line class is just a list of Points, and it provides a move_all_points function to translate them all. Because Line subclasses a list, you get all the standard behaviour of lists for free:
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return "<Point({},{})>".format(self.x, self.y)
def __str__(self):
return(repr(self))
def move(self, dx, dy):
"""Move the point by (dx, dy)."""
self.x += dx
self.y += dy
class Line(list):
"""A list of points that make up a line."""
def move_all_points(self, dx, dy):
for p in self:
p.move(dx, dy)
So then you can use them as follows:
>>> p1, p2, p3 = Point(0, 0), Point(5, 0), Point(10, 10)
>>> my_line = Line((p1, p2, ))
>>> print my_line
[<Point(0,0)>, <Point(5,0)>]
>>> my_line.append(p3)
>>> print my_line
[<Point(0,0)>, <Point(5,0)>, <Point(10,10)>]
>>> p4 = Point(100,100)
>>> my_line.move_all_points(1, 1)
>>> print my_line
[<Point(1,1)>, <Point(6,1)>, <Point(11,11)>]
>>> my_line.append(p4)
>>> print my_line
[<Point(1,1)>, <Point(6,1)>, <Point(11,11)>, <Point(100,100)>]

One of functions in class not working?

I would like to know why are my variables not changing in the def moving(self) method? Am I missing something? In this object the snake should move (up, down, left, right) depending on the dir_x, dir_y.
The code:
from tkinter import *
from tkinter import ttk
class Snake(object):
def __init__ (self, x, y, dir_x, dir_y, con_x, con_y):
self.x = x
self.y = y
self.dir_x = dir_x
self.dir_y = dir_y
self.con_x = con_x
self.con_y = con_y
self.snakey = root.create_rectangle((self.x+243, self.y+243, self.x+251, self.y+251), fill = "#000000")
def moving(self):
if self.dir_x == 10:
self.x = self.x + 10
root.coords(self.snakey, self.x, self.y, self.dir_x, self.dir_y, self.con_x, self.con_y)
if self.dir_x == -10:
self.x = self.x - 10
root.coords(self.snakey, self.x, self.y, self.dir_x, self.dir_y, self.con_x, self.con_y)
if self.dir_y == 10:
self.y = self.y + 10
root.coords(self.snakey, self.x, self.y, self.dir_x, self.dir_y, self.con_x, self.con_y)
if self.dir_y == -10:
self.y = self.y - 10
root.coords(self.snakey, self.x, self.y, self.dir_x, self.dir_y, self.con_x, self.con_y)
def __str__ (self):
return "<Snake x:%s y:%s dir_x:%s dir_y:%s con_x:%s con_y:%s>" % (self.x, self.y, self.dir_x, self.dir_y, self.con_x, self.con_y)
def moveup(event):
global dy, dx
dy = 10
dx = 0
def movedown(event):
global dy, dx
dy = -10
dx = 0
def moveleft(event):
global dx, dy
dx = -10
dy = 0
def moveright(event):
global dx, dy
dx = 10
dy = 0
win = Tk()
win.title("Snake")
root = Canvas(win, width = 493, height = 493, background = "white")
root.grid(row = 0, column = 0)
x = -1
d, c = 0, 0
xs, xy, dx, dy, cx, cy = 0, 0, 0, 0, 0, 0
for i in range(2, 492, 10):
root.create_line((i, 1, i, 500), fill = "#BFBFBF")
root.create_line((1, i, 500, i), fill = "#BFBFBF")
root.create_rectangle((2, 2, 493, 493), width = 4)
#S1 = Snake(xs, xy, dx, dy, cx, cy)
def Repeat():
S1 = Snake(xs, xy, dx, dy, cx, cy)
print("Tik", dx, dy)
print (S1)
root.after(500, Repeat)
Repeat()
root.bind("w", moveup)
root.bind("s", movedown)
root.bind("a", moveleft)
root.bind("d", moveright)
root.focus_set()
win.mainloop()
You create the method moving, but never call it - it's never executed.
You probably want to call in in repeat. Like this:
def Repeat():
S1 = Snake(xs, xy, dx, dy, cx, cy)
S1.moving ()
print("Tik", dx, dy)
print (S1)
root.after(500, Repeat)
But be warned that the variables will only change inside S1, and not outside - if you're creating it every call of repeat, you'll discard data like S1.x (and so the snake won't move)

Rotation matrix scales down

I'm trying to build some micro "3d engine" as to understand the basics of this field.
Everything works quite fine except for rotations. I use the standard rotation matrices to do this, yet all 3 of the possible rotations not only rotate the points, they also scale them down. This behaviour is not intended or wished for.
Following is the relevant part of the code (I think):
class Point:
def __init__(self, x, y, z, ui):
self.x = mpf(x)
self.y = mpf(y)
self.z = mpf(z)
self.ui = ui
def subtractVectorFromPoint(self, vector):
self.x -= vector.x
self.y -= vector.y
self.z -= vector.z
return self
def subtractPointFromPoint(self, point):
TempVector = Vector(0, 0, 0)
TempVector.x = self.x - point.x
TempVector.y = self.y - point.y
TempVector.z = self.z - point.z
return TempVector
def setPointToPoint(self, point):
self.x = point.x
self.y = point.y
self.z = point.z
return self
class Vector:
def __init__(self, x, y ,z):
self.x = mpf(x)
self.y = mpf(y)
self.z = mpf(z)
def rotateXY(self, degrees):
radians = mpf(math.radians(degrees))
self.x = (math.cos(radians) * self.x) + (- math.sin(radians) * self.y)
self.y = (math.sin(radians) * self.x) + (math.cos(radians) * self.y)
return self
#rotate xy plane by 15 degrees on pressing r
if event.key == pygame.K_r:
origin = Vector(0, 0, 0)
UI.draw_background()
for point in pointList:
tempVector = point.subtractPointFromPoint(origin)
point.setPointToPoint(origin)
point.addVectorToPoint(tempVector.rotateXY(15))
point.drawPoint()
That should be all you need I think. Any pointers to where I went wrong are welcome.
I know the classes miss an indent in the example here, I suck at the layout on this website :)
p.s. I tried using the "mpf()" function to increase the precision but this had 0 result.
The problem is in this part:
def rotateXY(self, degrees):
radians = mpf(math.radians(degrees))
self.x = (math.cos(radians) * self.x) + (- math.sin(radians) * self.y)
self.y = (math.sin(radians) * self.x) + (math.cos(radians) * self.y)
return self
self.y is being calculated using a self.x that is already adjusted, resulting in given problem.
A fix for this is using a temp variable like this:
def rotateXY(self, degrees):
radians = mpf(math.radians(degrees))
tempX = (math.cos(radians) * self.x) + (- math.sin(radians) * self.y)
self.y = (math.sin(radians) * self.x) + (math.cos(radians) * self.y)
self.x = tempX
return self

Categories