Classes with defined functions that won't call correctly - python

The question is noted in the title. It might be a question of details, as always, but still, any help would be appreciated.
# create a supervilan class
class supervilan:
size = ""
color = ""
powers = ""
weapons = ""
special_ability = ""
def customs(self):
print(self.name + " has a supercool and technologic advanced suit.")
def organic_gear(self, gear):
print(self.name + " use they´re" + gear + " with mastery and precision!")
I reduced the amount of methods to facilitate:
# objects
Dracula = supervilan()
Dracula.size = "2.12cm"
Dracula.color = "white"
Dracula.organic_gear("Astucy")
Chimical = supervilan()
Chimical.size = "2.30cm"
Chimical.color = "Caucasian"
Dracula.organic_gear()
Chimical.customs()

Positional arguments are values you put in the brackets of a function (eg: function(arg1,arg2)). The organic_gear function requires two positional arguments as specified when you defined the function (organic_gear(self, gear)). However in your code you call organic_gear without specifying what "self" or "gear" are, and that's why that error message appears. There may be other errors or style improvements to be corrected but I'll leave that to people better versed in classes in python.

First, you should go through the basics of OOPs concept to work with class and instances.
Since you wants to create different instances of your supervilan class with different attribute of (size, color, etc..), you must make them instance variable not class and set default values when you are initializing the instance of your class.
class supervilan:
def __init__(self, name='', size='', color='', powers='', weapons='', special_ability=''):
self.name = name
self.size = size
self.color = color
self.powers = powers
self.weapons = weapons
def customs(self):
print(self.name + " has a supercool and technologic advanced suit.")
def organic_gear(self, gear):
print(self.name + " use they´re" + gear + " with mastery and precision!")
Now you can create different instances of your class with different attribute values
Dracula = supervilan("Dracula", "2.12cm", "white")
Chimical = supervilan("Chimical", "2.30cm", "Caucasian)

Related

Python - What is correct way to copy a class object A which contains an array of class objects B

I want to copy an array of class objects and update the original array without the copied array changing also. See this code which illustrates the problem. I do not want B to change when I change A:
Copy array of class objects test
import copy
class B:
val=0
p=40
class A:
g=[]
def __init__(self):
self.g.append(B())
self.g.append(B())
def main():
a=A()
print("a.g[0] is " + str(a.g[0].val) + " , " + str(a.g[0].p))
print("a.g[1] is " + str(a.g[1].val) + " , " + str(a.g[1].p))
print("Copying a to b")
b=copy.deepcopy(a)
print ("Now updating a[0]")
a.g[0].val=25
print("a.g[0] now is " + str(a.g[0].val) + " , " + str(a.g[0].p))
print("a.g[1] now is " + str(a.g[1].val) + " , " + str(a.g[1].p))
print("Now printing which which was copied from original a")
print("b.g[0] is " + str(b.g[0].val) + " , " + str(b.g[0].p))
print("b.g[1] is " + str(b.g[1].val) + " , " + str(b.g[1].p))
if __name__ == "__main__":
main()
The problem is that you define val ,p, and g as class variables by declaring them directly within the class.
When you declare a class variable, that variable is related directly to the class itself and affects all instances of the class. An instance variable gets created with all objects of that class, but the value can vary from object to object. Imagine a class called wallet that has an attribute called money. Each wallet starts with 1000 for money, but they gain and lose money independently of each other. If I add 100 to one wallet, all the others are changed. A class variable behaves differently. Lets say I gave wallet a class variable called currency and set it to "USD". If I change this variable to "CAD", now ALL wallet objects will have their currency attribute set to "CAD", including the ones who are created already.
The solution is to make them instance variables and assigning the values underneath __init__ as self.<insert> rather than just <insert>. You can see an example of the change below. When I ran your main() function with the changes I made to the classes below, the changes made to A were not reflected in B.
A good rule of thumb is to always default to declaring your variables inside of __init__ because it will force you to think about how a class variable is behaving when you use it.
class B:
def __init__(self):
self.val=0
self.p=40
class A:
def __init__(self):
self.g=[]
self.g.append(B())
self.g.append(B())

Error on codeacademy labs writing python script

this is my first attempt at coding a game with python. I am at trying to run it through codeacademy labs but it says this:
File "<stdin>", line 7
__init__(self, name, size_v, size_h):
^ SyntaxError: invalid syntax Unknown error.
don't be afraid of hurting my feelings I am a very novice coder and I know I'm probably making quite a few mistakes.
I supposed I'm also looking for an explanation or alternative on how to code and experiment in a different setting (i think it's called an IDE)
from datetime import datetime
log = open("log.txt", "a")
class Ocean(object):
__init__(self, name, size_v, size_h):
self.name = name
self.size_v = size_v
self.size_h = size_h
class Ship(object):
__init__(self, size):
self.health = size
self.size = size
class BattleShip(Ship)
__init__(self):
self.health = 4
self.size = 4
class AirCarrier(Ship)
__init__(self):
self.health = 6
self.size = 6
class MedicShip(Ship)
__init__(self, size):
self.health = 2
self.size = 2
class ArmouredShip(Ship)
__init__(self, size):
self.health = 3
self.size = 2
def create_user_profile(username):
user_profile = open(username + "prof", "r+")
def create_default_ocean(name):
ocean = Ocean(name, 20, 20)
return ocean.populate(2,1,1,1)
def mainload():
gametime = datetime.now()
gamestate = "mainmenu"
username = str(raw_input("What is your name? "))
create_user_profile(username)
gametype = str(raw_input("What do you want to play? (QUICKPLAY) (CUSTOM)"))
log.write("[] " + gametime + " [] " + gamestate + " [] " + username + " [] " +gametype")
quick = "quick quickplay qp q"
custom = "custom cust c"
mainload()
if gametype.lower() in quick:
ocean = create_default_ocean(newocean)
elif gametype.lower() in custom:
#get height/width of ocean
#get amount of ships/size
There's 4 kind of errors in your script:
You forget the def identifier before each function:
class Ocean(object):
def __init__(self, name, size_v, size_h):
# ^^^
self.name = name
self.size_v = size_v
self.size_h = size_h
See documentation examples to get the syntax of classes :)
You forget some semicolons after class definition
class MedicShip(Ship):
# ^ this one
You also have a syntax error in the last function (mainload), there's a quote at the end. The correct line is:
log.write("[] " + gametime + " [] " + gamestate + " [] " + username + " [] " +gametype)
Finally, if you want to execute your code, you'll need to put something (other than comments) in the elif block at the end of your file. Otherwise, the interpreter will raise a syntax error (EOF error). Put a pass statement if you don't want to put any code for the moment:
elif gametype.lower() in custom:
pass # <- do nothing but create a correct block for the elif
#get height/width of ocean
#get amount of ships/size
I recommend you to read some beginner Python tutorial to learn the syntax ;)
You should define your function __init__() by writing def __init__(self, size)
also in some places you have forgotten to put ':' after defining class.
If you are a beginner in python u can get tutorial here(official python documentation)
To practice some basic programming stuff go to www.codingbat.com

Python Accessing Dict That Has Defualt Values That Have Been Updated

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.

Python Class inheritance Constructor fail: What am I doing wrong?

I have a small Python OOP program in which 2 class, Flan and Outil inherit from a superclass Part.
My problem is when I call Flan everything works perfectly, however when I call Outil the program fails silently.
The Outil instance is created, but it lacks all the attributes it doesn't share with Part.
The Outil instance isn't added to Outil.list_instance_outils, nor to Part.list_instances.
class Outil(Part):
list_instance_outils = []
def __init___(self, name, part_type, nodes, elems):
Part.__init__(self, name, part_type, nodes, elems)
self.vect_norm = vectnorm(self.nodes[self.elems[0,1:]-1, 1:])
self.elset = Elset(self)
self.nset = Nset(self, refpoint=True, generate=False)
self.SPOS = Ab_surface(self, self.elset)
self.SNEG = Ab_surface(self, self.elset, type_surf='SNEG')
Outil.list_instance_outils.append(self)
Part.list_instances.append(self)
class Flan(Part):
list_instances_flans = []
def __init__(self, name, part_type, nodes, elems):
Part.__init__(self, name, part_type, nodes, elems)
self.vect_norm = vectnorm(self.nodes[self.elems[0,1:4]-1, 1:])
self.elset = Elset(self)
self.nset = Nset(self)
self.SPOS = Ab_surface(self, self.elset)
self.SNEG = Ab_surface(self, self.elset, type_surf='SNEG')
Flan.list_instances_flans.append(self)
Part.list_instances.append(self)
Both this Classes inherit from Part :
class Part():
list_instances = []
def __init__(self, name, part_type, nodes, elems):
self.name = name
self.name_instance = self.name + '-1'
self.part_type = part_type
self.elems = elems
self.nodes = nodes
offset = np.min(self.elems[:, 1:])-1
self.nodes[:, 0] -= offset
self.elems[:, 1:] -= offset
I cannot stress enough that I have no error message whatsoever.
What am I doing wrong here ?
You wrote __init__ with three trailing underscores instead of two in Outil.
Because of this, it doesn't get called -- Part.__init__ gets called instead. That's why the class is created but it lacks the attributes beyond what are in Part.
To solve this sort of problem, the best thing to do is to run the code through the debugger.
Get your classes into the python interpreter (import, paste, whatever you like), then call pdb: import pdb; pdb.run('Outil()'). You can now step through the code to see what is happening.

problems writing address book program in python

I am writing a program to add to and update an address book. Here is my code:
EDITED
import sys
import os
list = []
class bookEntry(dict):
total = 0
def __init__(self):
bookEntry.total += 1
self.d = {}
def __del__(self):
bookEntry.total -= 1
list.remove(self)
class Person(bookEntry):
def __init__(self, n):
self.n = n
print '%s has been created' % (self.n)
def __del__(self):
print '%s has been deleted' % (self.n)
def addnewperson(self, n, e = '', ph = '', note = ''):
self.d['name'] = n
self.d['email'] = e
self.d['phone'] = ph
self.d['note'] = note
list.append()
def updateperson(self):
key = raw_input('What else would you like to add to this person?')
val = raw_input('Please add a value for %s' % (key))
self.d[key] = val
def startup():
aor = raw_input('Hello! Would you like to add an entry or retrieve one?')
if aor == 'add':
info = raw_input('Would you like to add a person or a company?')
if info == 'person':
n = raw_input('Please enter this persons name:')
e = raw_input('Please enter this persons email address:')
ph = raw_input('Please enter this persons phone number:')
note = raw_input('Please add any notes if applicable:')
X = Person(n)
X.addnewperson(n, e, ph, note)
startup()
When I run this code I get the following error:
in addnewperson
self.d['name'] = n
AttributeError: 'Person' object has no attribute 'd'
I have two questions:
UPDATED QUESTIONS
1. why isnt the d object being inherited from bookentry()?
I know this question/code is lengthy but I do not know where to go from here. Any help would be greatly appreciated.
The addnewperson shoud have 'self' as first argument; actually, the name doesn't matter ('self' is just a convention), but the first argument represent the object itself. In your case, it's interpreting n as the "self" and the other 3 as regular arguments.
____del____ must not take arguments besides 'self'.
Edit: BTW I spotted a few other problems in your example, that maybe you're not aware of:
1) d in bookentry is a class member, not an instance member. It's shared by all bookentry's instances. To create an instance member, use:
class bookentry(dict):
def __init__(self,n):
self.d = {}
# rest of your constructor
2) you're trying to access d directly (as you would do in Java, C++ etc), but Python doesn't support that. You must have a 'self' parameter in your methods, and access instance variables through it:
class person(bookentry):
def foo(self,bar):
self.d[bar] = ...
person().foo(bar)
Update: for the last problem, the solution is to call the super constructor (which must be done explicitly in Python):
class Person(bookEntry):
def __init__(self, n):
super(Person, self).__init__()
self.n = n
print '%s has been created' % (self.n)
A brief explanation: for people with background in OO languages without multiple inheritance, it feels natural to expect the super type constructor to be called implicitly, automatically choosing the most suitable one if no one is mentioned explicitly. However, things get messy when a class can inherit from two or more at the same time, for this reason Python requires the programmer to make the choices himself: which superclass constructor to call first? Or at all?
The behavior of constructors (and destructors) can vary wildly from language to language. If you have further questions about the life cycle of Python objects, a good place to start would be here, here and here.
why isnt the d object being inherited from bookentry()?
That's because __init__ of the bookEntry is not called in the __init__ of the Person:
super(Person, self).__init__()
BTW, why inherit from dict if its functionality is not used? It's better to remove it and inherit from object instead (also class names are usually CamelCased):
class BookEntry(object):

Categories

Resources