Как объявить метод, который принимает экземпляр в качестве аргумента в Python? - PullRequest
2 голосов
/ 21 сентября 2010

Я знаю, что это, вероятно, глупый вопрос, но я плохо знаком с ООП в Python, и если я объявляю функцию def myFunction( b) и передаю ей экземпляр объекта, я получаю TypeError: ожидаемая строка или буфер. *

Если говорить более конкретно, у меня есть следующий код, который я использую для анализа сводной молекулярной формулы и создания объекта из нее.

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)

Спасибо, Томас

Ответы [ 3 ]

1 голос
/ 21 сентября 2010

Ричард Кук прав.Однако существует другая проблема: в extend вы говорите:

addAtoms = SummaryFormula( b)

Таким образом, экземпляр SummaryFormula передается в метод __init__ объекта SummaryFormula.Здесь (по модулю упомянутой выше опечатки) этот объект присваивается re.finditer:

for atom in re.finditer( "([A-Z][a-z]{0,2})(\d*)", summaryFormula)

Функция re.finditer ожидает строку;он не знает, что делать с экземпляром SummaryFormula.

Есть несколько способов исправить это.Самое простое - проверить, есть ли у вас экземпляр SummaryFormula, прежде чем пытаться его создать:

if isinstance(b, SummaryFormula):
    addAtoms = b
else if isinstance(b, str):
    addAtoms = SummaryFormula(b)
else:
    raise TypeError("Expected a SummaryFormula or equivalent string.")
1 голос
/ 21 сентября 2010

Короче говоря, вы можете передать любой объект функции, включая экземпляры созданных вами классов.

В общем, все в Python является объектом. Это концепция key в Python, поэтому, если вы новичок в языке, потратьте некоторое время на ознакомление, так как это поможет вашему коду написания, который будет более лаконичным и питоническим.

Ошибка, которую вы получаете не от передачи объекта экземпляра класса, а скорее от того, что она генерируется где-то (смотрите другие ответы, как они, кажется, на него), в другом месте вашего кода, с помощью другой функции или операции, которая ожидает строку, строковый объект для работы. Например, вы можете создать похожую ошибку, выполнив:

>>> a = 2
>>> open(a, 'r')

TypeError: coercing to Unicode: need string or buffer, int found

Здесь ошибка возникает потому, что функция открытия файла open ожидает строку, а не целое число.

1 голос
/ 21 сентября 2010

Во-первых, в программу должен быть включен модуль re.

Во-вторых, у вас есть опечатка в строке 4:

for atom in re.finditer( "([A-Z][a-z]{0,2})(\d*)", SummaryFormula):

должно читаться

for atom in re.finditer( "([A-Z][a-z]{0,2})(\d*)", summaryFormula):

то есть строчные буквы s в summaryFormula.

SummaryFormula относится к названию класса, а summaryFormula относится ко второму параметру (после self) __init__method.

В-третьих, строка addAtoms = SummaryFormula(b) передает экземпляр SummaryFormula в качестве аргумента b (назначается в части верхнего уровня скрипта test.extend(toExtend).

Фиксированная программадолжен выглядеть так:

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)

с заменой "SOME STRING" на предполагаемый строковый литерал или ссылку на строковую переменную. Я не знаю точное намерение программы, поэтому оставлю это кому-то другомуопределите, что эта программа должна передать конструктору SummaryFormula на данный момент.

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...