[Tutor] method, type?

Steven D'Aprano steve at pearwood.info
Wed Jan 6 09:46:08 EST 2016


On Wed, Jan 06, 2016 at 09:59:49AM +0000, Alan Gauld wrote:
> On 06/01/16 04:58, Alex Kleider wrote:
> 
> > 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 get_line_item(text):
> >          return JournalLineItem(*text.split())
> 
> > What kind of a method/function is get_line_item?
> 
> As it stands its not.

Actually, it is a function, because `def` ALWAYS creates a function.


> As its intended to be, its a named constructor.
> But Python doesn't support named constructors so instead it
> could be a class method - that is a method of the class
> rather than of a particular instance.

I don't understand what you mean by "Python doesn't support named 
constructors". It seems to me that this is the *only* sort of 
constructor that Python supports.

As I understand it, "named constructor" comes from the C++ world, where 
functions are matched not just by name, but by parameters as well.

https://isocpp.org/wiki/faq/ctors#named-ctor-idiom


Constructors are named the same as the class by default. So, using 
Python syntax for simplicity, this is how you would define two 
constructors for a class called Spam, one that takes a single argument, 
and the other which takes two arguments:


class Spam:
    def Spam(x):
       # create a new Spam instance from one argument, x

    def Spam(x, y):
       # create a new Spam instance from two arguments, x and y


When you go to create an instance, you have a choice of saying:

x = Spam("arg")  # calls the one argument constructor
y = Spam(23, 99)  # calls the two argument constructor

and the C++ compiler will automatically choose the right constructor 
method.

But what if you need two constructors with the same number and type of 
arguments? For instance, you might have a Coordinate object, which takes 
two integers representing the position relative to the entire screen, or 
two integers representing the position relative to the current window. 
The C++ compiler cannot distinguish those two cases, and would give an 
error.

The solution is to use constructors with different names, which C++ 
calls "named constructors".

But note that Python DOES NOT support the standard name-of-class kind of 
constructor that C++ uses. In Python, we would write __new__ or 
__init__, not Spam, but that's just a cosmetic difference. The big 
difference is that we cannot write two methods with the same name and 
have Python keep them both. The second method would overwrite the first. 
So the only way to have two different constructors is to give them 
different names.

Hence all constructors in Python are "named constructors".


> But it should probably be a factory function. That is,
> defined at the module level and not part of the class
> at all. Not everything in OOP needs to be in a class.

It would be reasonable to make this a factory function declared in the 
global module level. But I think making it a classmethod is better. That 
keeps it encapsulated with the class, and ensures that if you subclass 
the class, you automatically get a valid constructor as well.



-- 
Steve


More information about the Tutor mailing list