Converting functions into a methods of a class in python - python

I'm trying to get the hang of python 2.6, which is my introduction to a programming language. I'm following Learn Python the Hard Way and I must have missed something. I have a set of functions that I want to combine into a class. These functions are contained here. I tried to combine these into a class called "Parsers". This code is contained here.
The functions themselves work outside of the class. I'm trying to call the functions out of the class like this:
import the module:
>>> from ex48 import parser2
Assign the class:
>>> parser_class = parser2.Parsers()
Call a function:
>>> parser_class.parse_subject(word_list, ('noun', 'player'))
I get the following:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "ex48/parser2.py", line 60, in parse_subject
verb = parse_verb(word_list)
NameError: global name 'parse_verb' is not defined
Not sure why it's telling me that. Can someone point me in the right direction?

You are confused as to what your code is doing.
This does not assign, a class, it creates an instance, and assigns that instance to a variable:
parser_class = parser2.Parsers()
This calls a method on that instance:
parser_class.parse_subject(word_list, ('noun', 'player'))
The following tells you that there is no global function (or indeed variable of any type) parse_verb:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "ex48/parser2.py", line 60, in parse_subject
verb = parse_verb(word_list)
NameError: global name 'parse_verb' is not defined
I expect that you want to change that to verb = self.parse_verb(word_list), which will call the parse_verb method of the same object (self).

There are two problems here, one mechanical, one conceptual. I'll deal with the latter first.
The whole point of a class is that its instances represent some kind of object in your model of the world. For example, a "sentence" is an object, so it makes sense to have a class called Sentence, but a "parsers" is not an object, so Parsers is probably going to be a confused class. Looking at things less abstractly, a class usually has some kind of state, encapsulated in data members that its methods work on.
What you really have here is a parser function that returns a Sentence object (or raises a ParserError). This function could be a method of Sentence, or it could be a free function; it could also be a method of a Parser class if there were any reason for such an object to exist in your model, but there doesn't seem to be one.
If you're just looking to encapsulate all those helper functions so they don't litter the global namespace (a good idea in itself), you don't need to abuse a class to do that. Just make them local functions inside parse_sentence, or put them in a module called parsers.
Now, on to the mechanical problem: If you have a method in a class, you normally only call it through dot syntax: someObject.methodName(params). When a method calls another method of the same object, you use the special self parameter (which you've correctly listed as the first param of each method) to do that. So:
verb = self.parse_verb(word_list)
obj = self.parse_object(word_list)
… and so on for all the other method calls in your sample.
Not every language requires an explicit self like this. For example, in C++ or related languages (Java, C#, etc.), a method can call another method without specifying a target, and it's implicitly assumed that the target is this (the C++ equivalent of self).

It looks like you are working from a python interactive session.
If you've made any changes to parser2.py after importing parser2, then you have to
reload(parser2)
to make those changes known to the interactive interpreter.

Related

super class doesn't work with subclass, a init fun is defined but doesn't act accordantly [duplicate]

If your question was closed as a duplicate of this, it is because you had a code sample including something along the lines of either:
class Example:
def __int__(self, parameter):
self.attribute = parameter
or:
class Example:
def _init_(self, parameter):
self.attribute = parameter
When you subsequently attempt to create an instance of the class, an error occurs:
>>> Example("an argument")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Example() takes no arguments
Alternately, instances of the class seem to be missing attributes:
>>> class Example:
... def __int__(self): # or _init_
... self.attribute = 'value'
>>> Example().attribute
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Example' object has no attribute 'attribute'
You might also wonder: what do these exception messages mean, and how do they relate to the problem? Why didn't a problem occur earlier, for example, with the class definition itself? How else might the problem manifest? How can I guard against this problem in the future?
This is an artificial canonical duplicate created specifically to head off two of the most common typographical errors in code written by new Python programmers. While questions caused by a typo are normally closed for that reason, there are some useful things to explain in this case, and having a duplicate target allows for closing questions faster. I have tried to design the question to be easy to search for.
This is because the code has a simple typographical error: the method should instead be named __init__ - note the spelling, and note that there are two underscores on each side.
What do the exception messages mean, and how do they relate to the problem?
As one might guess, a TypeError is an Error that has to do with the Type of something. In this case, the meaning is a bit strained: Python also uses this error type for function calls where the arguments (the things you put in between () in order to call a function, class constructor or other "callable") cannot be properly assigned to the parameters (the things you put between () when writing a function using the def syntax).
In the examples where a TypeError occurs, the class constructor for Example does not take arguments. Why? Because it is using the base object constructor, which does not take arguments. That is just following the normal rules of inheritance: there is no __init__ defined locally, so the one from the superclass - in this case, object - is used.
Similarly, an AttributeError is an Error that has to do with the Attributes of something. This is quite straightforward: the instance of Example doesn't have any .attribute attribute, because the constructor (which, again, comes from object due to the typo) did not set one.
Why didn't a problem occur earlier, for example, with the class definition itself?
Because the method with a wrongly typed name is still syntactically valid. Only syntax errors (reported as SyntaxError; yes, it's an exception, and yes, there are valid uses for it in real programs) can be caught before the code runs. Python does not assign any special meaning to methods named _init_ (with one underscore on each side), so it does not care what the parameters are. While __int__ is used for converting instances of the class to integer, and shouldn't have any parameters besides self, it is still syntactically valid.
Your IDE might be able to warn you about an __int__ method that takes suspicious parameters (i.e., anything besides self). However, a) that doesn't completely solve the problem (see below), and b) the IDE might have helped you get it wrong in the first place (by making a bad autocomplete suggestion).
The _init_ typo seems to be much less common nowadays. My guess is that people used to do this after reading example code out of books with poor typesetting.
How else might the problem manifest?
In the case where an instance is successfully created (but not properly initialized), any kind of problem could potentially happen later (depending on why proper initialization was needed). For example:
BOMB_IS_SET = True
class DefusalExpert():
def __int__(self):
global BOMB_IS_SET
BOMB_IS_SET = False
def congratulate(self):
global BOMB_IS_SET
if BOMB_IS_SET:
raise RuntimeError("everything blew up, gg")
else:
print("hooray!")
If you intend for the class to be convertible to integer and also wrote __int__ deliberately, the last one will take precedence:
class LoneliestNumber:
def __int__(self):
return 1
def __int__(self): # was supposed to be __init__
self.two = "can be as bad"
>>> int(LoneliestNumber())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __int__ returned non-int (type NoneType)
(Note that __int__ will not be used implicitly to convert instances of the class to an index for a list or tuple. That's done by __index__.)
How might I guard against the problem in the future?
There is no magic bullet. I find it helps a little to have the convention of always putting __init__ (and/or __new__) as the first method in a class, if the class needs one. However, there is no substitute for proofreading, or for training.

TypeError: Car() takes no arguments. when I run the python program, it keeps giving me this kind of result and I could not find the reason [duplicate]

If your question was closed as a duplicate of this, it is because you had a code sample including something along the lines of either:
class Example:
def __int__(self, parameter):
self.attribute = parameter
or:
class Example:
def _init_(self, parameter):
self.attribute = parameter
When you subsequently attempt to create an instance of the class, an error occurs:
>>> Example("an argument")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Example() takes no arguments
Alternately, instances of the class seem to be missing attributes:
>>> class Example:
... def __int__(self): # or _init_
... self.attribute = 'value'
>>> Example().attribute
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Example' object has no attribute 'attribute'
You might also wonder: what do these exception messages mean, and how do they relate to the problem? Why didn't a problem occur earlier, for example, with the class definition itself? How else might the problem manifest? How can I guard against this problem in the future?
This is an artificial canonical duplicate created specifically to head off two of the most common typographical errors in code written by new Python programmers. While questions caused by a typo are normally closed for that reason, there are some useful things to explain in this case, and having a duplicate target allows for closing questions faster. I have tried to design the question to be easy to search for.
This is because the code has a simple typographical error: the method should instead be named __init__ - note the spelling, and note that there are two underscores on each side.
What do the exception messages mean, and how do they relate to the problem?
As one might guess, a TypeError is an Error that has to do with the Type of something. In this case, the meaning is a bit strained: Python also uses this error type for function calls where the arguments (the things you put in between () in order to call a function, class constructor or other "callable") cannot be properly assigned to the parameters (the things you put between () when writing a function using the def syntax).
In the examples where a TypeError occurs, the class constructor for Example does not take arguments. Why? Because it is using the base object constructor, which does not take arguments. That is just following the normal rules of inheritance: there is no __init__ defined locally, so the one from the superclass - in this case, object - is used.
Similarly, an AttributeError is an Error that has to do with the Attributes of something. This is quite straightforward: the instance of Example doesn't have any .attribute attribute, because the constructor (which, again, comes from object due to the typo) did not set one.
Why didn't a problem occur earlier, for example, with the class definition itself?
Because the method with a wrongly typed name is still syntactically valid. Only syntax errors (reported as SyntaxError; yes, it's an exception, and yes, there are valid uses for it in real programs) can be caught before the code runs. Python does not assign any special meaning to methods named _init_ (with one underscore on each side), so it does not care what the parameters are. While __int__ is used for converting instances of the class to integer, and shouldn't have any parameters besides self, it is still syntactically valid.
Your IDE might be able to warn you about an __int__ method that takes suspicious parameters (i.e., anything besides self). However, a) that doesn't completely solve the problem (see below), and b) the IDE might have helped you get it wrong in the first place (by making a bad autocomplete suggestion).
The _init_ typo seems to be much less common nowadays. My guess is that people used to do this after reading example code out of books with poor typesetting.
How else might the problem manifest?
In the case where an instance is successfully created (but not properly initialized), any kind of problem could potentially happen later (depending on why proper initialization was needed). For example:
BOMB_IS_SET = True
class DefusalExpert():
def __int__(self):
global BOMB_IS_SET
BOMB_IS_SET = False
def congratulate(self):
global BOMB_IS_SET
if BOMB_IS_SET:
raise RuntimeError("everything blew up, gg")
else:
print("hooray!")
If you intend for the class to be convertible to integer and also wrote __int__ deliberately, the last one will take precedence:
class LoneliestNumber:
def __int__(self):
return 1
def __int__(self): # was supposed to be __init__
self.two = "can be as bad"
>>> int(LoneliestNumber())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __int__ returned non-int (type NoneType)
(Note that __int__ will not be used implicitly to convert instances of the class to an index for a list or tuple. That's done by __index__.)
How might I guard against the problem in the future?
There is no magic bullet. I find it helps a little to have the convention of always putting __init__ (and/or __new__) as the first method in a class, if the class needs one. However, there is no substitute for proofreading, or for training.

Trouble calling methods in Class

I'm having trouble calling methods in a class written by someone else (https://github.com/travishathaway/python-ach/blob/master/ach/parser.py). I have done some research but don't fully understand how to call methods with self and other arguments within a class.
The class is written out in the link above, but how do I call any of the methods written out? I have a file in the correct format asked but I cannot get the methods to work. For example, I have tried (and other variations):
a = Parser(file) # where "file" is the filepath
a.__parse_file_header()
This gives me the error: 'Parser' object has no attribute '__parse_file_header'
The methods with 2 underscores in the front are "private" to the class object itself, which is not supposed to be called externally. (Saying that you can still call private methods if you really want to, via mangling)
By the look of the Parser, you should only call as_json or as_dict of the Parser object you initiated with the string variable
eg.
parser = Parser(string_variable)
dict = parser.as_dict()

Can't view variables within a static method

EDIT:
Ok so here is the background. I am trying to understand code written by a coworker. He has specifically written the code in the format of this example:
>>> class A:
#staticmethod
def ok(abc):
thebigone=abc
(This is a simplification but the style is the same. Namely, a variable was declared in a #staticmethod within a class)
So since I am new to his code, I wanted to see what type of data thebigone was.I called the function in the shell and tried to use the to return the contents of this variable. I ran the function ok and then tried to use the shell to print the contents of the variable thebigone but the shell returned a definition error.
Here are the commands I tried in the shell:
>>> class A:
#staticmethod
def ok(abc):
thebigone=abc
>>> A.ok('d')
>>> thebigone
Traceback (most recent call last):
File "<pyshell#12>", line 1, in <module>
thebigone
NameError: name 'thebigone' is not defined
>>> A.thebigone
Traceback (most recent call last):
File "<pyshell#13>", line 1, in <module>
A.thebigone
AttributeError: type object 'A' has no attribute 'thebigone'
After running the function, is it possible for the shell to return the contents of the variable, thebigone without altering the code? If not why is that?
Thanks
You can't create global variables spontaneously inside a method any more than you can create them spontaneously inside a function. Otherwise, you wouldn't be able to have local variables in a static method without polluting the global namespace.
In addition to Pynchia's solution, you can declare a global variable outside the class, and reference it explicitly with global:
THEBIGONE = None
class a:
#staticmethod
def ok(abc):
global THEBIGONE
THEBIGONE = abc
Or you might want to use a classmethod to make it a member of the class:
class a:
#classmethod
def ok(cls, abc):
cls.THEBIGONE = abc
Class methods are generally more useful than static methods, so consider whether that might be a better solution to your real problem.
as it is assigned, THEBIGONE is a variable (name) in the local namespace of the method, not of the class.
Try with
a.THEBIGONE = ...
Generally speaking, in Python where the assignment takes places defines the namespace where the name ends up.
So the assignment THEBIGONE = ... makes it go in the current namespace, i.e. the method's.
Unless, you explicitly specify where the name should go, e.g.
an object (usually called self in instance methods) with self.THEBIGONE = ...
a class, with a.THEBIGONE = ... in your case. Note that, as suggested in trentcl's answer, you could make the method a classmethod and avoid using the class' name explicitly.
etc.
BTW: class names should start with capital letters, using the CapWords convention, leave lowercase to variables.
Please see the guidelines described in Python's PEP-8

Class instantiation and 'self' in python

I know a ton has been written on this subject. I cannot, however, absorb much of it. Perhaps because I'm a complete novice teaching myself without the benefit of any training in computer science. Regardless, maybe if some of you big brains chime in on this specific example, you'll help other beginners like me.
So, I've written the following function which works just fine when I call it (as a module?) as it's own file called 'funky.py':
I type the following into my terminal:
python classy.py
and it runs fine.
def load_deck():
suite = ('Spades', 'Hearts')
rank = ('2', '3')
full_deck = {}
i = 0
for s in suite:
for r in rank:
full_deck[i] = "%s of %s" % (r, s)
i += 1
return full_deck
print load_deck()
When I put the same function in a class, however, I get an error.
Here's my code for 'classy.py':
class GAME():
def load_deck():
suite = ('Spades', 'Hearts')
rank = ('2', '3')
full_deck = {}
i = 0
for s in suite:
for r in rank:
full_deck[i] = "%s of %s" % (r, s)
i += 1
return full_deck
MyGame = GAME()
print MyGame.load_deck()
I get the following error:
Traceback (most recent call last):
File "classy.py", line 15, in <module>
print MyGame.load_deck()
TypeError: load_deck() takes no arguments (1 given)
So, I changed the definition line to the following and it works fine:
def load_deck(self):
What is it about putting a function in a class that demands the use of 'self'. I understand that 'self' is just a convention. So, why is any argument needed at all? Do functions behave differently when they are called from within a class?
Also, and this is almost more important, why does my class work without the benefit of using init ? What would using init do for my class?
Basically, if someone has the time to explain this to me like i'm a 6 year-old, it would help. Thanks in advance for any help.
Defining a function in a class definition invokes some magic that turns it into a method descriptor. When you access foo.method it will automatically create a bound method and pass the object instance as the first parameter. You can avoid this by using the #staticmethod decorator.
__init__ is simply a method called when your class is created to do optional setup. __new__ is what actually creates the object.
Here are some examples
>>> class Foo(object):
def bar(*args, **kwargs):
print args, kwargs
>>> foo = Foo()
>>> foo.bar
<bound method Foo.bar of <__main__.Foo object at 0x01C9FEB0>>
>>> Foo.bar
<unbound method Foo.bar>
>>> foo.bar()
(<__main__.Foo object at 0x01C9FEB0>,) {}
>>> Foo.bar()
Traceback (most recent call last):
File "<pyshell#29>", line 1, in <module>
Foo.bar()
TypeError: unbound method bar() must be called with Foo instance as first argument (got nothing instead)
>>> Foo.bar(foo)
(<__main__.Foo object at 0x01C9FEB0>,) {}
So, why is any argument needed at all?
To access attributes on the current instance of the class.
Say you have a class with two methods, load_deck and shuffle. At the end of load_deck you want to shuffle the deck (by calling the shuffle method)
In Python you'd do something like this:
class Game(object):
def shuffle(self, deck):
return random.shuffle(deck)
def load_deck(self):
# ...
return self.shuffle(full_deck)
Compare this to the roughly-equivalent C++ code:
class Game {
shuffle(deck) {
return random.shuffle(deck);
}
load_deck() {
// ...
return shuffle(full_deck)
}
}
On shuffle(full_deck) line, first it looks for a local variable called shuffle - this doesn't exist, to next it checks one level higher, and finds an instance-method called shuffle (if this doesn't exist, it would check for a global variable with the right name)
This is okay, but it's not clear if shuffle refers to some local variable, or the instance method. To address this ambiguity, instance-methods or instance-attributes can also be accessed via this:
...
load_deck() {
// ...
return this->shuffle(full_deck)
}
this is almost identical to Python's self, except it's not passed as an argument.
Why is it useful to have self as an argument useful? The FAQ lists several good reasons - these can be summarised by a line in "The Zen of Python":
Explicit is better than implicit.
This is backed up by a post in The History of Python blog,
I decided to give up on the idea of implicit references to instance variables. Languages like C++ let you write this->foo to explicitly reference the instance variable foo (in case there’s a separate local variable foo). Thus, I decided to make such explicit references the only way to reference instance variables. In addition, I decided that rather than making the current object ("this") a special keyword, I would simply make "this" (or its equivalent) the first named argument to a method. Instance variables would just always be referenced as attributes of that argument.
With explicit references, there is no need to have a special syntax for method definitions nor do you have to worry about complicated semantics concerning variable lookup. Instead, one simply defines a function whose first argument corresponds to the instance, which by convention is named "self."
If you don't intent to use self you should probably declare the method to be a staticmethod.
class Game:
#staticmethod
def load_deck():
....
This undoes the automatic default packing that ordinarily happens to turn a function in a class scope into a method taking the instance as an argument.
Passing arguments you don't use is disconcerting to others trying to read your code.
Most classes have members. Yours doesn't, so all of its methods should be static. As your project develops, you will probably find data that should be accessible to all of the functions in it, and you will put those in self, and pass it around to all of them.
In this context, where the application itself is your primary object, __init__ is just the function that would initialize all of those shared values.
This is the first step toward an object-oriented style, wherein smaller pieces of data get used as objects themselves. But this is a normal stage in moving from straight scripting to OO programming.

Categories