Re: staticmethod makes my brain hurt

2011-11-17 Thread alex23
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

2011-11-17 Thread Chris Angelico
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

2011-11-17 Thread Dotan Cohen
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

2011-11-17 Thread Thomas Rachel

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

2011-11-16 Thread Ian Kelly
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

2011-11-16 Thread Dotan Cohen
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

2011-11-16 Thread Devin Jeanpierre
> 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

2011-11-16 Thread Roy Smith
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

2011-11-16 Thread Steven D'Aprano
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

2011-11-16 Thread Ethan Furman

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

2011-11-16 Thread Roy Smith
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

2011-11-16 Thread alex23
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