Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #15799 > unrolled thread
| Started by | Roy Smith <roy@panix.com> |
|---|---|
| First post | 2011-11-16 21:30 -0500 |
| Last post | 2011-11-17 22:38 +1100 |
| Articles | 13 — 9 participants |
Back to article view | Back to comp.lang.python
staticmethod makes my brain hurt Roy Smith <roy@panix.com> - 2011-11-16 21:30 -0500
Re: staticmethod makes my brain hurt alex23 <wuwei23@gmail.com> - 2011-11-16 18:44 -0800
Re: staticmethod makes my brain hurt Roy Smith <roy@panix.com> - 2011-11-16 21:52 -0500
Re: staticmethod makes my brain hurt Ethan Furman <ethan@stoneleaf.us> - 2011-11-16 19:24 -0800
Re: staticmethod makes my brain hurt alex23 <wuwei23@gmail.com> - 2011-11-17 18:31 -0800
Re: staticmethod makes my brain hurt Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-11-17 04:43 +0000
Re: staticmethod makes my brain hurt Roy Smith <roy@panix.com> - 2011-11-17 00:26 -0500
Re: staticmethod makes my brain hurt Devin Jeanpierre <jeanpierreda@gmail.com> - 2011-11-17 01:20 -0500
Re: staticmethod makes my brain hurt Dotan Cohen <dotancohen@gmail.com> - 2011-11-17 08:44 +0200
Re: staticmethod makes my brain hurt Ian Kelly <ian.g.kelly@gmail.com> - 2011-11-17 00:37 -0700
Re: staticmethod makes my brain hurt Thomas Rachel <nutznetz-0c1b6768-bfa9-48d5-a470-7603bd3aa915@spamschutz.glglgl.de> - 2011-11-17 10:17 +0100
Re: staticmethod makes my brain hurt Dotan Cohen <dotancohen@gmail.com> - 2011-11-17 13:13 +0200
Re: staticmethod makes my brain hurt Chris Angelico <rosuav@gmail.com> - 2011-11-17 22:38 +1100
| From | Roy Smith <roy@panix.com> |
|---|---|
| Date | 2011-11-16 21:30 -0500 |
| Subject | staticmethod makes my brain hurt |
| Message-ID | <roy-DD1C5B.21305716112011@news.panix.com> |
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 <staticmethod object at 0x421df0> False
outside <function foo at 0x41e6f0> 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: <staticmethod object at 0x2a3c1a0> could not be
converted to int
[toc] | [next] | [standalone]
| From | alex23 <wuwei23@gmail.com> |
|---|---|
| Date | 2011-11-16 18:44 -0800 |
| Message-ID | <e9f5814a-6f0d-4985-aebb-5b68b8c799c2@x10g2000prk.googlegroups.com> |
| In reply to | #15799 |
On Nov 17, 12:30 pm, Roy Smith <r...@panix.com> 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.
[toc] | [prev] | [next] | [standalone]
| From | Roy Smith <roy@panix.com> |
|---|---|
| Date | 2011-11-16 21:52 -0500 |
| Message-ID | <roy-8EE081.21525716112011@news.panix.com> |
| In reply to | #15800 |
In article <e9f5814a-6f0d-4985-aebb-5b68b8c799c2@x10g2000prk.googlegroups.com>, alex23 <wuwei23@gmail.com> 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.
[toc] | [prev] | [next] | [standalone]
| From | Ethan Furman <ethan@stoneleaf.us> |
|---|---|
| Date | 2011-11-16 19:24 -0800 |
| Message-ID | <mailman.2790.1321501935.27778.python-list@python.org> |
| In reply to | #15799 |
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~
[toc] | [prev] | [next] | [standalone]
| From | alex23 <wuwei23@gmail.com> |
|---|---|
| Date | 2011-11-17 18:31 -0800 |
| Message-ID | <ed48a730-2d39-4e71-a175-deda7578f8a8@o17g2000yqa.googlegroups.com> |
| In reply to | #15803 |
On Nov 17, 1:24 pm, Ethan Furman <et...@stoneleaf.us> 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 :)
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2011-11-17 04:43 +0000 |
| Message-ID | <4ec490ec$0$30003$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #15799 |
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 <staticmethod object at 0x421df0> False > outside <function foo at 0x41e6f0> 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
[toc] | [prev] | [next] | [standalone]
| From | Roy Smith <roy@panix.com> |
|---|---|
| Date | 2011-11-17 00:26 -0500 |
| Message-ID | <roy-11A6C6.00262017112011@news.panix.com> |
| In reply to | #15805 |
In article <4ec490ec$0$30003$c3e8da3$5496439d@news.astraweb.com>, Steven D'Aprano <steve+comp.lang.python@pearwood.info> 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...
[toc] | [prev] | [next] | [standalone]
| From | Devin Jeanpierre <jeanpierreda@gmail.com> |
|---|---|
| Date | 2011-11-17 01:20 -0500 |
| Message-ID | <mailman.2791.1321510888.27778.python-list@python.org> |
| In reply to | #15805 |
> 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
<steve+comp.lang.python@pearwood.info> 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 <staticmethod object at 0x421df0> False
>> outside <function foo at 0x41e6f0> 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
>
[toc] | [prev] | [next] | [standalone]
| From | Dotan Cohen <dotancohen@gmail.com> |
|---|---|
| Date | 2011-11-17 08:44 +0200 |
| Message-ID | <mailman.2792.1321512266.27778.python-list@python.org> |
| In reply to | #15799 |
On Thu, Nov 17, 2011 at 04:30, Roy Smith <roy@panix.com> 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 <staticmethod object at 0x421df0> False
> outside <function foo at 0x41e6f0> 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: <staticmethod object at 0x2a3c1a0> 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
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2011-11-17 00:37 -0700 |
| Message-ID | <mailman.2795.1321515508.27778.python-list@python.org> |
| In reply to | #15799 |
On Wed, Nov 16, 2011 at 11:44 PM, Dotan Cohen <dotancohen@gmail.com> 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.
[toc] | [prev] | [next] | [standalone]
| From | Thomas Rachel <nutznetz-0c1b6768-bfa9-48d5-a470-7603bd3aa915@spamschutz.glglgl.de> |
|---|---|
| Date | 2011-11-17 10:17 +0100 |
| Message-ID | <ja2jf7$bl7$1@r03.glglgl.gl> |
| In reply to | #15799 |
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<staticmethod object at 0x421df0> False
> outside<function foo at 0x41e6f0> 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
<function <lambda> at 0x00B43E30>
>>> s
<staticmethod object at 0x00B48A90>
>>> C.f
<unbound method C.<lambda>>
>>> C().f
<bound method C.<lambda> of <__main__.C object at 0x00B48810>>
>>> C.s
<function <lambda> at 0x00B43E30>
>>> C().s
<function <lambda> at 0x00B43E30>
>>> f.__get__(None, C)
<unbound method C.<lambda>>
>>> f.__get__(C(), C)
<bound method C.<lambda> of <__main__.C object at 0x00B48AD0>>
>>> s.__get__(None, C)
<function <lambda> at 0x00B43E30>
>>> s.__get__(C(), C)
<function <lambda> 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
[toc] | [prev] | [next] | [standalone]
| From | Dotan Cohen <dotancohen@gmail.com> |
|---|---|
| Date | 2011-11-17 13:13 +0200 |
| Message-ID | <mailman.2803.1321528426.27778.python-list@python.org> |
| In reply to | #15799 |
On Thu, Nov 17, 2011 at 09:37, Ian Kelly <ian.g.kelly@gmail.com> wrote: > On Wed, Nov 16, 2011 at 11:44 PM, Dotan Cohen <dotancohen@gmail.com> 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
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2011-11-17 22:38 +1100 |
| Message-ID | <mailman.2804.1321529903.27778.python-list@python.org> |
| In reply to | #15799 |
On Thu, Nov 17, 2011 at 10:13 PM, Dotan Cohen <dotancohen@gmail.com> wrote: > I'm at work far from Idle. Taken out of context, I'm sure your boss is pleased. :) ChrisA
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web