68

I have this code to implement a Particle Swarm Optimization algorithm:

class Particle:    
    def __init__(self,domain,ID):
        self.ID = ID
        self.gbest = None
        self.velocity = []
        self.current = []
        self.pbest = []
        for x in range(len(domain)):
            self.current.append(random.randint(domain[x][0],domain[x][1])) 
            self.velocity.append(random.randint(domain[x][0],domain[x][1])) 
            self.pbestx = self.current          
    
    def updateVelocity():
        for x in range(0,len(self.velocity)):
            self.velocity[x] = 2*random.random()*(self.pbestx[x]-self.current[x]) + 2 * random.random()*(self.gbest[x]-self.current[x])
        
    def updatePosition():    
        for x in range(0,len(self.current)):
            self.current[x] = self.current[x] + self.velocity[x]    
            
    def updatePbest():
        if costf(self.current) < costf(self.best):
            self.best = self.current        
    
    def psoOptimize(domain,costf,noOfParticles=20, noOfRuns=30):
        particles = []
        for i in range(noOfParticles):    
            particle = Particle(domain,i)    
            particles.append(particle)    
        
        for i in range(noOfRuns):
            Globalgbest = []
            cost = 9999999999999999999
        for i in particles:    
        if costf(i.pbest) < cost:
                cost = costf(i.pbest)
            Globalgbest = i.pbest
            for particle in particles:
                particle.updateVelocity()
                particle.updatePosition()
                particle.updatePbest(costf)
                particle.gbest = Globalgbest    
    
        return determineGbest(particles,costf)

When I run it, I get this error:

TypeError: updateVelocity() takes no arguments (1 given)

But it clearly says particle.updateVelocity(), with nothing between the (). Where is the "1 given" argument coming from? What is wrong with the code, and how do I fix it?

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
Linus
  • 1,113
  • 1
  • 8
  • 14
  • There's no blank lines in my source, that's just the way this site formats it. – Linus Dec 15 '10 at 22:26
  • 1
    Low quality question: many unrelated code with many syntax errors due to mixed spaces and tabs. Duplicate of better question http://stackoverflow.com/q/6614123/448474 – hynekcer Dec 13 '12 at 12:28
  • 3
    It's a very plausible question! The error procuced is very common for someone who is new to Python. And it is a very perplexing problem! You can easily see that the programmer calls 'particle.updateVelocity()' w/o any argument, which is iideed how it should be called. It is solvable, but not using standard documentation! – Apostolos Jan 21 '18 at 18:30
  • Python is not naturally compiled, but interpreted. CPython is an interpreter, not a compiler. –  Sep 13 '18 at 18:49
  • @J. C. Rocamonde: No, CPython is [a compiler and a bytecode interpreter](https://stackoverflow.com/a/6889798/10077). – Fred Larson Jan 03 '19 at 03:33
  • OK, you have a point, and though you are technically right, it is irrelevant to mine. Bytecode still needs to be interpreted. CPython does not produce executables, as you already know. In fact, many python functions depend on their C definition that is only referenced to in bytecode. For general talking Python standard implementation makes it an interpreted language, not compiled. –  Jan 03 '19 at 18:39
  • In 3.8, the error message is instead `TypeError: updateVelocity() takes 0 positional arguments but 1 was given`. I don't have other versions around to test, but I know that there was a major overhaul of error messages in 3.10. – Karl Knechtel Sep 08 '22 at 06:01

4 Answers4

133

Python implicitly passes the object to method calls, but you need to explicitly declare the parameter for it. This is customarily named self:

def updateVelocity(self):
Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
Fred Larson
  • 60,987
  • 18
  • 112
  • 174
  • 16
    I just started learning python. At least for now I think that is ugly. – shaffooo May 07 '16 at 21:09
  • @fred I was curious did you learn this by exploring along the way while working on an IronPython project or did you have a way of debugging this type of error? Either way I would love to learn =D – wiz_lee Aug 09 '16 at 10:19
  • 1
    @wiz-_-lee: Honestly, I don't remember where exactly I learned it. I think it was from a Python tutorial and then experience. I've never used IronPython or Jython, only CPython. – Fred Larson Aug 09 '16 at 13:59
  • If python internally handles passing object reference from caller then why it is not handled in called class behaviours. It is very confusing to get such error message and unable to predict cause. – Sagar balai Aug 08 '17 at 06:48
  • This is one of those nasty "gotchas" – Phil Oct 22 '17 at 17:19
  • 1
    @Sagarbalai @shaffooo it is not confusing. It is confusing if you don't have experience. That is what learning is for: understanding things you would not otherwise know. `self` is not a keyword, it's a convention. You can call the first argument whatever you want. Doing what you suggest would need making `self` a keyword like `this` in JavaScript, and restructuring Python's scope system. And that would be even more confusing for most cases. Python is dynamic, and that feature goes with its philosophy and structure. –  Sep 13 '18 at 18:53
  • What happens, for example, if you are passing class instances as an argument to the class method? There would be a conflict of scopes; and one would shadow the other. It's simply an unncessary complication. Bound methods are passed an instance, unbound are not. Remember: explicit is better than implicit (The Zen of Python). Besides, that would contradict Python's principle of that _everything is an object_ (and how objects are passed by assignment to variables) –  Sep 13 '18 at 18:56
8

Make sure, that all of your class methods (updateVelocity, updatePosition, ...) take at least one positional argument, which is canonically named self and refers to the current instance of the class.

When you call particle.updateVelocity(), the called method implicitly gets an argument: the instance, here particle as first parameter.

miku
  • 181,842
  • 47
  • 306
  • 310
6

Your updateVelocity() method is missing the explicit self parameter in its definition.

Should be something like this:

def updateVelocity(self):    
    for x in range(0,len(self.velocity)):
        self.velocity[x] = 2*random.random()*(self.pbestx[x]-self.current[x]) + 2 \
          * random.random()*(self.gbest[x]-self.current[x])

Your other methods (except for __init__) have the same problem.

bgporter
  • 35,114
  • 8
  • 59
  • 65
-2

I have been puzzled a lot with this problem, since I am relively new in Python. I cannot apply the solution to the code given by the questioned, since it's not self executable. So I bring a very simple code:

from turtle import *

ts = Screen(); tu = Turtle()

def move(x,y):
  print "move()"
  tu.goto(100,100)

ts.listen();
ts.onclick(move)

done()

As you can see, the solution consists in using two (dummy) arguments, even if they are not used either by the function itself or in calling it! It sounds crazy, but I believe there must be a reason for it (hidden from the novice!).

I have tried a lot of other ways ('self' included). It's the only one that works (for me, at least).

Apostolos
  • 3,115
  • 25
  • 28
  • 2
    This is not an answer to the question. `move` is not a method of a class, so `self` would not make any sense. `move` is being given as a callback function. When the screen is clicked, it will call that function with x and y values. You may not use them, but you must accept them. – Fred Larson Dec 28 '18 at 18:26
  • Right, this applies to a function of the main module, not a class. I gave a general solution to the so common and puzzling Python error in question. – Apostolos Dec 30 '18 at 11:24