Dale Woods
Dale Woods

Reputation: 849

"takes 1 positional argument but 2 were given" Error in Python OOP

I am new to python and come from a c++ background

I am trying to get my head around OOP. I am creating a class which uses the Zero MQ library to connect to other software.

I am trying to make private elements in my class, which to my understanding is done by adding two underscores to the front of the member and property names.

I am getting this error - stacktrace:

 File "d:/python/mt4inPython/Mt4Client.py", line 29, in <module>
 test = MT4Client(30, 40, 50)
 File "d:/python/mt4inPython/Mt4Client.py", line 10, in __init__
 self.__SetupPorts(self)
 TypeError: __SetupPorts() takes 1 positional argument but 2 were given

My class:

class MT4Client:    
import zmq as __zmq

def __init__ (self, inREQPortNum = 6850, inPULLPortNum = 2527, inSUBPortnum = 6999, inHostName = "127.0.0.1"):
    self.__REQPort = inREQPortNum
    self.__PULLPort = inPULLPortNum
    self.__SUBPort = inSUBPortnum
    self.__HOST = inHostName  

    self.__SetupPorts(self)
    self.__ConnectRequest(self)

def __BuildNetworkAddress(self, inHost, inPort):
    return "return tcp://{}:{}".format(inHost, inPort)

def __SetupPorts(self):        
    self.__ZMQContext = self.__zmq.Context()
    self.__replySocket = self.__ZMQContext.socket(self.__zmq.REQ)
    self.__pullSocket = self.__ZMQContext.socket(self.__zmq.PULL)
    print("Setup ports was called")

def __ConnectRequest(self):
    #__replySocket.connect( self.__BuildNetworkAddress(self, self.__HOST, self.__REQPort) )
    addr = self.__BuildNetworkAddress(self, self.__HOST, self.__REQPort)
    print( "Connecting to %s", addr )

With python OOP, I noticed you need to pass self as the first parameter for every method.

But can anyone tell me why I am getting these argument errors? What hidden python magic is going on in the background that I am not aware of?

Thanks so much.

Upvotes: 0

Views: 1169

Answers (1)

Blckknght
Blckknght

Reputation: 104722

All instance methods need to have a self parameter in their declaration (though the specific name, self, is just convention), but you normally don't need to pass it manually when you call the method on an instance. When you look up some_instance.method, it "binds" the method to the instance, so that when you call it, the instance gets passed as the first argument automatically.

In your code, you should just call self.__SetupPorts().

I'd further recommend that you get rid of most or all of the double-leading-underscore names you're currently using. That prefix invokes Python's name mangling system. Name mangling is only intended for a few uncommon situations like writing a proxy or mixin class, where you don't know what other attribute names might be used alongside your own.

If you just want to mark a variable or method as being "private", use a single leading underscore. This doesn't prevent other code from accessing the attribute (neither does name mangling, really), but it serves as documentation of your intent for the attributes to be private.

Upvotes: 1

Related Questions