Himmators
Himmators

Reputation: 15006

Python asks for 3 arguments when I pass 2 and 2 arguments when I pass 3

I have a class and constructor that looks like this:

def init(log, edge):
    if edge:
        return Helper(log, edge)
    return BookableProduct(log)
class BookableProduct():
    # Add helper to property bag
    def __init__(self, log, Kernel):
        self.log = log
        self.Kernel = Kernel

I just added the Kernel-argument and it casues an error.

If I try to invoke it like this:

import BookableProduct
log = PyLogger.get(edge.Controller.Kernel)
BookableProduct.init(log, edge)

I get the error:

2016-01-04 15:12:33,422 [38] ERROR Panagora.WebCore.Scripting.DefaultRuntimeExtensionsManager - Unable to run script C:\dev\..\Extensions\Global.py
Microsoft.Scripting.ArgumentTypeException: __init__() takes exactly 3 arguments (2 given)

But if I try to run it like this:

import BookableProduct
log = PyLogger.get(edge.Controller.Kernel)
BookableProduct.init(log, edge, edge.Controller.Kernel)

I get the following error:

2016-01-04 15:12:20,117 [36] ERROR Panagora.WebCore.Scripting.DefaultRuntimeExtensionsManager - Unable to run script C:\dev\git-sites\..\Extensions\Global.py
Microsoft.Scripting.ArgumentTypeException: init() takes exactly 2 arguments (3 given)

Upvotes: 1

Views: 366

Answers (3)

Galax
Galax

Reputation: 1431

__init__() is the constructor. You should be constructing your object with something like p = BookableProduct(log, edge), then self would be implicitly passed as the first parameter to __init__(self, log, Kernel).

Update: You edited the question to add init() function. In both of your examples the error messages are clear and accurate. In the first you construct the object passing only one parameter, when the __init__() constructor actually takes 3, with one being the implicitly passed self, so you should be passing two explicit parameters. In the second example you call the module scope function init() with the wrong number of parameters.

Upvotes: 1

Larry Lustig
Larry Lustig

Reputation: 50970

It's not entirely clear what you're trying to do, but I'm guessing that you want a product factory that returns an instance of BookableProduct under some circumstances and an instance of Helper under other circumstances.

You're confusing the issue somewhat by calling your factory function (which is not a method of any class) init when that word (in the form __init__) has a special and reserved meaning in Python.

Instead, write your factory like this:

def product_factory(log, edge):
    if edge:
        return Helper(log, edge)
    return BookableProduct(log, edge)

Note that I've changed the name to be clearer about what's going on and added the second, previously missing argument when instantiating a BookableProduct (these arguments, along with self will get passed to the initializer __init__ in BookableProduct).

Upvotes: 2

PatNowak
PatNowak

Reputation: 5812

self is not a parameter you should pass as a regular argument for the method. Python manages that for you and it's always is the object, which you want to call the method.

In different languages this param doesn't exist, but in Python everything should be explicit, so it's just emphasizes that there you will use particular method on particular method.

For instance:

class Foo:
def bar(self, number):
    self.number = number
    print(self.number)

You can invoke bar with:

Foo().bar(3)

as well as :

Foo.bar(Foo(), 3)

And both this examples with just print 3.

Upvotes: 0

Related Questions