TypeError : Circle() takes no arguments - python-3.x

I'm getting the error TypeError : Circle() takes no arguments when trying to run the code above. Does anyone know what I'm missing?
class Circle:
is_shape = True
radius,color=0,""
def __init__(self, color, radius):
self.color = color
self.radius = radius
def display(self):
print("radius:",self.radius)
print("color:",self.color)
first_circle = Circle("red",2)
first_circle.display()

Actually you have an indentation problem in your code. Your functions aren't defined under classes, that's why it shows your class Circle() takes no argument.
To correct this put your functions inside a class :
class Circle:
is_shape = True
radius, color = 0, ""
def __init__(self, color, radius):
self.color = color
self.radius = radius
def display(self):
print("radius:", self.radius)
print("color:", self.color)
first_circle = Circle("red", 2)
first_circle.display()

Related

Plot text in 3d-plot that does not scale or move

Hello Pyqtgraph community,
I want to be able to create a "fixed" text window in a 3D interactive plot generated in PyQtGraph.
This text window will contain simulation-related information and should be visible at all times, regardless if you zoom in/out or pan to the left or right; and the location of the window should not change.
So far all the solutions I have found, create a text object that moves as the scaling of the axes changes. For example, the code below prints text on 3D axis, but once you zoom in/out the text moves all over the place. Any ideas would be greatly appreciated.
Thanks in advance
from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph.opengl as gl
from pyqtgraph.opengl.GLGraphicsItem import GLGraphicsItem
class GLTextItem(GLGraphicsItem):
"""
Class for plotting text on a GLWidget
"""
def __init__(self, X=None, Y=None, Z=None, text=None):
GLGraphicsItem.__init__(self)
self.setGLOptions('translucent')
self.text = text
self.X = X
self.Y = Y
self.Z = Z
def setGLViewWidget(self, GLViewWidget):
self.GLViewWidget = GLViewWidget
def setText(self, text):
self.text = text
self.update()
def setX(self, X):
self.X = X
self.update()
def setY(self, Y):
self.Y = Y
self.update()
def setZ(self, Z):
self.Z = Z
self.update()
def paint(self):
self.GLViewWidget.qglColor(QtCore.Qt.white)
self.GLViewWidget.renderText(self.X, self.Y, self.Z, self.text)
if __name__ == '__main__':
# Create app
app = QtGui.QApplication([])
w1 = gl.GLViewWidget()
w1.resize(800, 800)
w1.show()
w1.setWindowTitle('Earth 3D')
gl_txt = GLTextItem(10, 10, 10, 'Sample test')
gl_txt.setGLViewWidget(w1)
w1.addItem(gl_txt)
while w1.isVisible():
app.processEvents()
So I was finally able to find a solution. What needs to be done is the following:
Subclass the GLViewWidget
From the derived class, overload the paintGL() so that it uses the member function renderText() to render text on the screen every time the paingGL() is called.
renderText() is overloaded to support both absolute screen coordinates, as well as axis-based coordinates:
i) renderText(int x, int y, const QString &str, const QFont &font = QFont()): plot based on (x, y) window coordinates
ii) renderText(double x, double y, double z, const QString &str, const QFont &font = QFont()): plot on (x, y, z) scene coordinates
You might want to use the QtGui.QFontMetrics() class to get the dimensions of the rendered text so you can place it in a location that makes sense for your application, as indicated in the code below.
from pyqtgraph.opengl import GLViewWidget
import pyqtgraph.opengl as gl
from PyQt5.QtGui import QColor
from pyqtgraph.Qt import QtCore, QtGui
class GLView(GLViewWidget):
"""
I have implemented my own GLViewWidget
"""
def __init__(self, parent=None):
super().__init__(parent)
def paintGL(self, *args, **kwds):
# Call parent's paintGL()
GLViewWidget.paintGL(self, *args, **kwds)
# select font
font = QtGui.QFont()
font.setFamily("Tahoma")
font.setPixelSize(21)
font.setBold(True)
title_str = 'Screen Coordinates'
metrics = QtGui.QFontMetrics(font)
m = metrics.boundingRect(title_str)
width = m.width()
height = m.height()
# Get window dimensions to center text
scrn_sz_width = self.size().width()
scrn_sz_height = self.size().height()
# Render text with screen based coordinates
self.qglColor(QColor(255,255,0,255))
self.renderText((scrn_sz_width-width)/2, height+5, title_str, font)
# Render text using Axis-based coordinates
self.qglColor(QColor(255, 0, 0, 255))
self.renderText(0, 0, 0, 'Axis-Based Coordinates')
if __name__ == '__main__':
# Create app
app = QtGui.QApplication([])
w = GLView()
w.resize(800, 800)
w.show()
w.setWindowTitle('Earth 3D')
w.setCameraPosition(distance=20)
g = gl.GLGridItem()
w.addItem(g)
while w.isVisible():
app.processEvents()

Memory game using pygame

I am making a memory game for an assignment. I can get all the tiles to be covered and make them reveal themselves upon being clicked on but I cannot cover them after they have been clicked on or match them. I dont know how to match the tiles also.
class Tile:
surface = None
border_size = 3
border_color = pygame.Color('black')
# An object in this class represents a Dot that moves
#classmethod
def set_surface(cls,game_surface):
cls.surface = game_surface
# instance method
def __init__(self,x , y, image, cover):
self.image = image
self.cover = cover
self.covered = True
self.time_cover = None
# self.timer = pygame.time.get_ticks()
width = self.image.get_width()
height = self.image.get_height()
self.rect = pygame.Rect(x, y, width, height)
def draw(self):
pygame.draw.rect(Tile.surface,Tile.border_color,self.rect,Tile.border_size)
Tile.surface.blit(self.image,self.rect)
if self.covered:
Tile.surface.blit(self.cover, self.rect)
def select(self, position):
valid_click = False
if self.rect.collidepoint(position):
if self.covered:
valid_click = True
self.expose_tile()
self.time_cover = pygame.time.get_ticks() + 2000
self.update()
else:
valid_click = False
return valid_click
def update(self):
if not self.covered and self.time_cover >= 2000:
self.covered = True
return self.covered
def expose_tile(self):
# if a tile is clicked this method will show the pic ture underneath that tile
self.covered = False
def __eq__ (self, other_tile):
pass
When you call update() in the main application loop, then revealed tiles will be covered after 2 seconds.
But you can add a cover_tile method, too:
class Tile:
# [...]
def cover_tile(self):
self.covered = True
If matching tiles share the same image (self.image), then matching tiles can be identified by comparing the images. e.g.:
(In the following tileA and tileB are instances of Tile)
if tielA.image != tileB.image:
tileA.cover_tile()
tileB.cover_tile()
else
print("matching")

Creating a rectangle class that accepts parameters

I am trying to create a create a rectangle class that accepts length and width as parameters. I would like the user to be able to enter a number and have python calculate the perimeter of the rectangle.
I tried using Input() to allow the user to do this, but python does not like that. I also tried using raw_input but, I received a 'this is not-defined' error.
I was hoping someone could point me in the right direction.
class circle:
def __init__ (self):
self.radius = 1
self.width = 1
self. length = 1
my_circle = circle ()
print(2 * 3.14 * my_circle.radius)
my_circle.radius = input('Input here:')
print(float(2 * 3.14 * my_circle.radius))
my_circle.radius = 48
print(2 * 3.14 * my_circle.radius)
I would like to enter length and width and have the perimeter returned. I also will do this for the area, but I should be able to replicate the perimeter code once I figure it out.
To begin with, you can use the __init__ constructor to pass your length and width argument instead of doing a attribute assignmnent like rectange.width = ...
So the Rectangle class will look like. You can see I am passing width and length in the constructor
class Rectangle:
def __init__ (self, width, length):
self.width = width
self.length = length
def perimeter(self):
return 2*(self.length + self.width)
After this, you can call your class and function like so.
Here I convert the width and length to float (which you did not do in your circle class), pass them when I create the object of the class and then calculate parameter
length = float(input('enter length:'))
width = float(input('enter width:'))
rectangle = Rectangle(length, width)
print( rectangle.perimeter())
A sample run will then look like
enter length:5
enter width:10
30.0
Similarly your circle class will look like
class circle:
def __init__ (self, radius):
self.radius = radius
def area(self):
return 2*3.14*self.radius
radius = float(input("Enter radius of circle"))
my_circle = circle (radius)
print(my_circle.area())
#Enter radius of curcle1
#6.28

Adding a attribute to an instance

I have the below code...
import math
class Circle:
"""Class to create Circle objects"""
def __init__(self, radius=1):
"""Circle initializer"""
self.radius = radius
#property
def area(self):
"""Calculate and return the area of the Circle"""
return math.pi * self.radius ** 2
#property
def diameter(self):
"""Calculate and return the diameter of the Circle"""
return self.radius * 2
#diameter.setter
def diameter(self, diameter):
"""Set the diameter"""
self.radius = diameter / 2
def __str__(self):
return 'Circle of radius {}'.format(self.radius)
def __repr__(self):
return "Circle(radius={})".format(self.radius)
I want to add an attribute radius_log to the instance. It is a list which would contain radius values which have belonged to the circle as well as the current radius value as the last item in the list. The other properties must still work. I know I have to make the radius a property and add a setter property for the radius. Below is an example output...
circle = Circle()
circle
Circle(radius=1)
circle.radius_log
[1]
circle.radius = 2
circle.diameter = 3
circle
Circle(radius=1.5)
circle.radius_log
[1, 2, 1.5]
circle2 = Circle(radius=2)
circle2.radius_log
[2]
Any ideas on how to do this?
Change radius to property and add new property radius_log.
Inside radius property setter you will add value to _property_log list in every change. This log will be exposed through radius_log property:
import math
class Circle:
"""Class to create Circle objects"""
def __init__(self, radius=1):
"""Circle initializer"""
self.radius = radius
#property
def radius(self):
return self._radius
#radius.setter
def radius(self, value):
self._radius = getattr(self, '_radius', None)
if self._radius == value:
return
self._radius_log = getattr(self, '_radius_log', [])
self._radius_log.append(value)
self._radius = value
#property
def radius_log(self):
return self._radius_log[:]
#property
def area(self):
"""Calculate and return the area of the Circle"""
return math.pi * self.radius ** 2
#property
def diameter(self):
"""Calculate and return the diameter of the Circle"""
return self.radius * 2
#diameter.setter
def diameter(self, diameter):
"""Set the diameter"""
self.radius = diameter / 2
def __str__(self):
return 'Circle of radius {}'.format(self.radius)
def __repr__(self):
return "Circle(radius={})".format(self.radius)
circle = Circle()
print(circle)
print(circle.radius_log)
circle.radius = 2
circle.diameter = 3
print(circle)
print(circle.radius_log)
circle2 = Circle(radius=2)
print(circle2.radius_log)
This prints:
Circle of radius 1
[1]
Circle of radius 1.5
[1, 2, 1.5]
[2]

Won't Pass Object

I have been working on asteroids but my random moving asteroid function won't happen. Here is the code-
class Player():
def __init__(self, canvas):
self.shape = canvas.create_rectangle(910, 540, 960, 590, outline = "blue", fill= "white")
self.pos = canvas.coords(self.shape)
self.xspeed = 0
self.yspeed = 0
def move(self, canvas):
canvas.move(self.shape, self.xspeed, self.yspeed)
self.pos = canvas.coords(self.shape)
class Asteroid():
def __init__(self, canvas):
self.One = canvas.create_oval(0,0, 50, 50, fill="grey")
self.speedx = (10)
self.speedy = (10)
def move(self, canvas):
while True:
self.canvas.move(self.One, self.speedx, self.speedy)
self.canvas.after(20)
self.canvas.update()
def game():
#create window and canvas
parent = Tk()
canvas = Canvas(parent, width = 1920, height = 1080,
background="black")
parent.title("Asteroids")
canvas.pack()
#create player
player = Player(canvas)
enemyOne = Asteroid(canvas)
enemyOne.move(canvas)
And I get the error message-
AttributeError: 'Asteroid' object has no attribute 'canvas'
So the object canvas isn't being passed to Asteroids and def move. I included class Player for reference to show that passing canvas worked in the past. Thanks.
Your constructor call to Asteriod() passes in canvas as a parameter. But the constructor doesn't create an attribute called canvas, in other words there is no assignment
self.canvas = canvas
But the method move() calls self.canvas.move() which implies that self.canvas must exist. It doesn't, and that is why you get the message 'Asteroid' object has no attribute 'canvas'.

Resources