simple CLASS in python - python

from math import pi
class sphere(object):
def __init__(self,radius):
self.radius = radius
def get_radius(self):
return radius
def surfaceArea(self):
return 4*pi*radius**2
def volume(self):
return (4//3)*pi*radius**3
radius = input("Please enter your radius:")
print sphere.get_radius()
print sphere.surfaceArea()
print sphere.volume()
i need to write the program that prompts the user for a radius then uses your sphere class to output the surface area and volume of a sphere. and I get a type error unbound method get_Radius() must be called with sphere instance as first argument(got nothing instead). Any way to solve this problemo?

You have never created an object from class sphere. Instead of calling sphere.get_radius(), you need to first initiate an object from that class, then call the method on that object.
a = sphere(radius) # initiate an object of class sphere called a
a.get_radius() # call method on the object a.

you need to create a new object and assign redius variable
You need also to use self.redius inside the class.
Check the code below for the above mentioned-comments
from math import pi
class sphere(object):
def __init__(self,radius):
self.radius = radius
def get_radius(self):
return self.radius
def surfaceArea(self):
return 4*pi*self.radius**2
def volume(self):
return (4//3)*pi*self.radius**3
radius = input("Please enter your radius:")
s= sphere(radius)
print s.get_radius()
print s.surfaceArea()
print s.volume()

Related

Error while testing the TestAreaCreation in Python using Unittest

Question:
Define a class Circle with method init which initializes a cicle with
attribute radius, having follwing restrictions.
radius must be numeric value, if not raise type error with error message "radius must be number".
radius must be between 0 to 1000 inclusive on both sides, if not raise the value error with error message "radius must be between 0 and
1000 inclusive"
Define a class method area and circumference which must return values rounded off to 2 decimals.
Complete the definition of class TestCircleArea which tests the
behaviour of area method as specification below.
Define the test method test_circlearea_with_random_numeric_radius
which creates circle c1 with radius 2.5 and check if its computed area
match the value 19.63
Define the test method test_circlearea_with_min_radius which creates
circle c2 with radius 0 and check if its computed area match the value
0
Define the test method test_circlearea_with_max_radius which creates
circle c3 with radius 1000 and check if its computed area match the
value 3141592.65
Tried solution:
import inspect
import re
import unittest
import math
class Circle:
def __init__(self, radius):
# Define the initialization method below
self.radius=radius
if not isinstance(self.radius,(int,float)):
raise TypeError("radius must be a number")
elif(self.radius>1000 or self.radius<0):
raise ValueError("radius must be between 0 and 1000 inclusive")
else:
pass
def area(self):
# Define the area functionality below
return math.pi*(self.radius**2)
def circumference(self):
return 2*math.pi*self.radius
# Define the circumference functionality below
class TestCircleArea(unittest.TestCase):
def test_circlearea_with_random_numeric_radius(self):
# Define a circle 'c1' with radius 2.5, and check if
# its area is 19.63.
c1=Circle(2.5)
self.assertEqual(c1.area(), 2.5)
def test_circlearea_with_min_radius(self):
# Define a circle 'c2' with radius 0, and check if
# its area is 0.
c2=Circle(0)
self.assertEqual(c2.area(), 0)
def test_circlearea_with_max_radius(self):
# Define a circle 'c3' with radius 1000.1. and check if
# its area is 3141592.65.
c3=Circle(1000)
self.assertEqual(c3.area(), 3141592.65)
if __name__ == '__main__':
fptr = open('output.txt', 'w')
runner = unittest.TextTestRunner(fptr)
unittest.main(testRunner=runner, exit=False)
fptr.close()
with open('output.txt') as fp:
output_lines = fp.readlines()
pass_count = [ len(re.findall(r'\.', line)) for line in output_lines if line.startswith('.')
and line.endswith('.\n')]
pass_count = pass_count[0]
print(str(pass_count))
doc1 = inspect.getsource(TestCircleArea.test_circlearea_with_random_numeric_radius)
doc2 = inspect.getsource(TestCircleArea.test_circlearea_with_min_radius)
doc3 = inspect.getsource(TestCircleArea.test_circlearea_with_max_radius)
assert1_count = len(re.findall(r'assertEqual', doc1))
print(str(assert1_count))
assert1_count = len(re.findall(r'assertEqual', doc2))
print(str(assert1_count))
assert1_count = len(re.findall(r'assertEqual', doc3))
print(str(assert1_count))
Error:
Traceback (most recent call last):
File "Solution.py", line 61, in <module>
pass_count = pass_count[0]
IndexError: list index out of range
Please assist what's wrong.
I have just modified the init method and it worked for me in hacker rank.
class Circle:
def __init__(self, radius):
# Define the initialization method below
pattern=re.compile("^\\-?[0-9]")
if(pattern.math(str(radius))):
if(radius>=0 and radius<=1000):
self.radius=radius
else:
raise ValueError("radius must be between 0 and 1000 inclusive")
else:
raise TypeError("radius must be a number")
def area(self):
# Define the area functionality below
return math.pi*(self.radius**2)
def circumference(self):
return 2*math.pi*self.radius
# Define the circumference functionality below
you must specify return statements
class TestCircleArea(unittest.TestCase):
def test_circlearea_with_random_numeric_radius(self):
# Define a circle 'c1' with radius 2.5, and check if
# its area is 19.63.
c1=Circle(2.5)
return c1.area
return self.assertEqual(c1.area,19.3)
def test_circlearea_with_min_radius(self):
# Define a circle 'c2' with radius 0, and check if
# its area is 0.
c2=Circle(0)
return c2.area
return self.assertEqual(c2.area,0)
def test_circlearea_with_max_radius(self):
# Define a circle 'c3' with radius 1000.1. and check if
# its area is 3141592.65.
c3=Circle(1000)
return c3.area
return self.assertEqual(c3.area,3141592.65)
Modify the driver code :
Remove/delete the passcount line
Directly assign the value i.e. total number of tests to be performed.(pass_count = 3).

Class function returning 'None'

I am trying to learn class inheritance for OOP in python. The following code does what I want it to so far, but returns None after printing the pipe data when the function in the parent class is called. At first I didn't have the function returning the print statement, so I added in the return keyword, but that didn't get rid of the issue. I know it must be a return issue that I am overlooking. Any help would be appreciated.
import numpy as np
class piping:
def __init__(self, diameter, length):
self.d = diameter
self.len = length
def getPipeData(self):
return print('The pipe length is %.1fm, and the diameter is %.1fm.' % (self.len, self.d))
class hydrodynamics(piping):
def __init__(self, diameter, length, fluid, density):
super().__init__(diameter, length)
self.fluid = fluid
self.density = density
self.volume = self.getVolume()
def getVolume(self):
return np.pi*self.d**2/4
sec1 = hydrodynamics(1, 10, 'water', 1000)
sec2 = hydrodynamics(0.5, 30, 'water', 1000)
print(sec1.getPipeData())
print(sec2.getPipeData())
print(sec1.volume)
print(sec2.volume)
This is what is being returned...(as I said, everything works fine so far, except that I am having issues with the return None)
The pipe length is 10.0m, and the diameter is 1.0m.
None
The pipe length is 30.0m, and the diameter is 0.5m.
None
0.7853981633974483
0.19634954084936207
The output I was expecting is:
The pipe length is 10.0m, and the diameter is 1.0m.
The pipe length is 30.0m, and the diameter is 0.5m.
0.7853981633974483
0.19634954084936207
If that really is what you want from your program then you could change your calling code to this:
sec1.getPipeData()
sec2.getPipeData()
print(sec1.volume)
print(sec2.volume)
However, better is to not print anything inside member functions. If you change your class to the following, you can keep your driving code as is.
class piping:
def __init__(self, diameter, length):
self.d = diameter
self.len = length
def getPipeData(self):
return 'The pipe length is %.1fm, and the diameter is %.1fm.' % (self.len, self.d)
You should leave out the print statement in your definition of getPipeData and only return the string.
OR:
Call sec1.getPipeData() without the print, since the print will be executed when you call sec1.getPipeData()

Property set correctly inside an object but not accessible outside

I'm working under python pyramid, with Python3.
I have a model that looks like this:
class OneTimeCode(Base):
__tablename__ = 'otc_one_time_codes'
otc_one_time_code_id = Column(Integer, primary_key=True)
otc_one_time_code = Column(String(32))
otc_usr_user_id = Column(Integer, ForeignKey('usr_users.usr_user_id'), nullable=True)
otc_expire_time = Column(DateTime)
def __init__(self, otc_usr_user_id, otc_expire_time=None):
self.otc_usr_user_id = otc_usr_user_id
if otc_expire_time is None:
self.otc_expire_time = (datetime.now() + timedelta(6*365/12)).isoformat()
else:
self.otc_expire_time = otc_expire_time
#classmethod
def get_code(self, hlength=6):
seed = datetime.now() + timedelta(random.randrange(1,10000))
tmp_hash = hashlib.md5(seed.strftime("%Y-%m-%d %H:%M:%S.%F").encode('utf-8')).hexdigest()
if hlength == 32:
self.otc_one_time_code = tmp_hash
else:
self.otc_one_time_code = tmp_hash[0 : hlength]
print(self.otc_one_time_code)
The problem is, when I instantiate one of these objects and then explicitly call get_code, the print line at the end prints to the screen the code successfully.
However, in my view, if I explicitly try to print that property, it's 'None'
Here's what my view code looks like:
otc = OneTimeCode(
otc_usr_user_id = user.usr_user_id
)
otc.get_code()
pprint.pprint(vars(otc))
session.add(otc)
And the console output looks like this:
0d097c
{'_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at 0x50877d0>, 'otc_expire_time': '2015-02-13T10:56:14.244447', 'otc_usr_user_id': 1} 2014-08-14 22:56:14,245
INFO [sqlalchemy.engine.base.Engine][Dummy-2] INSERT INTO otc_one_time_codes (otc_one_time_code, otc_usr_user_id, otc_expire_time) VALUES (%(otc_one_time_code)s, %(otc_usr_user_id)s, %(otc_expire_time)s) RETURNING otc_one_time_codes.otc_one_time_code_id 2014-08-14 22:56:14,245
INFO [sqlalchemy.engine.base.Engine][Dummy-2] {'otc_one_time_code': None, 'otc_expire_time': '2015-02-13T10:56:14.244447', 'otc_usr_user_id': 1} 2014-08-14 22:56:14,247
INFO [sqlalchemy.engine.base.Engine][Dummy-2] COMMIT
You can see the value inside the model: 0d097c, and also the pprint object, where it doesn't look like the property exists.
Why can't I get access to this property?
Looks like you should be using a #property instead of a OTC, however it also seems like this may be something you DON'T want to calculate each time!
# for all the docstrings, let multi = Multi(2)
class Multi(object):
def __init__(self, attribute):
"""When instantiated, set self.attribute to attribute"""
self.attribute = attribute
#property
def attribute_times_ten(self):
"""accessed via multi.attribute_times_ten
and will return 20. Use properties to signify
a variable that requires some work done to it
that needs to calculated each time it's called."""
return attribute_times_ten
#classmethod
def times_ten(cls, num):
"""Not the best example, but a #classmethod will
give the class as its first argument, NOT the
instance. This is useful in lots of constructor
settings, e.g. CreateClass.fromstring("attributes")"""
return num * 5
def generate_number(self, multiplier):
"""This is just a normal method. This is what I think
you want, tbh, and you should probably call it in your
__init__ method since you NEED this to run in your OTC
for it to work as intended. Methods (like properties)
are automagically passed the instance as the first
argument, so we can CHANGE self.attribute with that."""
self.attribute = self.attribute * multiplier
Docstrings should be self descriptive, but:
multi = Multi(2)
multi.attribute_times_ten # returns 20
Multi.times_ten(8) # returns 80, note the capital M!
multi.generate_number(3) # self.attribute is now 6
multi.attribute_times_ten # returns 60
A real-world case where you might need all of the above:
class _Tile(object):
def __init__(self, x, y):
"""A naive implementation of Tile that doesn't care
what its side length is and doesn't have any properties
to hide its attributes"""
self.x = x
self.y = y
#classmethod
def tiles_to_pixels(cls, tile):
return cls(tile._x * tile.side_length, tile._y * tile.side_length)
#classmethod
def tiles_to_tiles(cls, tile):
return cls(tile._x, tile._y)
class Tile(object):
def __init__(self, x, y, side_length):
"""A tile object in a map"""
self._x = x # x-coord in tiles
self._y = y # y-coord in tiles
self.side_length = side_length # pixels per tile
#property
def in_pixels(self):
"""self.in_pixels returns an object whose .x and .y
correspond to the x and y position IN PIXELS of the
top-left corner of the tile."""
_tile = _Tile.tiles_to_pixels(self)
return _tile
#property
def in_tiles(self):
"""self.in_tiles returns an object whose .x and .y
correspond to the x and y position IN TILES of the
top-left corner of the tile."""
_tile = _Tile.tiles_to_tiles(self)
return _tile
def change_side_length(self, new_length):
"""Use to change the side length. This can break
your whole map since it's naive, so be careful."""
self.side_length = new_length
my_tile = Tile(0,0,32) # 32 pixel tile starting at (0,0)
my_tile.x # NameError, since it's called my_tile._x
my_tile.in_tiles.x # 0
my_tile.in_pixels.y # 0
other_tile = Tile(4,7,32) # 32 pixel tile starting at (4,7)
other_tile.y # NameError, see above
other_tile.in_tiles.y # 7
other_tile.in_pixels.x # 128

How do I rewrite this function now that it needs to call upon a method in a class from a different file?

Here is the function (it's in a file, "worldmodel.py"):
def add_entity(world, entity):
pt = entities.get_position(entity)
if within_bounds(world, pt):
old_entity = occ_grid.get_cell(world.occupancy, pt)
if old_entity != None:
entities.clear_pending_actions(old_entity)
occ_grid.set_cell(world.occupancy, pt, entity)
world.entities.append(entity)
And here is the class in a file named, "occ_grid.py":
class Grid:
def __init__(self, width, height, occupancy_value):
self.width = width
self.height = height
self.cells = []
# initialize grid to all specified occupancy value
for row in range(0, self.height):
self.cells.append([])
for col in range(0, self.width):
self.cells[row].append(occupancy_value)
def set_cell(self, point, value):
self.cells[point.y][point.x] = value
My question is, how would I rewrite the line of code in "def add_entity" that refers to "set_cell"? (Now that I've made set_cell a method of the class Grid) NOTE: Before I made set_cell part of the grid class, it was a function outside of the class (but still in the same file as the class) Thanks!
You'll need to import occ_grid in your worldmodel.py, then instantiate a Grid object and call that objects set_cell()-method. The add_entity needs to get the Grid-object as its parameter unless it can safely instantiate new ones at will.
Here's a naive example which does not work but demonstrates what I mean:
import occ_grid
g = occ_grid.Grid(your_width, your_height, occupancy)
def add_entity(world, entity, grid):
pt = entities.get_position(entity)
if within_bounds(world, pt):
old_entity = grid.get_cell(world.occupancy, pt)
if old_entity != None:
entities.clear_pending_actions(old_entity)
grid.set_cell(world.occupancy, pt, entity)
world.entities.append(entity)
add_entity(world, entity, g)
Unless you make the set_cell function a static method of the Grid class, you're going to need and instance of Grid.
from occ_grid import Grid
I am going to make an assumption here, and say that your want your grid to be part of the world? Either way, this is an example of instantiating that class.
class World:
grid = Grid()
def add_entity(world, entity):
# All that other stuff.
world.grid.set_cell(pt, entity)
There are two issues here, (1) calling functions across modules and (2) calling methods of classes.
It seems you can already do (1).
The trick is that although methods are defined as
def methodName(self, ...)
They are called as
object.methodName(...)
And object implicitly becomes the "self" Parameter. Here is an example:
import occ_grid # Import the module (file) that contains Grid.
.
.
world.occupancy = occ_grid.Grid() # Create an instance of Grid.
.
.
def add_entity(world, entity):
pt = entities.get_position(entity)
.
.
world.occupancy.set_cell(pt, entity)
In this example, grid is a global variable, which is probably not a good design. I guess it should be a property of world, but that's only a guess.

Class python error

Original class program:
from Circle import circle
class circle:
def __init__(self,radius=1): #write def __init__(self,radius=1) to set a value
self.radius=radius
# constructer constructs the object and initializes it
def getArea(self):
return(3.142*self.radius*self.radius)
def getPerimeter(self):
return(2*3.142*self.myradius)
Using class:
def main():
c1=circle()
#If below happens
c1.radius=-1
#if above happens then negative value will be returned
c2=circle(5)
c3=circle(3)
print(c1.getArea())
print(c2.getArea())
print(c3.getArea())
main()
I was just trying to learn about classes in python. When I run the program it says that
builtins.AttributeError: 'circle' object has no attribute 'getArea'
I am not able to understand why it is happening.
What about something like this:
from math import pi
class Circle:
def __init__(self,radius=1):
self.radius=radius
def get_area(self):
return pi * self.radius**2
def get_circumvention(self):
return 2 * pi * self.radius
if __name__ == "__main__":
c1=Circle()
#If below happens
c1.radius=-1
#if above happens then negative value will be returned
c2=Circle(5)
c3=Circle(3)
print(c1.get_area())
print(c2.get_area())
print(c3.get_area())
print(c1.get_circumvention())
print(c2.get_circumvention())
print(c3.get_circumvention())
The error you are seeing is probably because you have that weird import statement on top that hides your circle class (you try to call Circle.circle.getArea() that does not exists)
Furthermore:
python coded styles suggest CapsWords for class names and
lowercase for methods and functions.
self.myradius is not defined in __init__ so getPerimeter will fail.
The brackets in the methods are not necessary.
math has pi
To the power is noted as ** (5**2 == 25)
Use the if __name__ == "__main__": construct if you only want to execute when directly run and not on import.
Perimeter -> circumvention
Use the import statement in another python file that you want to use the Circle class in: from whateveryounamedthisfile import Circle. Then you can use Circle like you would in this file.
Your import is pointless. Don't import 'circle' from 'Circle' if you, as the comments have stated. Also, you have not defined the 'myradius' attribute, therefore your 'getPerimeter()' function will not work unless you change that.

Categories