On 05Jan2016 20:58, Alex Kleider <aklei...@sonic.net> wrote:
#!/usr/bin/env python3
# OS: Ubuntu 10.4LTS

# My code:

class JournalLineItem(object):
   """
   """

   def __init__(self, account, debit_or_credit, amount):
       self.account = account
       self.debit_or_credit = debit_or_credit
       self.amount = float(amount)

   def show(self):
       return ("ACNT: {}  ${:0.2f} {}".
           format(self.account, self.amount, self.debit_or_credit))

   def get_line_item(text):
       return JournalLineItem(*text.split())

def test():
   print(
   JournalLineItem.get_line_item("2435 Dr 25.33").show())

if __name__ == "__main__":
   test()

   myquestion = """

What kind of a method/function is get_line_item?

As written, it is an instance menthod that _thinks_ it is a static method. Not that that was what you intended :-)

From what I've read (and not fully understood)
static methods and class methods must have
@staticmethod and @classmethod on the line above them.

As written, you could put @staticmethod above it - it is an ordinary function that resides in the class to associate its functionality with the class.

However, what you are probably better off with is @classmethod, for reasons I will explain below.

Instance methods expect their first parameter to be the instance (self) and class methods expect their first parameter to be the class. This is arranged implicitly when you call the method via an instance or class.

get_line_item works as I wanted but it's clearly not the
usual type of method and I don't know how to categorize it.

It is confused. There is nothing in the Python language that requires the instance to be called "self", that is just convention. So your method thinks that the instance is "text", and works on that. So you could do this:

 jli = JournalLineItem(account, debit_or_credit, amount)
 jli.get_line_item()

and the call would go ahead, but fail because a JournalLineItem has no .split method. And you can't do this:

 jli = JournalLineItem(account, debit_or_credit, amount)
 jli.get_line_item("2435 Dr 25.33")

because, since it is an instance method, Python implicitly passes in the instance (jli) as the first parameter, so the call is equivalent to:

 JournalLineItem.get_line_item(jil, "2435 Dr 25.33")

but the function only expected a single parameter. Badness ensues.

It's an instance creator- is there a better term?

Generally these are called factories. Normally you would either write this as a class method:

 @classmethod
 def get_line_item(cls, text):
   return cls(*text.split())

which will get JournalLineItem when you call it as in your example:

 item = JournalLineItem.get_line_item("2435 Dr 25.33")

but will get the right subclass if you subclass JournalLineItem:

 class SpecialJournalLineItem(JournalLineItem):
   ...

 special_item = SpecialJournalLineItem.get_line_item("2435 Dr 25.33")

Alternatively, if you never expect to subclass this, you could just declare it as a normal function outside the class entirely:

 def get_line_item(cls, text):
   return JournalLineItem(*text.split())

Often these functions or methods are called from_blah, so the outside-the-class function might be called "JournalLineItem_from_text", and the inside the class @classmethod one might be called "from_text". So you might write:

 jli = JournalLineItem.from_text("2435 Dr 25.33")

which reads well and allows you to subclass JournalLineItem later. Therefore I would recommend the @classmethod approach. And stylisticly, I would put that up the top, just under __init__.

Hoping this helps rather than confuses,
Cameron Simpson <c...@zip.com.au>
_______________________________________________
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor

Reply via email to