I'm writing my own code language in Python (called Bean), and I want the math functions to have the syntax:
print math.add(3+7)
==>10
print math.mul(4*8)
==>32
and so on. So far my code is:
bean_version = "1.0"
console = []
print "Running Bean v%s" % bean_version
#Math Function
class math(object):
def __init__(self, add, sub, mul, div):
self.add = add
self.sub = sub
self.mul = mul
self.div = div
def add(self):
print self.add
math = math(1,0,0,0)
print math.add()
But this will return an error, saying that TypeError: 'int' object is not callable. I can change the "add" function to a different name and it will work, but I would like to use "add" as the name.
Thanks (This is Python 2.7.10 by the way)
An object can't have two properties with the same name. So if you have a property called add that holds a number, it can't also have a method called add, because methods are just properties that happen to hold functions. When you do:
this.add = add
you're replacing the method with that number. So you need to use different names.
You say you want to be able to call math.Add(). But the method you defined is add. It should be:
def Add():
print this.add
This doesn't conflict with the add property that holds the number, since names are case-sensitive.
If you don't want to change the name of the add function, you can just change self.add. These two adds are conflicting with each other. You will not get any error if you run this:
bean_version = "1.0"
console = []
print "Running Bean v%s" % bean_version
#Math Function
class math(object):
def __init__(self, add, sub, mul, div):
self.adds = add
self.sub = sub
self.mul = mul
self.div = div
def add(self):
print self.adds
math = math(1,0,0,0)
print math.add()
Related
I have a method object with assigned value from user's input inside a class. The problem is i can't use the method object maxcount_inventory = int(input("How many Inventories: ")) outside the class. The error says "method' object cannot be interpreted as an integer"
class CLASS_INVENTORY:
maxcount_inventory = int(input("How many Inventories: "))
inventory_name = []
def __init__(Function_Inventory):
for count_inventory in range(Function_Inventory.maxcount_inventory):
add_inventory = str(input("Enter Inventory #%d: " % (count_inventory+1)))
Function_Inventory.inventory_name.append(add_inventory)
def Return_Inventory(Function_Inventory):
return Function_Inventory.inventory_name
def Return_Maxcount(Function_Inventory):
return maxcount_inventory
maxcount_inventory = CLASS_INVENTORY().Return_Maxcount
Another extra question if I may, how can i access items in the list per index outside the class? I have the code below, but I think it's not working. Haven't found out yet due to my error above.
for count_inventory in range(maxcount_inventory):
class_inv = CLASS_INVENTORY().Return_Inventory[count_inventory]
print(class_inv)
skip()
Here is my full code: https://pastebin.com/crnayXYy
Here you go I've refactored your code.
As #Daniel Roseman mentioned you should be using self rather than Function_Inventory, so I changed that. I also changed the return value of Return_Maxcount to provide a list as you requested.
class CLASS_INVENTORY:
maxcount_inventory = int(input("How many Inventories: "))
inventory_name = []
def __init__(self):
for count_inventory in range(self.maxcount_inventory):
add_inventory = str(input("Enter Inventory #%d: " % (count_inventory+1)))
self.inventory_name.append(add_inventory)
def Return_Inventory(self):
for item in self.inventory_name:
print(item)
def Return_Maxcount(self):
return self.inventory_name
maxcount_inventory = CLASS_INVENTORY()
inventory_list = maxcount_inventory.Return_Maxcount()
maxcount_inventory.Return_Inventory()
You can change the print statement at the bottom and set that equal to a variable to access it outside of the class itself.
In your code just change this:
maxcount_inventory = CLASS_INVENTORY().Return_Maxcount
to this:
maxcount_inventory = CLASS_INVENTORY().Return_Maxcount()
also change the variables in your class to have the self. prefix before them
like self.maxcount_inventory
the reason is you want to call your method , otherwise it will try getting a variable not the method.
you also want to change all your arguments in your functions inside of the class to self
I'm new to python.I'm getting "main instance has no call method" error in the below code.I'm trying to create product class objects in main class and call product class function using these objects. What is the correct way to do this to not get such error.
import sys
from sys import argv
class read():
def __init__(self):
return
def read_function(self):
self.file_one=open(argv[1],"r")
self.file_two=open(argv[2],"w")
return self.file_one,self.file_two
class product():
def calculate(self,calc_row):
self.calc_row=calc_row
if "India" in calc_row[3]:
print "In India"
self.tax_amt=int(calc_row[2])*5/100
self.final_amt=self.tax_amt+int(calc_row[2])
elif "US" in calc_row[3]:
print "In US"
self.tax_amt=int(calc_row[2])*10/100
self.final_amt=self.tax_amt+int(calc_row[2])
else:
print "In UK"
self.tax_amt=int(calc_row[2])*15/100
self.final_amt=self.tax_amt+int(calc_row[2])
return self.tax_amt,self.final_amt
def writerow(self,out_file,list,tax_am,final_am):
self.list=data
self.tax_am=tax_val
self.final_am=final_val
self.out_file=out_data
self.string=",".join(self.list)
self.string=self.string+","+str(self.tax_am)+","+str(self.final_am)+"\n"
print self.string
self.out_file.write(self.string)
class main():
def __init__(self):
return
def main_function(self):
read_obj=read()
self.in_data,self.out_data=read_obj.read_function()
self.prod_list = [product() for i in range(3)]
for self.index,self.line in enumerate(self.in_data):
if (self.index == 0):
self.header=self.line
self.header=self.header.replace("\n","")
self.header=self.header+",Sales_Tax,Final_Price \n"
self.out_data.write(self.header)
else:
self.line.replace("/n","")
self.data=self.line.split(",")
self.prod=self.prod_list[index-1]
self.tax_val,self.final_val=self.prod.calculate(self.data)
print "Tax %d Final %d"% (self.tax_val,self.final_val)
self.prod.writerow(self.out_data,self.data,self.tax_val,self.final_val)
product=main()
product.main_function()
write_obj=write()
print type(prod_list[0])
When you write
product = main()
you replace the class that is bound to product with an instance of main. Later, when you try to create an instance of product, you are actually attempting to call the instance of main as a function.
You need to use a different name, and the simplest way to do that is to follow the convention that user-defined class names start with uppercase letters, and all other names (excluding CONSTANTS) start with lowercase names.
import sys
from sys import argv
class Read():
...
class Product():
...
class Main():
...
# This is a bad name, by the way. If you have two classes named Product
# and Main, a variable named product seems far more likely to be an
# instance of Product, not Main.
product = Main()
product.main_function()
As they answered you on comments
class product():
conflicts with
product=main()
so product is not a class name anymore. Please make your classes' first letter uppercase or better take a look at PEP8
Imagine following structure (I've cut most imho relevant parts):
class mymodificatorclass:
def callback(self,object):
print object
class generator(BoxLayout):
#(...)
def add(self, *l):
for i,t in enumerate(self.texts):
self.mytext.append(TextInput(hint_text=t, on_text_validate=modify.callback(self)))
self.add_widget(self.mytext[i])
#(...)
modify = mymodificatorclass() #global scope variable
prints for example <main.generator object at 0x433eef0>. Which is fine.
But, how would one access this class instance variables?
meaning, desired output would be:
print XXXXX
$ <__main__.mytext object at 0x433eef0>
print XXXXX.text, XXXXX
$ "text inside" <__main__.mytext object at 0x433eef0>
I've checked:
print object.__class__.__dict__.items() #no mytext here
print object.mytext #no mytext here
print getattr(object,object.mytext) # object generator has no attribute mytext
I know i can assign for example additional variable storing each TextInput object, but i'd rather not, since i know that if I modified example like this:
class generator(BoxLayout):
def add(self, *l):
for i,t in enumerate(self.texts):
self.mytext.append(TextInput(hint_text=t, on_text_validate=self.callback))
self.add_widget(self.mytext[i])
def callback(self,object):
print object
i would get desired result (i had that like this, but decided i need to move closer to mvc )
self.mytext.append(TextInput(hint_text=t,
on_text_validate=modify.callback(self)))
You are calling the function instead of passing it. Use functools.partial.
self.mytext.append(TextInput(hint_text=t,
on_text_validate=partial(modify.callback, self)))
So I have this class:
class hero():
def __init__(self, name="Jimmy", prof="Warrior", weapon="Sword"):
"""Constructor for hero"""
self.name = name
self.prof = prof
self.weapon = weapon
self.herodict = {
"Name": self.name,
"Class": self.prof,
"Weapon": self.weapon
}
self.herotext = {
"Welcome": "Greetings, hero. What is thine name? ",
"AskClass": "A fine name, {Name}. What is your class? ",
"AskWeapon": "A {Class}, hmm? What shalt thy weapon be? ",
}
def setHeroDicts(self, textkey, herokey):
n = raw_input(self.herotext[textkey].format(**self.herodict))
if n == "":
n = self.herodict[herokey]
self.herodict[herokey] = n
#print self.herodict[herokey]
def heroMake(self):
h = hero()
h.setHeroDicts("Welcome", "Name")
h.setHeroDicts("AskClass", "Class")
h.setHeroDicts("AskWeapon", "Weapon")
And in another class I have this executing
def Someclass(self):
h = hero()
print h.herodict["Class"]
h.heroMake()
print h.getClass()
if "Mage" in h.herodict["Class"]:
print "OMG MAGE"
elif "Warrior" in h.herodict["Class"]:
print "Warrior!"
else:
print "NONE"
So if I input nothing each time, it will result in a blank user input, and give the default values. But if I put an input, then it will change the herodict values to what I customize. My problem is, if I try and access those updated values in Someclass it only gives me the default values instead of the new ones. How do I go about accessing the updated values?
The main issue with your class is that you are creating a new object within heromake instead of using the existing one. You can fix this by replacing h with self (so that each time you are calling setHeroDicts on the object):
def heromake(self):
self.setHeroDicts("Welcome", "Name")
self.setHeroDicts("AskClass", "Class")
self.setHeroDicts("AskWeapon", "Weapon")
The first argument to a method is always set to the instance itself, so if you want to interact with the instance or mutate it, you need to use it directly. When you do h = hero() in your original code, you create a whole new hero object, manipulate it and then it disappears when control passes back to your function.
A few other notes: you should name your classes with CamelCase, so it's easier to tell they are classes (e.g., you should really have class Hero) and in python 2, you need to make your classes descend from object (so class Hero(object)). Finally, you are duplicating nearly the entire point of having classes with your herodict, you should consider accessing the attributes of the object directly, instead of having the intermediary herodict (e.g., instead of doing h.herodict["Class"] you could do h.prof directly.
Am new to Python OOP. Please dont be harsh. Here is my code which calculates which is the fastest time of an athlete from a list and displays them. But When Running, I get this error:
z= add.mylist.min()
NameError: global name 'add' is not defined
My Code:
class Athlete:
def add(self):
list=[]
mylist=[]
for i in range(2):
self.name = raw_input("Enter name: ")
self.fastest_time = input("time: ")
list.append(self.name)
mylist.append(self.fastest_time)
print "Names: ",list
print "Fastest times: ",mylist
def display(self):
z= add.mylist.min()
w= add.mylist.index(z)
print "Minimum time: ",z
print "Name of athelte with fastest time: ",list[w]
x = Athlete()
x.add()
x.display()
You need to refer to methods on the instance with the self parameter. In addition, your add() method needs to return the mylist variable it generates, you cannot refer to method local variables as attributes on methods:
def display(self):
mylist = self.add()
z = min(mylist)
w = mylist.index(z)
def add(self):
list=[]
mylist=[]
for i in range(2):
self.name = raw_input("Enter name: ")
self.fastest_time = input("time: ")
list.append(self.name)
mylist.append(self.fastest_time)
print "Names: ",list
print "Fastest times: ",mylist
return mylist
That is what self is for, as a reference point to find instance attributes and other methods on the same object.
You may want to rename list to something that does not shadow the built-in type.
Martijn has already answered your question, so here are some remarks and code style tips:
New-style classes derive from object
You have both athlete names and their times, those belong together as key-value pairs in a dictionary instead of two separate lists
Don't use print statements inside class methods, a class method should return an object that you then can print
what if you have more then 2 athletes for which you want to enter the time? If you make the number of athletes an argument of your function, you can add a variable number of athlethes
give descriptive variable names (not mylist) and don't use names of builtin functions (like list) as variable name
variables that you want to use throughout your class can be initalized in an __init__method.
For printing, use the format function instead of using commas
use if __name__ == '__main__' so that your Python file can act as either reusable modules or as standalone program
Taking these into account, I would rewrite your code to something like this:
from collections import defaultdict
class Athlete(object): # see (1)
def __init__(self): # see (6)
self.athlete_times = defaultdict(str) # see (2)
def add_athletes_and_times(self, n): # see (4)
for i in range(n):
self.name = raw_input("Enter name: ")
self.fastest_time = input("time (in seconds): ")
self.athlete_times[self.fastest_time] = self.name
def get_fastest_time(self):
return min(self.athlete_times) # see (3)
if __name__ == '__main__': # see (8)
x = Athlete()
x.add_athletes_and_times(2)
for fast_time in x.athlete_times:
print "The fastest time of athlete {0} is {1} seconds.".format(
x.athlete_times[fast_time], fast_time) # see (7)
fastest_time = x.get_fastest_time()
print "The overall fastest time is: {0} seconds for athlete {1}.".format(
fastest_time, x.athlete_times[fastest_time])