Reputation: 8317
I know it is probably a stupid question, but I am new to OOP in Python and if I declare a function def myFunction( b)
and pass an instance of an object to it, I get TypeError: expected string or buffer.
To be more specific, I have a following code that I use to parse a summary molecular formula and make an object out of it.
class SummaryFormula:
def __init__( self, summaryFormula):
self.atoms = {}
for atom in re.finditer( "([A-Z][a-z]{0,2})(\d*)", summaryFormula):
symbol = atom.group(1)
count = atom.group(2)
def extend( self, b):
# these are the two dictionaries of both molecules
originalFormula = self.atoms.copy()
self.atoms.clear()
addAtoms = SummaryFormula( b)
# and here both dictionaries are merged
for atom in addAtoms.atoms.keys():
if atom in originalFormula.keys():
self.atoms[ atom] = originalFormula[ atom]
self.atoms[ atom] += addAtoms.atoms[ atom]
else:
pass
for atom in originalFormula.keys():
if atom not in self.atoms.keys():
self.atoms[ atom] = originalFormula[ atom]
#this is what works now
test = SummaryFormula( "H2CFe2")
test.extend("H5C5") #result is a molecule H7C6Fe2
#this is what I want instead
test = SummaryFormula( "H2CFe2")
toExtend = SummaryFormula( "H5C5")
test.extend( toExtend)
Thank you, Tomas
Upvotes: 2
Views: 261
Reputation: 3129
In short you can pass any object to a function, including instances of classes you created.
More generally, everything in Python is an object. This is a key concept in Python so if you're new to the language spend some time getting familiar as it will help your write code which is more concise and pythonic.
The error you get isn't from passing a class instance object, but rather is generated somewhere (see other answers as they seem to be onto it) else in your code by another function or operation which is expecting a string, or string-like object to operate on. For example you can generate a similar error by doing:
>>> a = 2
>>> open(a, 'r')
TypeError: coercing to Unicode: need string or buffer, int found
Here the error occurs because the file opening function open
is expecting a string rather than an integer.
Upvotes: 1
Reputation: 33089
Firstly, the program needs to include the re
module.
Secondly, you have a typo at line 4:
for atom in re.finditer( "([A-Z][a-z]{0,2})(\d*)", SummaryFormula):
should read
for atom in re.finditer( "([A-Z][a-z]{0,2})(\d*)", summaryFormula):
i.e. lower-case s
in summaryFormula
.
SummaryFormula
refers to the name of the class while summaryFormula
refers to the second parameter (after self
) of the __init__
method.
Third, the line addAtoms = SummaryFormula(b)
is passing an instance of SummaryFormula
as argument b
(assigned in top-level part of script test.extend(toExtend)
.
The fixed program should look like:
import re
class SummaryFormula:
def __init__(self, summaryFormula):
self.atoms = {}
for atom in re.finditer("([A-Z][a-z]{0,2})(\d*)", summaryFormula):
symbol = atom.group(1)
count = atom.group(2)
def extend( self, b):
# these are the two dictionaries of both molecules
originalFormula = self.atoms.copy()
self.atoms.clear()
# PASS AN APPROPRIATE VALUE HERE!
addAtoms = SummaryFormula("SOME STRING")
# and here both dictionaries are merged
for atom in addAtoms.atoms.keys():
if atom in originalFormula.keys():
self.atoms[ atom] = originalFormula[ atom]
self.atoms[ atom] += addAtoms.atoms[ atom]
else:
pass
for atom in originalFormula.keys():
if atom not in self.atoms.keys():
self.atoms[ atom] = originalFormula[ atom]
#this is what works now
test = SummaryFormula("H2CFe2")
test.extend("H5C5") #result is a molecule H7C6Fe2
#this is what I want instead
test = SummaryFormula("H2CFe2")
toExtend = SummaryFormula("H5C5")
test.extend(toExtend)
with "SOME STRING"
replaced by the intended string literal or string variable reference. I don't know the exact intention of the program so I'll leave it up to somebody else to determine what this program should be passing to the constructor of SummaryFormula
at this point.
Hope that helps!
Upvotes: 1
Reputation: 3685
Richard Cook is correct. There is another problem, however: In extend
, you say:
addAtoms = SummaryFormula( b)
Thus, a SummaryFormula instance is passed into the __init__
method of SummaryFormula. Here (modulo the typo mentioned before), this object is given to re.finditer
:
for atom in re.finditer( "([A-Z][a-z]{0,2})(\d*)", summaryFormula)
The function re.finditer
expects a string; it doesn't know what to do with a SummaryFormula
instance.
There are a few ways to fix this. The immediately simplest is to check whether you already have a SummaryFormula instance before trying to create one:
if isinstance(b, SummaryFormula):
addAtoms = b
else if isinstance(b, str):
addAtoms = SummaryFormula(b)
else:
raise TypeError("Expected a SummaryFormula or equivalent string.")
Upvotes: 1