-2

I have following class and a function defined in it.

class utils:
    def pass_hash(unhashed):
        hashed = hashlib.sha256(unhashed)
        hashed = hashed.hexdigest()
        return hashed

When I call

print(utils.pass_hash('abc'.encode()))

it works fine but if i call

obj = utils()
print(obj.pass_hash('abc'.encode()))

it gives following error:

  print(obj.pass_hash('abc'.encode()))
TypeError: pass_hash() takes 1 positional argument but 2 were given

Whereas if I pass self argument in function then this bheaviour gets reversed i.e. it works fine with object but on accesing like utils.pass_hash() it gives error.

Can someone please exlain this behaviour?

Aran-Fey
  • 39,665
  • 11
  • 104
  • 149
Ayush Aggarwal
  • 177
  • 3
  • 12
  • 1
    Possible duplicate of [TypeError: method() takes 1 positional argument but 2 were given](https://stackoverflow.com/questions/23944657/typeerror-method-takes-1-positional-argument-but-2-were-given) – mkrieger1 May 15 '19 at 09:10
  • 2
    This should not be a method on a class at all. Python is not Java, it does not require everything to be defined in a class. – Daniel Roseman May 15 '19 at 09:13

3 Answers3

5

It is the usual behaviour of classes and their instances.

If you do obj = utils(), you create an instance of the class utils (which should better be named Utils). If you perform an instance method call such as obj.pass_hash(x), obj is automatically passed as a first argument to the method and x as second one. Thus, it is required that the method is defined as def pass_hash(self, x).

If you want to call a method on the class itself, you have to annotate it with @staticmethod or with @classmethod.

A @staticmethod changes the described behaviour in so far as the auto-passing of self is suppressed. A @classmethod has the method called with the class object instead.

glglgl
  • 89,107
  • 13
  • 149
  • 217
0

Calling obj.pass_hash('abc'.encode()) is the same as calling

utils.pass_hash(obj,'abc'.encode())

The first parameter is the instance the method was called on. (It probably does not need to be called self, but not doing so would be confusing for other readers).

kutschkem
  • 7,826
  • 3
  • 21
  • 56
0

So class methods need to know what class they belong to. If a method doesn't need self then it is most likely a function and should be outside of that class or in a different class.

The error comes up due to you calling it on a specific object rather than the class itself, so when you call it via utils it calls the general class method while calling it via

obj = utils()
print(obj.pass_hash('abc'.encode()))

calls that method within the obj object.

In this example, I would recommend refactoring to make the pass_hash method into a function, if you find that you make a lot more use of similar hash-editing functions then feel free to make a HashHandler class.