I've just started learning Python and I was trying out class concept and came across this error and cant find out what I've done wrong ! Can someone point out ?!
class animal:
def __init__(self,name,ani,age,location):
self.name= name
self.ani = ani
self.age = age
self.location = location
def info(self):
print("I'm a {0} called {1} and I'm {2} years old, living in {3}".format(ani,name,age,location))
Arun = animal(Martin,Dog,7,Amazon)
Arun.info()
And the error is :
Traceback (most recent call last): File
"C:\Users\DELL\Desktop\python\class_trail.py", line 12, in <module>
Arun = animal(Martin,Dog,7,Amazon) NameError: name 'Martin' is not defined
So a couple of things have gone wrong with your code:
You are passing in variable names, not strings.
When you call Arun = animal(Martin,Dog,7,Amazon), Python looks for a variable name called Martin, but doesn't find one and raises NameError.
What you probably intended was Arun = animal('Martin','Dog',7,'Amazon')
Your .info() method needs to refer to self.ani and self.age etc., because those data items are bound up inside the object.
Arun = animal(Martin,Dog,7,Amazon)
^ you want to pass here string values, but instead you're passing there variables which are not defined. To pass there strings you have to wrap them into quotes like this:
Arun = animal("Martin","Dog",7,"Amazon")
The error you are getting refers to the fact that no variable Martin is defined in the code, before you use it. What you probably meant to do is
Arun = animal("Martin", "Dog", 7, "Amazon")
Note the quotes around the strings you are passing as parameters, as opposed to how python interprets your code, where this would work:
name = "Martin"
animal = "Dog"
age = 7
location = "Amazon"
Arun = animal(name, animal, age, location)
Extra: something you may want to get used to while learning to code in Python are its good practices. Python classes are typically declared with a capital letter (or actually PascalCase), like so class Animal():, while variable names are typically declared lower case (snake_case), like so arun = Animal(...).
There is a small exception: constants are declared all capital, like so EULER_CONSTANT = 0.577.
Related
I am making an RPG text based game with classes and subclasses. I'm importing other python files, each of which have their own classes. Each python file is the name of their RPG main class, each of which have multiple classes for the respective RPG subclass. My question is, if I wanted to access a variable from one of these classes from the main file (E.G. if I wanted to access the bard's spellist I'd do Bard.Bard.Spellist, (First bard being the file import, second being the name of the class), could I use a variable like:
x = input("Enter class from which to access the spellist: )
print(x.x.spellist)
hope that makes sense!
This is what I tried:
x = Bard
for item in x.x.SpellBook:
print(item, ":", x.x.SpellBook[item])
I expected it to print a list of the names and spell level like this:
(spellname) : (spellevel)
It comes up with this error:
Traceback (most recent call last):
File "main.py", line 82, in <module>
for item in x.x.SpellBook:
AttributeError: module 'ClassFold.Bard' has no attribute 'x'
While you can do what you're asking (through a combination of globals() and getattr), it's a bad idea to do so. Your variable names should not be data in your program. Variable names are for you the programmer to use, not for your users.
Instead, use a dictionary or some other data structure to map from one kind of data (e.g. a string like 'bard') to another kind of data (e.g. the bard.Bard class). Use that mapping to process the user input into the data you actually need to use.
Here's a very simplified example:
class Bard:
spell_list = ['x', 'y', 'z']
class_name_mapping = {'bard': Bard, 'fighter': ...}
user_class_name = input('What class is your character? ')
user_class = class_name_mapping[user_class_name.lower()]
user_spell_list = user_class.spell_list
print(f'Your spells are: {", ".join(user_spell_list)}.')
An explanation on why there is a syntax error when starting with a full stop while naming a variable
As mentioned the grammar doesn't allow it https://docs.python.org/3/reference/lexical_analysis.html#identifiers .
And to give you a small example how it would mess things up imagine you had this code
class Fruit:
name = 'Fruitas'
#classmethod
def printName(cls):
print('The name is:', cls.name)
apple = Fruit()
apple.printName()
if you could use a . and named .apple when calling the fucntion how would python undertand it? You would need to call .apple.printName(). Python reads . as a connector...
While running a trading algorithm, I ran into the following issue that I tried to reproduce in the following way:
Suppose I have one algorithm named algo1.py and another named algo2.py.
Here's algo2.py...
class mathOperations():
def __init__(self):
self.value = 0
def sum(self, __a = 0, __b = 0):
return (__a + __b)
Here's algo1.py...
from algo2 import mathOperations
math = mathOperations()
print(math.sum(__a = 56, __b = 44))
When I run algo1.py, I get the following message:
Traceback (most recent call last):
File "algo1.py", line 5, in <module>
print(math.sum(__a = 56, __b = 67))
TypeError: sum() got an unexpected keyword argument '__a'
However, when I remove the '__' or two underscores from the front of the named arguments in both algorithms, this error goes away. Could someone please explain to me why?
See the documentation about name mangling:
Private name mangling: When an identifier that textually occurs in a class definition begins with two or more underscore characters and does not end in two or more underscores, it is considered a private name of that class. Private names are transformed to a longer form before code is generated for them. The transformation inserts the class name, with leading underscores removed and a single underscore inserted, in front of the name. For example, the identifier __spam occurring in a class named Ham will be transformed to _Ham__spam. This transformation is independent of the syntactical context in which the identifier is used. If the transformed name is extremely long (longer than 255 characters), implementation defined truncation may happen. If the class name consists only of underscores, no transformation is done.
That explains the why. The reason for this weird feature existing in the first place is described in the tutorial here (TL;DR: it's a hack to avoid name clashes with names defined by subclasses).
The solution is easy: don't use names with two leading underscores when defining the arguments for methods.
class UniversityAthletics():
def _init_(self, university_name, sport):
self.university_name = university_name
self.sport = sport
def describe_athletics(self):
print(self.university_name.title() + " " + self.sport.title())
def in_season(self):
print(self.sport.title() + " is in season.")
athletics = UniversityAthletics('salisbury university', 'soccer')
print("The school name is " + athletics.university_name.title() + ".")
print(str(athletics.sport.title()) + " is in season")
athletics.describe_athletics()
athletics.in_season()
Guys, I'm just learning how to code so if I say something that makes no sense my apologies.
But I'm trying to give the class UniversityAthletics the attributes
'salisbury university', 'soccer'
but when I try to execute the program I get this error
Traceback (most recent call last): File "E:/WorWic/IntroToProgramming/chapter9/University Athletics.py", line 13, in
athletics = UniversityAthletics('salisbury university', 'soccer') TypeError: object() takes no parameters
I've gone back to the book that my professor gave me and still cannot find a solution. There must be something simple and plain that I missed.
Your init method is named _init_ (one underscore on each side), when it should be __init__ (two underscores on each side).
Because the method is named wrong, python is not finding it, and instead directly calling the method in the superclass of your class, which is:
object.__init__
and passing it your two parameters, which it is not expecting.. hence the error message.
The __init__ function needs double underscores on either sides (you have only singles).
It's 2 lines around the init, so instead of _init_ type __init__.
I've created the code below, when I import the module and attempt to run it I received the following error:
>>> import aiyoo
>>> aiyoo.bixidist(1,3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "aiyoo.py", line 50, in bixidist
currentDist = dist(X,Y,c)
File "aiyoo.py", line 39, in dist
distance = math.sqrt(math.pow((X-getLat(i)),2)+math.pow((Y-getLong(i)),2))
File "aiyoo.py", line 28, in getLat
xmlLat = double(xmlLat)
NameError: global name 'double' is not defined
The double function was used in order to convert the unicode output from the XML into a double as input for the functions to follow. So I do not understand why, it is considered to be a name when the aiyoo module is imported.
Here is the module, which was named aiyoo.py:
import math
import urllib2
from xml.dom.minidom import parseString
file = urllib2.urlopen('http://profil.bixi.ca/data/bikeStations.xml')
data = file.read()
file.close()
dom = parseString(data)
#this is how you get the data
def getID(i):
xmlID = dom.getElementsByTagName('id')[i].toxml()
xmlID = xmlID.replace('<id>','').replace('</id>','')
xmlID = int(xmlID)
return xmlID
def getLat(i):
xmlLat = dom.getElementsByTagName('lat')[i].toxml()
xmlLat = xmlLat.replace('<lat>','').replace('</lat>','')
xmlLat = double(xmlLat)
return xmlLat
def getLong(i):
xmlLong = dom.getElementsByTagName('long')[i].toxml()
xmlLong = xmlLong.replace('<long>','').replace('</long>','')
xmlLong = double(xmlLong)
return xmlLong
#this is how we find the distance for a given station
def dist(X,Y,i):
distance = math.sqrt(math.pow((X-getLat(i)),2)+math.pow((Y-getLong(i)),2))
return distance
#this is how we find the closest station
def bixidist(X,Y):
#counter for the lowest
lowDist = 100000
lowIndex = 0
c = 0
end = len(dom.getElementsByTagName('name'))
for c in range(0,end):
currentDist = dist(X,Y,c)
if currentDist < lowDist:
lowIndex = c
lowDist = currentDist
return getID(lowIndex)
As answered by others, double is not a built-in type in python. You have to use, float instead. Floating point is implemented using double in C [ ref ].
And as to the main part of your question i.e. "why the double considered a global name?", when you use a variable-name say double, which is not found in local context, the next lookup is in global context. It is then, if it is not found even in global context, the exception is raised, saying NameError: global name 'double' is not defined.
Happy Coding.
There is no double type in Python. And if you look at the error it complains that it can't find anything named double. The floating-point type in Python is named float.
it should be xmlLat = float(xmlLat)
Python float is same as double of other languages. ( 64 bit )
http://codepad.org/AayFYhEd
Like the other 2 answers so far have said, Python doesn't have a double variable type, instead it has float.
Now for the question in your title and possibly another source of confusion for you. The reason the interpreter is saying "NameError: global name 'double' is not defined" is because of how Python searches for names of functions, variables, objects, etc. This pattern is described by Python's namespace and scope rules. Because you tried to call the nonexistent function Double from within a function without qualifying it (ie. SomeObject.Double(x)), Python first looks for an object of that name in the local namespace (namespace of the current function that is running), then the local namespace of the enclosing functions, then the global namespace, and finally the built-in namespace. The reason the interpreter gave you that message is because of the order of Python's search for the definition of Double(). global namespace was the last place it checked before looking for it in the built-ins (which are Python's coding, not yours, so I guess it wouldn't make sense for the interpreter to say "NameError: built-in name 'double' is not defined"). At least I think this is what's going on. I'm still not a very seasoned programmer, so I trust someone else will correct me if I got something wrong.