Can a method be used as either a staticmethod or instance method?
Asked Answered
H

4

5

I'd like to be able to do this:

class A(object):
    @staticandinstancemethod
    def B(self=None, x, y):
        print self is None and "static" or "instance"

A.B(1,2)
A().B(1,2)

This seems like a problem that should have a simple solution, but I can't think of or find one.

Hardison answered 28/4, 2011 at 1:17 Comment(5)
Why would you want this? It seems very confusing.Nicholas
It's to get a form for creation or editing of the class. The static method would return a blank one while the instance method would return the same thing populated with the instance's data.Hardison
@Jake: That sounds like a bad idea. Usually we a complete set of default values in the constructor. An empty constructor builds the blank form. A constructor with real values would populate the form with data.Nicholas
Why would the model possibly be responsible for the view?Leghorn
Nope, that doesn't work anyway.Madrepore
E
9

It is possible, but please don't. I couldn't help but implement it though:

class staticandinstancemethod(object):
     def __init__(self, f):
          self.f = f

     def __get__(self, obj, klass=None):
          def newfunc(*args, **kw):
               return self.f(obj, *args, **kw)
          return newfunc

...and its use:

>>> class A(object):
...     @staticandinstancemethod
...     def B(self, x, y):
...         print self is None and "static" or "instance"

>>> A.B(1,2)
static
>>> A().B(1,2)
instance

Evil!

Earthy answered 28/4, 2011 at 2:17 Comment(3)
Bravo! <clap> <clap> <clap>. Now the sharks just need laser beams.Coagulate
Thanks. I thought of something similar myself, but thought better of actually using it, hence my question here.Hardison
I realise this is kinda old, but still: Why shouldn't I use it? My intention is to write a class with an info() method, which returns information that allows to filter multiple classes of the same parent type. It further supports different configurations when initialising, so once initialised the info() method would be able to return more detailed information. I thought about this for a while, and also considered using different methods, but that seems to make things more complicated (for the user) than necessary.Harday
D
0

Since you'd like the static method case to be used to create a new class anyway, you'd best just make it a normal method and call it at the end of the __init__ method.

Or, if you don't want that, create a separate factory function outside the class that will instantiate a new, empty object, and call the desired method on it.

There probably are ways of making exactly what you are asking for, but they will wander through the inner mechanisms of Python, be confusing, incompatible across python 2.x and 3.x - and I can't see a real need for it.

Disclamation answered 28/4, 2011 at 1:48 Comment(0)
V
0

From what you're saying, is this along the line of what you're looking for? I'm not sure there is a way to do exactly what you're saying that is "built in"

class Foo(object):
    def __init__(self, a=None, b=None):
        self.a
        self.b

    def Foo(self):
        if self.a is None and self.b is None:
            form = CreationForm()
        else: 
            form = EditingForm()
        return form
Vargo answered 28/4, 2011 at 2:46 Comment(0)
M
-3

The answer to your question is no, you can't do that.

What I would do, since Python also supports regular functions, is define a function outside that class, then call that function from a normal method. The caller can decide what which one is needed.

Madrepore answered 28/4, 2011 at 1:48 Comment(9)
Did you see #5813037?Monogram
"Don't do that, because..." is much stronger and less counter-productive than lying.Monogram
@Fred The syntax as shown by the OP will not work. That is not lying. But Python does expose all of its inner workings so you can really do whatever you want. But that doesn't mean you should.Madrepore
@Keith: How helpful of you to ignore "Can a method be used as either a staticmethod or instance method?" and focus on "self=None" to justify an answer which, if you meant the "self=None" issue originally, is purposefully misleading.Monogram
@Fred it is quite helpful to steer someone away from an error. It is not helpful to help someone shoot themselves in the foot. Nor is it helpful call someone a liar that is trying to help. But clearly you are on your high-horse and can't be dislodged.Madrepore
@Keith: You steer someone away from a probable error by getting more information on why they (think they) need it or by "Don't do that, because...", not "You can't do that." If you can't see that, then I don't see any where to go with this.Monogram
@Fred, perhaps, but you are not omniscient enough to know what was on a persons mind when they write some sentence. Labeling someone a liar is offensive and also not helpful in any way.Madrepore
@Keith: "You can't do that" is false. Being made aware that it's false and still claiming it as true (see the first two comments here) is lying. If you meant the "self=None" syntax by "can't do that", then I can't see other than you were being purposefully misleading, as that was an example of what the OP would like to do, rather than being the exact syntax they want to use.Monogram
@Fred Try that line of code and you will see that it won't work. Therefore you can't do that is a truthful statement. Python doesn't allow keyword arguments before non-keyword arguments, anyway. You can't do that. Neither is it, in my opinion, good design to make it work in some way, even though you could.Madrepore

© 2022 - 2024 — McMap. All rights reserved.