Re: staticmethod makes my brain hurt
On Nov 17, 1:24 pm, Ethan Furman wrote: > If you do need to sometimes call it from a method then still leave off > the '@staticmethod', and give 'self' a default of 'None': > > def _get_next_id(self=None): > [blah, blah, blah] > return id > > user_id = IntField(required=True, default=_get_next_id) And if the OP needs it to be a staticmethod as well, he can just wrap the nested function: gen_next_id = staticmethod(_gen_next_id) I think I like this approach best. I'm annoyed that I forgot functions declared in a class scope were callable within the definition :) -- http://mail.python.org/mailman/listinfo/python-list
Re: staticmethod makes my brain hurt
On Thu, Nov 17, 2011 at 10:13 PM, Dotan Cohen wrote: > I'm at work far from Idle. Taken out of context, I'm sure your boss is pleased. :) ChrisA -- http://mail.python.org/mailman/listinfo/python-list
Re: staticmethod makes my brain hurt
On Thu, Nov 17, 2011 at 09:37, Ian Kelly wrote: > On Wed, Nov 16, 2011 at 11:44 PM, Dotan Cohen wrote: >> Try this (untested): >> >> class C: >> @staticmethod >> def foo(): >> pass >> >> print "inside", C.foo, callable(C.foo) > > If you had tested this, you would have found that you get a NameError, > since C is not yet bound inside the class block where you define it. > I hadn't tested, I'm at work far from Idle. Just shooting from the hip. For that matter, though, this does work in Java (I'm pretty sure but again, untested right now). -- Dotan Cohen http://gibberish.co.il http://what-is-what.com -- http://mail.python.org/mailman/listinfo/python-list
Re: staticmethod makes my brain hurt
Am 17.11.2011 03:30 schrieb Roy Smith: When I run this (python 2.6.1): class C: @staticmethod def foo(): pass print "inside", foo, callable(foo) print "outside", C.foo, callable(C.foo) I get: inside False outside True Right. The reason is that on an attribute access, you get a __get__ call of the "real" attribute. That is, if your class has a "regular" method, it is stored there as a formal function. But if you access it (C.f), you get C.__dict__["f"].__get__(None, C) (not sure about the arguments, but you should get the idea). A functions __get__ returns a unbound or bound method, depending on its own arguments. With a static method, you don't want this to happen. So you wrap your "regular" function into a staticmethod object, which has a __get__() method itself just returning the wrapped function object. Look at this: >>> class C(object): pass ... >>> f=lambda *a:a >>> C.f=f >>> s=staticmethod(f) >>> C.s=s >>> # Now we test the access ... >>> f at 0x00B43E30> >>> s >>> C.f > >>> C().f of <__main__.C object at 0x00B48810>> >>> C.s at 0x00B43E30> >>> C().s at 0x00B43E30> >>> f.__get__(None, C) > >>> f.__get__(C(), C) of <__main__.C object at 0x00B48AD0>> >>> s.__get__(None, C) at 0x00B43E30> >>> s.__get__(C(), C) at 0x00B43E30> That's how things work. If you want to get back the "real" function from a staticmethod, you either call its __get__ with an arbitrary argument, or you do it the clean way and do a def deref(s): class C(object): s=s return s.s and so do a class User(Document): @staticmethod def _get_next_id(): [blah, blah, blah] return id user_id = IntField(required=True, default=deref(_get_next_id)) HTH, Thomas -- http://mail.python.org/mailman/listinfo/python-list
Re: staticmethod makes my brain hurt
On Wed, Nov 16, 2011 at 11:44 PM, Dotan Cohen wrote: > Try this (untested): > > class C: > @staticmethod > def foo(): > pass > > print "inside", C.foo, callable(C.foo) If you had tested this, you would have found that you get a NameError, since C is not yet bound inside the class block where you define it. -- http://mail.python.org/mailman/listinfo/python-list
Re: staticmethod makes my brain hurt
On Thu, Nov 17, 2011 at 04:30, Roy Smith wrote: > When I run this (python 2.6.1): > > class C: > @staticmethod > def foo(): > pass > > print "inside", foo, callable(foo) > > print "outside", C.foo, callable(C.foo) > > I get: > > inside False > outside True > > I don't understand. Why is foo not callable inside of the class > definition? Where this comes up is that I'm trying to use a callable > default in mongoengine: > > class User(Document): > @staticmethod > def _get_next_id(): > [blah, blah, blah] > return id > > user_id = IntField(required=True, default=_get_next_id) > > The way mongoengine works is if callable(default) is true, it calls > default() to get the real value to use. At the point where the > IntField() call is made, _get_next_id is not callable, and eventually I > end up with: > > ValidationError: could not be > converted to int Try this (untested): class C: @staticmethod def foo(): pass print "inside", C.foo, callable(C.foo) -- Dotan Cohen http://gibberish.co.il http://what-is-what.com -- http://mail.python.org/mailman/listinfo/python-list
Re: staticmethod makes my brain hurt
> However, the fix is not as simple as merely making staticmethod objects > callable. This was discussed at the 2011 language summit: > > http://www.boredomandlaziness.org/2011/03/python-language-summit-rough-notes.html > > See also this thread: > > http://mail.python.org/pipermail/python-dev/2011-March/109090.html The notes didn't actually mention what was discussed, but re the second thread, the issue was not changing staticmethod to be callable. Making staticmethod callable is fine, but __get__ still has to return the original function, not self. The context of the second thread was that staticmethod was imagined as one way to eliminate the difference between C and Python functions, when added to a class. But this doesn't quite work, unless staticmethod.__get__ returned self (which broke for related reasons). If it returns the original function (as it does now) then the issue is unresolved: C functions still behave differently from Python functions, so you can't quite just hide them behind a staticmethod and let everything remain the same. It doesn't eliminate the difference in behavior in certain circumstances, e.g.: class MyClass: foo = staticmethod(foo) class MyOtherClass: foo = MyClass.foo MyOtherClass().foo() # what happens if foo is builtin vs pure-Python? In the context of this thread, though, just making it callable without modifying __get__ is fine. Or at least, I don't see the issue. Devin On Wed, Nov 16, 2011 at 11:43 PM, Steven D'Aprano wrote: > On Wed, 16 Nov 2011 21:30:57 -0500, Roy Smith wrote: > >> When I run this (python 2.6.1): >> >> class C: >> @staticmethod >> def foo(): >> pass >> print "inside", foo, callable(foo) >> >> print "outside", C.foo, callable(C.foo) >> >> I get: >> >> inside False >> outside True >> >> I don't understand. Why is foo not callable inside of the class >> definition? > > > This has come up before. > > http://bytes.com/topic/python/answers/34396-static-method-object-not-callable > > http://bytes.com/topic/python/answers/462734-make-staticmethod-objects-callable > > > However, the fix is not as simple as merely making staticmethod objects > callable. This was discussed at the 2011 language summit: > > http://www.boredomandlaziness.org/2011/03/python-language-summit-rough-notes.html > > See also this thread: > > http://mail.python.org/pipermail/python-dev/2011-March/109090.html > > > > -- > Steven > -- > http://mail.python.org/mailman/listinfo/python-list > -- http://mail.python.org/mailman/listinfo/python-list
Re: staticmethod makes my brain hurt
In article <4ec490ec$0$30003$c3e8da3$54964...@news.astraweb.com>, Steven D'Aprano wrote: > This has come up before. > > http://bytes.com/topic/python/answers/34396-static-method-object-not-callable > > http://bytes.com/topic/python/answers/462734-make-staticmethod-objects-callabl > e > > > However, the fix is not as simple as merely making staticmethod objects > callable. This was discussed at the 2011 language summit: > > http://www.boredomandlaziness.org/2011/03/python-language-summit-rough-notes.h > tml > > See also this thread: > > http://mail.python.org/pipermail/python-dev/2011-March/109090.html Thanks for the links. It always makes me feel good when I get tripped up by something complex and subtle. It almost makes up for all the times when I feel like a dolt because I got tripped up by something obvious and elementary... -- http://mail.python.org/mailman/listinfo/python-list
Re: staticmethod makes my brain hurt
On Wed, 16 Nov 2011 21:30:57 -0500, Roy Smith wrote: > When I run this (python 2.6.1): > > class C: > @staticmethod > def foo(): > pass > print "inside", foo, callable(foo) > > print "outside", C.foo, callable(C.foo) > > I get: > > inside False > outside True > > I don't understand. Why is foo not callable inside of the class > definition? This has come up before. http://bytes.com/topic/python/answers/34396-static-method-object-not-callable http://bytes.com/topic/python/answers/462734-make-staticmethod-objects-callable However, the fix is not as simple as merely making staticmethod objects callable. This was discussed at the 2011 language summit: http://www.boredomandlaziness.org/2011/03/python-language-summit-rough-notes.html See also this thread: http://mail.python.org/pipermail/python-dev/2011-March/109090.html -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: staticmethod makes my brain hurt
Roy Smith wrote: class User(Document): @staticmethod def _get_next_id(): [blah, blah, blah] return id user_id = IntField(required=True, default=_get_next_id) If you don't call '_get_next_id()' from any class methods (in other words, if you don't need to ever say 'self._gen_next_id()') then you can remove the '@staticmethod': def _get_next_id(): [blah, blah, blah] return id user_id = IntField(required=True, default=_get_next_id) If you do need to sometimes call it from a method then still leave off the '@staticmethod', and give 'self' a default of 'None': def _get_next_id(self=None): [blah, blah, blah] return id user_id = IntField(required=True, default=_get_next_id) ~Ethan~ -- http://mail.python.org/mailman/listinfo/python-list
Re: staticmethod makes my brain hurt
In article , alex23 wrote: > What you're effectively trying to do is use a class before it has been > constructed to help construct itself. > > Just define it as a helper function before the class declaration. Yes, this is the workaround I ended up with. -- http://mail.python.org/mailman/listinfo/python-list
Re: staticmethod makes my brain hurt
On Nov 17, 12:30 pm, Roy Smith wrote: > class C: > @staticmethod > def foo(): > pass > > print "inside", foo, callable(foo) > > print "outside", C.foo, callable(C.foo) > > I don't understand. Why is foo not callable inside of the class > definition? Consider this: >>> def foo(): pass ... >>> foo = staticmethod(foo) >>> callable(foo) False A staticmethod by itself does not appear to be callable. Your internal 'foo' is referring to the staticmethod wrapper. Your external 'C.foo' refers to the result returned by the class mechanism's __getattr__, which I'm guessing is munged into a callable at that point. Where this comes up is that I'm trying to use a callable > default in mongoengine: > > class User(Document): > @staticmethod > def _get_next_id(): > [blah, blah, blah] > return id > > user_id = IntField(required=True, default=_get_next_id) What you're effectively trying to do is use a class before it has been constructed to help construct itself. Just define it as a helper function before the class declaration. -- http://mail.python.org/mailman/listinfo/python-list