i've written this simple code, i think that it doesn't contain gramatical error but it doesn't execute so i think that thare is somewhere a logical error :o, so please i need help !! someone can save me ?! :D
class NumberGenerator:
"""A simple class that contains functions to generate ranges of numbers"""
#classmethod
def generate(quantity, value=[]):
while quantity: value.append(quantity) ; quantity -= 1
return value
class Figure:
"""Abstract class for geometric figures"""
def init(self, name):
"""This is the constructor"""
self._name = name
def name(self):
return self._name
class Rectangle(Figure):
"""Rectangle figure"""
def init(self, width, height):
Figure.__init__("rectangle")
self._width = width
self._height = height
def width(self):
return self.width
def height(self):
return self.height
def size(self):
self.width() * self.height()
if __name__ == "__main__":
# We print the range(10,0,-1)
print NumberGenerator.generate(10)
# We print the range(20,0,-1)
print NumberGenerator.generate(20)
# We create a rectangle
r = Rectangle(10, 20)
print r.size()
# EOF
Indentation aside, two errors are right here:
def width(self):
return self.width
def height(self):
return self.height
This should read:
def width(self):
return self._width
def height(self):
return self._height
Also, constructors should be called __init__ and not init.
Finally, the generate() method has several issues:
You probably meant to say #staticmethod and not #classmethod (class methods should take an implicit first argument, which your method doesn't).
The loop is unnecessary (a simple range() call can do the trick).
The method has a subtle bug in it, whereby the second argument (value) is preserved across calls to generate(). If you must extend value, move value = [] into the body of the method.
Your first error message is AttributeError: 'int' object has no attribute 'append' from NumberGenerator.generate due to no self as the first argument and it is then creating the variable quantity as an instance of NumberGenerator.
Once you fix that, your next error is in the fact that init() should actually be __init__(), and once you fix that you have a further error, but I will leave that exercise to yourself.
Related
I have the following class:
class Resources:
"""
Resources class.
"""
def __init__(self, food: int, gold: int):
self.F = food
self.G = gold
def __sub__(self, other):
return Resources(self.F - other.F, self.G - other.G)
def __getitem__(self, attr):
return self.__getattribute__(attr)
I am coding another class for buying / selling specific resources. The part Im struggling with is this:
a = Resources(100, 200)
a['F'] -= 50
When executed, TypeError: 'Resources' object does not support item assignment
I can get any attribute once I know its name, but I don't know how to change its value through the -= operator.
So, to clarify, the question is: How to substract a float value to a given attribute selected by using a string, and store the result in the same attribute?
An answer to the post-edit question:
def reduce_resource(self, resource_name, value):
setattr(self, resource_name, getattr(resource_name) - value)
Either do
self.resources[what] = self.resources[what] - amount
or implement the __isub__() method in your Resources class, which is called when the -= operator is used (just like the - operator calls the __sub__() method).
# mutating this object
def __isub__(self, other):
self.F -= other.F
self.G -= other.G
return self
# not mutating this object, returning a copy that will be assigned over the original
def __isub__(self, other):
return self - other # delegate to __sub__()
(a similar method, __rsub__(), exists for if your object is used on the right side of a - sign instead of the left side. Note that this trio of methods exists for most operators).
Be careful to check whether your Resources objects should be mutable or immutable. The procedure for x -= y unrolls to x = x.__isub__(y), so the method can be built without mutating the original x, as explained by this answer.
Well, after some research I found this solution:
name = 'G'
amount = 50
a = Resources(100, 200)
vars(self.resources)[name] -= amount
I have a simple class. I want to set the periodicity property using a private attribute which is tested before being used to set the public attribute. I am passing self around the class module, when I run the test code the function seems to expect 2 arguments. I thought it should ignore self and ask for the one freq parameter. I am trying to be "pythonic" and use #property with .setter. Do I need to change the property call? If I remove self from set_periodicity it says it does not recognize self.
class ModelSetUp:
def __init__(self):
self.periodicity= None
#property
def set_periodicity(self,freq):
self.periodicity = self._periodicity
#set_periodicity.setter
def set_periodicity(self,freq):
if freq in ("Q","S","A"):
self._periodicity = freq
else:
raise ValueError("Frequency Must Be Q, S or A")
if __name__=="__main__":
mod = ModelSetUp()
mod.set_periodicity("Q")
Properties don't take any arguments, nor are they callable. Try this:
class ModelSetUp:
def __init__(self):
self._periodicity = None
#property
def periodicity(self):
return self._periodicity
#periodicity.setter
def periodicity(self, freq):
if freq in ("Q","S","A"):
self._periodicity = freq
else:
raise ValueError("Frequency Must Be Q, S or A")
if __name__=="__main__":
mod = ModelSetUp()
mod.periodicity = "Q"
So Im just learning how to integrate two classes in one call and I keep getting the error on the print statement: TypeError: 'str' object is not callable. Do I need to create a str contructor? Or do I need to intergrate the two classes into one?
class Election:
def __init__(self, place, ballot):
self.place=place
self.ballot=ballot
def place(self):
return self.place
def getBallot(self):
return self.ballot
def getContest(self,number):
if self.ballot[number]:
return self.ballot[number]
else:
return False
def size(self):
return len(self.ballot)
def addContest(self,Contest):
self.ballot=self.ballot.append(Contest)
return self.ballot.get(Contest)
class Contest:
def __init__(self, position, cands):
self.position = position
self.cands = {"Jones":0,"Smith":0}
def getPosition(self):
return str(self.position)
def getCandidates(self):
return str(self.cands)
def getTally(self,candidate):
return self.cands[candidate]
def addTally(self,candidate,n_votes):
self.cands[candidate]=self.cands[candidate]+n_votes
def main():
elect = Election('TestTown', [
Contest('Senator', ['Jones', 'Smith']),
Contest('Mayor', ['Anderson', 'Green'])])
print(elect.place())
elect.getContest(1)# --> <Election object at 0x7f4b359cf5d0>
elect.getContest(1).getTally('Anderson')# --> 0
main()
The error tells you exactly what the problem is: elect.place is a string, and you're trying to call it by adding (). elect.place is the string 'TestTown'. Simply refer to it as normal. Don't call it. It's not a function or other callable.
print(elect.place)
And you can get rid of the getters, e.g. def place, def getBallot, def getPosition, and so on. The instance variables are already directly accessible.
The problem is these two lines of code:
def place(self):
return self.place
See, now your Election object has self.place as a string and as a function. In this case, it appears to be the case that the string is shadowing the function. To fix this, follow the same convention as your other class functions and name the function getPlace.
I'm learning Python and I'm getting confused with syntax for calls from one class to another. I did a lot of search, but couldn't make any answer to work. I always get variations like:
TypeError: __init__() takes exactly 3 arguments (1 given)
Help much appreciated
import random
class Position(object):
'''
Initializes a position
'''
def __init__(self, x, y):
self.x = x
self.y = y
def getX(self):
return self.x
def getY(self):
return self.y
class RectangularRoom(object):
'''
Limits for valid positions
'''
def __init__(self, width, height):
self.width = width
self.height = height
def getRandomPosition(self):
'''
Return a random position
inside the limits
'''
rX = random.randrange(0, self.width)
rY = random.randrange(0, self.height)
pos = Position(self, rX, rY)
# how do I instantiate Position with rX, rY?
room = RectangularRoom()
room.getRandomPosition()
You don't need to pass self - that is the newly created instance, and is automatically given by Python.
pos = Position(rX, rY)
Note that the error here is happening on this line, however:
room = RectangularRoom()
The issue on this line is you are not giving width or height.
Maybe the answers to these previous questions help you understand why python decided to add that explicit special first parameter on methods:
What is the purpose of self?
Why do you need explicitly have the "self" argument into a Python method?
Python - why use "self" in a class?
The error message may be a little cryptic but once you have seen it once or twice you know what to check:
Did you forgot to define a self/cls first argument on the method?
Are you passing all the required method arguments? (first one doesn't count)
Those expecting/given numbers help a lot.
I'm learning Python OOP now and confused with somethings in the code below.
Questions:
def __init__(self, radius=1):
What does the argument/attribute "radius = 1" mean exactly?
Why isn't it just called "radius"?
The method area() has no argument/attribute "radius".
Where does it get its "radius" from in the code?
How does it know that the radius is 5?
class Circle:
pi = 3.141592
def __init__(self, radius=1):
self.radius = radius
def area(self):
return self.radius * self.radius * Circle.pi
def setRadius(self, radius):
self.radius = radius
def getRadius(self):
return self.radius
c = Circle()
c.setRadius(5)
Also,
In the code below, why is the attribute/argument name missing in the brackets?
Why was is not written like this: def __init__(self, name)
and def getName(self, name)?
class Methods:
def __init__(self):
self.name = 'Methods'
def getName(self):
return self.name
The def method(self, argument=value): syntax defines a keyword argument, with a default value. Using that argument is now optional, if you do not specify it, the default value is used instead. In your example, that means radius is set to 1.
Instances are referred to, within a method, with the self parameter. The name and radius values are stored on self as attributes (self.name = 'Methods' and self.radius = radius) and can later be retrieved by referring to that named attribute (return self.name, return self.radius * self.radius * Circle.pi).
I can heartily recommend you follow the Python tutorial, it'll explain all this and more.
def __init__(self, radius=1):
self.radius = radius
This is default value setting to initialize a variable for the class scope.This is to avoid any garbage output in case some user calls c.Area() right after c = Circle().
In the code below, why is the attribute/argument "name" missing in the brackets?
In the line self.name = 'Methods' you are creating a variable name initialized to string value Methods.
Why was is not written like this: def init(self, name) and def
getName(self, name)?
self.name is defined for the class scope. You can get and set its value anywhere inside the class.
The syntax radius = 1 specifies a parameter "radius" which has a default value of 1:
def my_func(param=1):
... print(param)
...
my_func() #uses the default value
1
my_func(2) #uses the value passed
2
Note that in python there exists more kinds of parameters: positional and keyword parameters, or both.
Usually parameters can be assigned both using the positional notation and the keyword:
>>> def my_func(a,b,c):
... print (a,b,c)
...
>>> my_func(1,2,3)
(1, 2, 3)
>>> my_func(1,2,c=3)
(1, 2, 3)
Python uses "explicit" instance passing, so the first self parameter is used to pass the instance on which the methods are called. You can think of self as being the this of Java. But you must always use it to access instance attributes/methods. You can't call just area(), you must say self.area().
When you do self.attribute = 1 you create a new attribute attribute with value 1 and assign it to the instance self. So in the area() method self.radius refers to the radius attribute of the self instance.
The __init__ method is a special method. It's something similar to a constructor.
It is called when you instantiate the class. Python has a lot of these "special methods", for example the method __add__(self, other) is called when using the operator +.