Reputation: 10882
I have a class db
defined like so:
class db:
def __init_(self, idx, host, port, db_name, user, password):
self.idx = idx
...
def Connect(self):
conn = db_engine.connect(host=self.host, ...)
@staticmethod
def Connect(idx):
if idx == 1:
d = db(1, "localhost", 80, ...)
conn = d.Connect()
return conn
So, as you can see, my class has two methods. Most importantly it has a static method Connect
which internally tries to call a non-static method Connect
. However, when I try to use my program, I get an error message:
d.Connect()
TypeError: Connect() missing 1 required positional argument ...
It seems like the static method tries to call itself, however I want to make it call another non-static method. So, what am I doing wrong?
Upvotes: 0
Views: 268
Reputation: 1125258
You redefined the Count
method. Python doesn't support overloading; you cannot define both a regular method and a static method. You only have the staticmethod
version because it was defined last, it replaced the non-static version altogether.
If you need a method that alters its behaviour based on wether or not it is bound (static vs. a regular method) you have two options; either test the type of the self
argument (it'll be an integer or an instance of the db
class), or you'll have to build a custom descriptor object that can alter how your method is called based on the context; on an instance or on the class.
Testing the type of self
looks like this:
class db:
def __init_(self, idx, host, port, db_name, user, password):
self.idx = idx
# ...
def Connect(self_or_idx):
if isinstance(self_or_idx, db):
self = self_or_idx
conn = db_engine.connect(host=self.host, ...)
# ...
else:
idx = self_or_idx
if idx == 1:
d = db(1, "localhost", 80, ...)
conn = d.Connect()
return conn
If using a custom descriptor, you could build one that supports two different functions like the property
object does:
class static_or_instance_method(object):
def __init__(self, instancemethod=None, staticmethod=None):
self.method = instancemethod
self.static = staticmethod
def staticmethod(self, staticmethod):
return type(self)(self.method, staticmethod)
def instancemethod(self, instancemethod):
return type(self)(instancemethod, self.static)
def __get__(self, instance, cls=None):
if instance is None:
return self.static
return self.method.__get__(instance, cls)
then use it like this:
class db:
def __init_(self, idx, host, port, db_name, user, password):
self.idx = idx
# ...
@static_or_instance_method
def Connect(self):
conn = db_engine.connect(host=self.host, ...)
# ...
@Connect.staticmethod
def Connect(idx):
if idx == 1:
d = db(1, "localhost", 80, ...)
conn = d.Connect()
return conn
Quick demo of the descriptor:
>>> class Foo:
... @static_or_instance_method
... def bar(self):
... return 'Bound method of {}'.format(self)
... @bar.staticmethod
... def bar(arg):
... return 'Static method, receiving argument {}'.format(arg)
...
>>> Foo().bar()
'Bound method of <__main__.Foo object at 0x10b6cf588>'
>>> Foo.bar('spam')
'Static method, receiving argument spam'
Upvotes: 3