How do you multiply values within a class in python? - python

class bread:
def __init__(self,grain,cost,number):
self.grain=(grain)
self.cost=int(cost)
self.number=int(number)
def price(self):
p=self.cost*self.number
print(p)
apple=bread("wholemeal",int(2),int(12))
print(apple.grain,apple.cost,apple.number)
print (apple.price)
After I enter this block of code I should expect to see 24, but instead I get:
bound method bread.price of <main.bread object at 0x05CC7430>>
I am new to oop and starting to experiment but I can't find a solution.

You need to call price:
apple.price()
However, variable attribute behavior with methods can be achieved using property:
class bread:
def __init__(self,grain,cost,number):
self.grain=grain
self.cost=cost
self.number=number
#property
def price(self):
return self.cost*self.number
apple=bread("wholemeal",2, 12)
print(apple.price)

In this case you don't seem to want to deal with a class object, but just want to get the output. This you can do like so:
class bread:
def __init__(self, grain, cost, number):
self.grain = (grain)
self.cost = int(cost)
self.number = int(number)
return self.price()
def price(self):
p = self.cost * self.number
print("%s : %d" % (self.grain, p))
bread("wholemeal", 2, 12)
As a beginner you should not worry too much about things like property but keep it as simple (and verbose) as possible. Also because you're making the input for the grain type, I'm guessing you want to print that out together with the value.
To unpack the changes I made to your code as an example for some basic coding practices:
note the spacing between functions
note the spacing between individual items
note how the output is produced with print()
Once all this is done, all we have to do is make the call we would otherwise have to make ourselves everytime, inside __init__. Good luck, and have fun learning python!

When you print the function at the end, you actually need to call the function. Currently you are just getting the instance of the method within the object. But you should be using parenthesis () to call the function when you print it. You also don't need to print the function call to get 24 since you are already printing the output of number and cost within your function. But if you do want to print the function, you can use a return value within your function. Here is an example below:
class bread(object):
def __init__(self, grain, cost, number):
self.grain = grain
self.cost = cost
self.number = number
def price(self):
price = self.cost * self.number
return price
apple=bread("wholemeal", 2, 12)
print(apple.price())
Notice that at the end of the code We actually called the function () when printing it. You will then print the return value of the function. If you wanted to simply print the value within the function, you could call the function at the bottom of the code without printing it like this:
apple.price()
and then choose to put the print statement within the price method. Your output from the code above it 24:
24

Related

Im having "TypeError: 'float' object is not callable" error. Plz anybody who can help. "Thanks"

class Employee:
def __init__(self, name, salary, increment):
self.name = name
self.salary = salary
self.increment = increment
#property
def salaryafterIncre(self):
return self.salary * (1+self.increment)
#salaryafterIncre.setter
def salaryafterIncre(self):
self.salary = self.salary * (1+self.increment)
e1 = Employee("shubh", 10000, 0.1)
print(e1.salaryafterIncre)
e1.salaryafterIncre()
print(e1.salary)
When you access the property you don't treat it as callable in python.
In your case e1.salaryafterIncre() is causing the problem. Change it to e1.salaryafterIncre
If you want to change the value with property.setter and keep that value in a variable inside the init function, you shouldn't give the imported value directly to salary in the init function.
Property does what you want and outputs it, but the value of salary doesn't change. The value of salary is the value it gets from outside. You can replace it with a non-property function and keep the value you changed.
If you give salary a random value and pass the imported value to property.setter function. property.setter does what you want and changes the value you hold in the init function and stores that value.
that is, if we want to replace a value in the init function with a property. you should not equate it to an external value inside the init function.
the code has been updated to do the action you specified,
you can try this;
class Employee:
def __init__(self,name, salary, increment):
self.salary = 0
self.name = name
self.increment = increment
#property
def salaryafterIncre(self):
return self.salary
#salaryafterIncre.setter
def salaryafterIncre(self,salary):
self.salary = self.salary+ salary * (1+self.increment)
e1 = Employee("shubh", 10000, 0.1)
e1.salaryafterIncre = 10000
print(e1.salary)
e1.salaryafterIncre = 10000
print(e1.salary)
(I'm keeping this answer basic -- this may be an oversimplification but is good enough for what you're doing).
By marking salaryafterIncre with #property, you've turned it into something that behaves a lot like a variable, rather than a method.
So when you write e1.salaryafterIncre, this actually already returns the value of this salary, which is a variable of type float. By adding () to this, you're attempting the call this floating point number as a function, which doesn't make sense! So just leave out the () when interacting with this property.
Edit: So the property function,
#property
def salaryafterIncre(self):
return self.salary * (1+self.increment)
does make sense as you've currently written it. The line print(e1.salaryafterIncre) would print (1 + increment)*salary.
However your setter doesn't make sense. A setter should take a value, and then update a variable with that value. A use case might be, perhaps you want some event to fire off every time the variable is updated, so you make it a property and fire that event off in the function. Or maybe other things depend on this variable and need to be recomputed when its value changes.
What you have instead is a setter which takes no arguments (besides self) and then does an update to self.salary. This should not be a setter, but its own method, perhaps:
def increment_salary(self):
self.salary = (1 + self.increment) * self.salary
Now, if you did:
e1 = Employee("shubh", 10000, 0.1)
print("Old salary: ", e1.salary)
print("Predicted salary: ", e1.salaryafterIncre)
e1.increment_salary()
print("New salary: ", e1.salary)
you would obtain the output:
10000
11000
11000
Is there a particular reason you want to use properties here instead of just variables and methods? Properties are just methods that look like variables.

FastQ programming error

So I'm trying to parse a FastQ sequence, but I'm a beginner to Python, and I'm a little confused as to why my code isn't working. This is what the program is supposed to carry out:
if I enter the FASTQ seqname line...
#EAS139:136:FC706VJ:2:2104:15343:197393
...then the program should output:
Instrument = EAS139
Run ID = 136
Flow Cell ID = FC706VJ
Flow Cell Lane = 2
Tile Number = 2104
X-coord = 15343
Y-coord = 197393
Here's my unfinished code thus far:
class fastq:
def __init__(self,str):
self.str = inStr.replace ('#',' ').split (':')
def lists (self,parameters):
self.parameters = ("Instrument","Run ID","Flow Cell ID","Flow Cell Lane","Tile Number","X-coordinates","y-coordinates")
def zip (self,myZip,zippedTuple):
self.Zip = zip(self.parameters,self.transform)
self.zippedTuple = tuple(myZip)
print (tuple(myZip))
def main():
seq = input('Enter FastQ sequence:')
new_fastq = fastq(str)
new_fastq.lists()
new_fastq.zip()
main()
The reason that your code isn't working is that it's more-or-less entirely wrong. To address your errors in the order we reach them when trying to run the program:
main:
new_fastq = fastq(str) does not pass the seq we just input, it passes the built-in string type;
__init__:
Calling the argument to fastq.__init__ str is a bad idea as it masks the very built-in we just tried to pass to it;
But whatever you call it, be consistent between the function definition and what is inside it - where do you think inStr is coming from?
lists:
Why is this separate to and not even called by __init__?
Why don't you pass any arguments?
What is the argument parameters even for?
zip:
Rather than define a method to print the object, it is more Pythonic to define fastq.__str__ that returns a string representation. Then you can print(str(new_fastq)). That being said;
Again, you mask a built-in. On this occasion, it's more of a problem because you actually try to use the built-in inside the method that masks it. Call it something else;
Again, you put unnecessary arguments in the definition, then don't bother to pass them anyway;
What is self.transform supposed to be? It is never mentioned anywhere else. Do you mean self.str (which, again, should be called something else, for reasons of masking a built-in and not actually being a string)?
myZip is one of the arguments you never passed, and I think you actually want self.Zip; but
Why would you create x = tuple(y) then on the next line print(tuple(y))? print(x)!
Addressing those points, plus some bonus PEP-008 tidying:
class FastQ:
def __init__(self, seq):
self.elements = seq.replace ('#',' ').split (':')
self.parameters = ("Instrument", "Run ID", "Flow Cell ID",
"Flow Cell Lane", "Tile Number",
"X-coordinates", "y-coordinates")
def __str__(self):
"""A rough idea to get you started."""
return "\n".join(map(str, zip(self.parameters, self.elements)))
def main():
seq = input('Enter FastQ sequence: ')
new_fastq = FastQ(seq)
print(str(new_fastq))
main()

How do I automatically pass arguments to a function on certain objects

I am trying to make a text based game using Python. I set up a radar() function but currently the only way to use it is if the player types in arguments directly to the console. I want the program to detect which vehicle the player is piloting and pass whatever attributes of that vehicle need to be passed automatically without the player having to type them.
For example
Instead of the player having to type in
'a.radar([100,100,100], 100)' in order to use the radar() function I want the player to only need to type in 'radar', and all other parameters to be passed automatically. How can I make this happen? Should I restructure this code entirely?
My code:
class Mobilesuits:
#class global variables/methods here
instances = [] #grid cords here
def __init__(self,armor,speed,name,description,cockpit_description,\
radar_range, coordinates):
Mobilesuits.instances.append(self)
self.armor=armor
self.speed=speed
self.name=name
self.description=description
self.cockpit_description=cockpit_description
self.radar_range=radar_range
self.coordinates=coordinates
def radar(self, coordinates, radar_range):
for i in range(len(a.instances)):
cordcheck=a.instances[i].coordinates
if cordcheck == coordinates:
pass
elif (abs(cordcheck[0]-coordinates[0]) <= radar_range) and \
(abs(cordcheck[1]-coordinates[1]) <= radar_range) and \
(abs(cordcheck[2]-coordinates[2]) <= radar_range):
print("%s detected at %s ") %(a.instances[i].description, a.instances[i].coordinates)
a=Mobilesuits(100,100,"Leo","leo desc","dockpit desc",100,[100,100,100])
b=Mobilesuits(100,100,"Leo","leo desc","dockpit desc",100,[300,100,100])
c=Mobilesuits(100,100,"Leo","leo desc","dockpit desc",100,[100,150,100])
a.radar([100,100,100], 100)
Have your program take input with the raw_input function:
user_input = raw_input()
and then do something based on the input:
if user_input == "some_command":
do_something(appropriate, variables)
For example,
if user_input == "radar":
a.radar([100,100,100], 100)
You might also want to change the way the radar method takes arguments. It looks like at least one of the coordinates or the radar_range arguments should be coming from the corresponding attributes of self. For example, if a mobile suit's radar should automatically use the mobile suit's own coordinates and radar range, you could write the method as follows:
def can_detect(self, other):
for own_coord, other_coord in zip(self.coordinates, other.coordinates):
if abs(own_coord - other_coord) > self.radar_range:
return False
return True
def radar(self):
for other in Mobilesuits.instances:
if other is not self and self.can_detect(other):
print "%s detected at %s" % (other.description, other.coordinates)
Do it like builtins do.
Look, str() function is just specialized call to __str__ function. object class has default __str__, and if you're not using p3k, str() has some logic for objects without __str__.
In the end, str() builtin MAY look like this (conceptually, implementation is probably quite different):
def str(obj):
try:
return obj.__str__()
except AttributeError:
return default_behaviour(obj)
You can do something alike.
You'll need function which will return user object (say there are 3 players in the game: A, B and C, where A is controlled by user; you'll need function get_user_player() which shall return A instance.
Then, you need to implement your argumentless radar function:
def radar():
return get_user_player().radar()
Now call to radar() will result in automatic finding of user controlled instance and calling radar on it.

Re-evaluating a function to get a new random value in python

here is the code that I am having a problem with(simplified to make it clearer). It is for a text based game just to help learn things.
class Character(object):
def __init__(self):
self.level = 5
self.moveset = [None,None,None,None]
def movesetleveling(self):
if self.level > 4:
self.moveset[0] = Punch(self.level)
def punch(level):
damagedealt = random.randint(0,5)**level
return damagedealt
I would like to know how I can make self.moveset[0] = Punch() rather than being equal to the output of Punch() in this block of code. So that everytime i run it in a while loop it will re-evaluate the output of Punch() rather than evaluating Punch() once and assigning that to the 0th index of self.moveset[0].
You could assign a function to self.moveset[0] instead of its result (using functools.partial()):
from functools import partial
self.moveset[0] = partial(punch, self.level)
Then later, in your while loop, just call it:
while True:
new_punch_every_time = self.moveset[0]() #note: parentheses
self.moveset[0]() calls punch function with level parameter set to self.level (its value at the time of partial call).
It works because functions, methods are first class citizens in Python. You can pass them as parameters to other functions, return from functions, bind to a different name, append to a list, etc.

Why is my instance counter display 0 in this Python code?

I made a simple code to demonstrate and understand classes - however when I run this, my lists show that they are empty, containing "None" values instead of the strings that the user enters as names.
#Static methods do not require the object to be initiated. Can be remotely accessed from outside the function .
#Counting critters and remote access.
class Orc (object):
total = 0
def get_score (self):
print "The number of orcs the orc factory has made is",Orc.total
def __init__ (self):
Orc.total += 1
name = raw_input ("I am a critter by the name of:\n")
#Creating 10 Orcs
list = []
for i in range (4): list[i] = list.append(Orc.get_score(Orc()))
print "You have created 4 Orcs!" print "The name of your first orc is",list[0] print "The name of your fourth orc is", list[3]
There are a few errors in your code. First in the way you use lists. Second, in the way you call methods on your objects. The combination of errors explains why you have a list of None at the end.
List name
list = []
Don't name a list list. It is already the name of, well..., the list class, i.e. in Python you can do my_list = [] or my_list = list() with the exact same effect.
You want to call your list something meaningful, like orc_list
List Insertion
for i in range (4):
orc_list[i] = orc_list.append(...)
orc_list.append does what it says: it appends an element to the given list. However, it does not return anything. So what your code is doing is
taking an empty list
setting i to 0
inserting what you pass to append at the end of the list
inserting None at index i and thus overriding what you did in 3.
incrementing i
going back to 3.
You want to simply use orc_list.append(...)
Method Call
Orc.get_score(Orc())
I imagine you are getting confused by the self argument. In a class, Python will automatically pass the instance you are working on as the self argument. You don't need to provide that argument.
You want to write
Orc().get_score()
This creates an Orc object, and then calls get_score on it. Python 'injects' the Orc instance you have created into get_score for you.
Method Return
We're now down to
orc_list.append(Orc().get_score())
which is equivalent to
score = Orc().get_score()
orc_list.append(score)
The problem is that there is no return statement in get_score. This means that python will return None when you call that method. Which means that you are appending None to your list.
You want to have
def get_score(self):
print "The number of orcs the orc factory has made is", Orc.total
return Orc.total
Static behaviour
If you really wanted to have a method not bound to an instance of the Orc class, you could use either a class method or a static method.
In your case, you do not need to do anything to the class object, so your choice would be to use a static method.
You would declare
#staticmethod
def get_score():
print "The number of orcs the orc factory has made is", Orc.total
You would then call that method using Orc.get_score()
To define a class method in Python, use classethod decorator and call the first parameter cls
class Orc(object):
total = 0
#classmethod # this will make the method a class method
def get_score (cls): # convention is then to call the 1st param 'cls'
print "The number of orcs the orc factory has made is", cls.total
def __init__ (self):
Orc.total += 1
# use self is you want' to register a name
# however putting a raw_input in an __init__ is NOT recommanded
# you should pass name as a parameter
# and call the raw_input in the for loop
self.name = raw_input ("I am a critter by the name of:\n")
orcs = [] # don't call your lists 'list' because `list` is standard Python function
for i in range(4): # put this on two lines for clarity or use a comprehension list
orcs.append(Orc())
print "You have created 4 Orcs!"
print "The name of your first orc is", orcs[0].name # if you don't use `name`, you will see the reference of the object
print "The name of your fourth orc is", orcs[3].name
A cleaner version (something you should aim for):
class Orc(object):
total = 0
#classmethod #
def get_instances_count(cls):
"""
Return the number or orcs that have been instanciated
"""
# ^ Put some documentation below your method
# these are called "docstring" and are detected by Python
# you should return values in method rather than print
# there are rare cases when you do want print, but when you'll
# encounter them, you won't need me to correct your code anymore
return cls.total
def __init__ (self, name):
Orc.total += 1
self.name = name # we get the name as a parameter
l = []
for i in range(4): # put this on two lines for clarity or use a comprehension list
orc = Orc(raw_input("Enter a name:\n"))
l.append(orc)
print "You have created %s Orcs!" % Orc.get_instances_count()
print "The name of your first orc is", l[0].name #
print "The name of your fourth orc is", l[3].name
Now the more Pythonic version (something you should be able to do once used to Python):
class Orc(object):
total = 0
# you don't need accessors in Python: most things are public anyway
# and you got property
def __init__ (self, name):
Orc.total += 1
self.name = name # we get the name as a parameter
def __str__(self):
# this will be call when printing an orc
return self.name
# list comprehension are quick and clean ways to create lists
# give a real name to your list
orcs = [Orc(raw_input("Enter a name:\n")) for i in range(4)]
# using parenthesis for `print` is a good habit to take with then incoming Python 3
print("You have created %s Orcs!" % Orc.total)
for i, orc in enumerate(orcs):
print("Orc #%s is %s" % (i, orc))
list.append returns a None value, so it essentially never makes sense to assign its result to anything. You call append for the side-effects, i.e., to have it put a value at the end of the list. Like this:
for i in range (4):
list.append(Orc.get_score(Orc()))
I don't think the Orc.get_score(Orc()) is what you want, either: it also returns None instead of a score and the method call is technically correct but unlikely to be what you really intend.
Why should there be something in your list?
you do:
list.append(Orc.get_score(Orc())
which is equivalent to:
item_to_add = Orc.get_score(Orc())
list.append(item_to_add)
Your method Orc.get_score has no return statement, so it returns None. therefore, item_to_add will be None, and None will be appended to your list.
As a side note: python is not java. Dont use classes just to use classes. Use classes, when you want to follow OO-Pradigma, i.e. sending messages to objects.

Categories

Resources