Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #12483 > unrolled thread
| Started by | "T. Goodchild" <tgoodchild@gmail.com> |
|---|---|
| First post | 2011-08-31 07:35 -0700 |
| Last post | 2011-09-05 20:58 -0700 |
| Articles | 20 on this page of 30 — 19 participants |
Back to article view | Back to comp.lang.python
Why do class methods always need 'self' as the first parameter? "T. Goodchild" <tgoodchild@gmail.com> - 2011-08-31 07:35 -0700
Re: Why do class methods always need 'self' as the first parameter? John Gordon <gordon@panix.com> - 2011-08-31 14:54 +0000
Re: Why do class methods always need 'self' as the first parameter? Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-09-01 02:06 +1000
Re: Why do class methods always need 'self' as the first parameter? Grant Edwards <invalid@invalid.invalid> - 2011-08-31 16:20 +0000
Re: Why do class methods always need 'self' as the first parameter? Emile van Sebille <emile@fenx.com> - 2011-08-31 08:01 -0700
Re: Why do class methods always need 'self' as the first parameter? Neil Cerutti <neilc@norwich.edu> - 2011-08-31 15:05 +0000
Re: Why do class methods always need 'self' as the first parameter? Javier Collado <javier.collado@gmail.com> - 2011-08-31 17:10 +0200
Re: Why do class methods always need 'self' as the first parameter? Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-09-01 01:41 +1000
Re: Why do class methods always need 'self' as the first parameter? Chris Torek <nospam@torek.net> - 2011-08-31 20:15 +0000
Re: Why do class methods always need 'self' as the first parameter? Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-09-01 10:48 +1000
Re: Why do class methods always need 'self' as the first parameter? Chris Angelico <rosuav@gmail.com> - 2011-09-01 11:47 +1000
Re: Why do class methods always need 'self' as the first parameter? Eric Snow <ericsnowcurrently@gmail.com> - 2011-08-31 20:07 -0600
Re: Why do class methods always need 'self' as the first parameter? Chris Torek <nospam@torek.net> - 2011-09-01 02:20 +0000
Re: Why do class methods always need 'self' as the first parameter? Piet van Oostrum <piet@vanoostrum.org> - 2011-09-05 16:15 +0200
Re: Why do class methods always need 'self' as the first parameter? Chris Torek <nospam@torek.net> - 2011-09-06 01:10 +0000
Re: Why do class methods always need 'self' as the first parameter? Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-09-06 14:31 +1000
Re: Why do class methods always need 'self' as the first parameter? Terry Reedy <tjreedy@udel.edu> - 2011-08-31 12:30 -0400
RE: Why do class methods always need 'self' as the first parameter? "Prasad, Ramit" <ramit.prasad@jpmorgan.com> - 2011-08-31 13:12 -0400
Re: Why do class methods always need 'self' as the first parameter? Piet van Oostrum <piet@vanoostrum.org> - 2011-09-08 01:01 +0200
Re: Why do class methods always need 'self' as the first parameter? Chris Rebert <clp2@rebertia.com> - 2011-08-31 11:31 -0700
Re: Why do class methods always need 'self' as the first parameter? Ian Kelly <ian.g.kelly@gmail.com> - 2011-08-31 15:52 -0600
Re: Why do class methods always need 'self' as the first parameter? Terry Reedy <tjreedy@udel.edu> - 2011-08-31 18:40 -0400
Re: Why do class methods always need 'self' as the first parameter? UncleLaz <andrei.lisnic@gmail.com> - 2011-09-01 03:40 -0700
Re: Why do class methods always need 'self' as the first parameter? Michiel Overtoom <motoom@xs4all.nl> - 2011-09-01 13:23 +0200
Re: Why do class methods always need 'self' as the first parameter? John Roth <johnroth1@gmail.com> - 2011-09-01 05:45 -0700
Re: Why do class methods always need 'self' as the first parameter? Ian Kelly <ian.g.kelly@gmail.com> - 2011-09-01 08:26 -0600
Re: Why do class methods always need 'self' as the first parameter? John Roth <johnroth1@gmail.com> - 2011-09-02 10:51 -0700
Re: Why do class methods always need 'self' as the first parameter? Ian Kelly <ian.g.kelly@gmail.com> - 2011-09-02 14:30 -0600
Re: Why do class methods always need 'self' as the first parameter? John Roth <johnroth1@gmail.com> - 2011-09-02 15:30 -0700
Re: Why do class methods always need 'self' as the first parameter? rantingrick <rantingrick@gmail.com> - 2011-09-05 20:58 -0700
Page 1 of 2 [1] 2 Next page →
| From | "T. Goodchild" <tgoodchild@gmail.com> |
|---|---|
| Date | 2011-08-31 07:35 -0700 |
| Subject | Why do class methods always need 'self' as the first parameter? |
| Message-ID | <0dc26f12-2541-4d41-8678-4fa53f347acf@g9g2000yqb.googlegroups.com> |
I’m new to Python, and I love it. The philosophy of the language (and of the community as a whole) is beautiful to me. But one of the things that bugs me is the requirement that all class methods have 'self' as their first parameter. On a gut level, to me this seems to be at odds with Python’s dedication to simplicity. For example, consider Python’s indent-sensitive syntax. Although other languages didn’t use indentation to specify scope, programmers always used indentation anyways. Making indentation took a common practice, made it a rule, and the result was a significantly improved signal-to-noise ratio in the readability of Python code. So why is 'self' necessary on class methods? It seems to me that the most common practice is that class methods *almost always* operate on the instance that called them. It would make more sense to me if this was assumed by default, and for "static" methods (methods that are part of a class, but never associated with a specific instance) to be labelled instead. Just curious about the rationale behind this part of the language.
[toc] | [next] | [standalone]
| From | John Gordon <gordon@panix.com> |
|---|---|
| Date | 2011-08-31 14:54 +0000 |
| Message-ID | <j3lhv1$26e$1@reader1.panix.com> |
| In reply to | #12483 |
In <0dc26f12-2541-4d41-8678-4fa53f347acf@g9g2000yqb.googlegroups.com> "T. Goodchild" <tgoodchild@gmail.com> writes:
> So why is 'self' necessary on class methods? It seems to me that the
> most common practice is that class methods *almost always* operate on
> the instance that called them. It would make more sense to me if this
> was assumed by default, and for "static" methods (methods that are
> part of a class, but never associated with a specific instance) to be
> labelled instead.
> Just curious about the rationale behind this part of the language.
How would a method access instance variables without 'self'?
They probably could have made 'self' a magical attribute that just
appears out of thin air instead of being passed as an argument, like
'this' in C++. But would that really provide any benefit?
--
John Gordon A is for Amy, who fell down the stairs
gordon@panix.com B is for Basil, assaulted by bears
-- Edward Gorey, "The Gashlycrumb Tinies"
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2011-09-01 02:06 +1000 |
| Message-ID | <4e5e5c1b$0$29974$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #12484 |
John Gordon wrote: > In <0dc26f12-2541-4d41-8678-4fa53f347acf@g9g2000yqb.googlegroups.com> "T. > Goodchild" <tgoodchild@gmail.com> writes: > >> So why is 'self' necessary on class methods? It seems to me that the >> most common practice is that class methods *almost always* operate on >> the instance that called them. It would make more sense to me if this >> was assumed by default, and for "static" methods (methods that are >> part of a class, but never associated with a specific instance) to be >> labelled instead. > >> Just curious about the rationale behind this part of the language. > > How would a method access instance variables without 'self'? If Python had compile time declarations, the compiler could know whether x=1 was referring to a local variable x or an attribute x. The reader might not, but the compiler would :) By the way, although the Python docs are a little inconsistent, the usual term here is "attribute" rather than "instance variable". Attributes need not live on the instance: they can also live on the class, a superclass, or be computed at run-time via at least three different mechanisms I can think of (__getattribute__, __getattr__, properties). Local variables are treated a bit differently from attributes, but broadly speaking, if you need a dot to access something, it's an attribute, if you don't, it's a name binding (or variable). Python even has two different sorts of errors for "variable" lookup failures: NameError (or UnboundLocalError) for un-dotted names, and AttributeError for dotted names. > They probably could have made 'self' a magical attribute that just > appears out of thin air instead of being passed as an argument, like > 'this' in C++. But would that really provide any benefit? Well obviously the C++ people thought so :) The effort to type "self, " in method signatures is pretty low. I don't think it is a problem. But other languages are free to choose differently. Cobra, for example, is explicitly derived from Python in many ways, but it drops the "self" (as well as other changes). http://cobra-language.com/docs/python/ -- Steven
[toc] | [prev] | [next] | [standalone]
| From | Grant Edwards <invalid@invalid.invalid> |
|---|---|
| Date | 2011-08-31 16:20 +0000 |
| Message-ID | <j3ln13$8ie$1@reader1.panix.com> |
| In reply to | #12493 |
On 2011-08-31, Steven D'Aprano <steve+comp.lang.python@pearwood.info> wrote:
> Well obviously the C++ people thought so :)
Well _that's_ certainly a ringing endorsement in the context of
designing a language that's easy to understand and use.
;)
--
Grant Edwards grant.b.edwards Yow! Where's SANDY DUNCAN?
at
gmail.com
[toc] | [prev] | [next] | [standalone]
| From | Emile van Sebille <emile@fenx.com> |
|---|---|
| Date | 2011-08-31 08:01 -0700 |
| Message-ID | <mailman.608.1314802888.27778.python-list@python.org> |
| In reply to | #12483 |
On 8/31/2011 7:35 AM T. Goodchild said... > Just curious about the rationale behind this part of the language. http://docs.python.org/faq/design.html
[toc] | [prev] | [next] | [standalone]
| From | Neil Cerutti <neilc@norwich.edu> |
|---|---|
| Date | 2011-08-31 15:05 +0000 |
| Message-ID | <9c70u5FckrU2@mid.individual.net> |
| In reply to | #12483 |
On 2011-08-31, T. Goodchild <tgoodchild@gmail.com> wrote: > I?m new to Python, and I love it. The philosophy of the > language (and of the community as a whole) is beautiful to me. > > But one of the things that bugs me is the requirement that all > class methods have 'self' as their first parameter. On a gut > level, to me this seems to be at odds with Python?s dedication > to simplicity. Think it through carefully, and you'll probably agree with Python's design. But not necessarily. In any case, this is a very common complaint, so check out the Python FAQ. http://docs.python.org/faq/design.html#why-self -- Neil Cerutti "A politician is an arse upon which everyone has sat except a man." e. e. cummings
[toc] | [prev] | [next] | [standalone]
| From | Javier Collado <javier.collado@gmail.com> |
|---|---|
| Date | 2011-08-31 17:10 +0200 |
| Message-ID | <mailman.609.1314803468.27778.python-list@python.org> |
| In reply to | #12483 |
Hello,
2011/8/31 T. Goodchild <tgoodchild@gmail.com>:
> But one of the things that bugs me is the requirement that all class
> methods have 'self' as their first parameter. On a gut level, to me
> this seems to be at odds with Python’s dedication to simplicity.
I think the answer to this question is part of the zen of python:
<<Explicit is better than implicit.>>
http://www.python.org/dev/peps/pep-0020/
Regards,
Javier
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2011-09-01 01:41 +1000 |
| Message-ID | <4e5e5628$0$29977$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #12483 |
T. Goodchild wrote:
> So why is 'self' necessary on class methods?
I assume you are talking about the declaration in the method signature:
def method(self, args): ...
rather than why methods have to be called using self.method. If not, there's
already a FAQ for that second question:
http://docs.python.org/faq/design.html#why-self
> It seems to me that the
> most common practice is that class methods *almost always* operate on
> the instance that called them.
By the way, what you're calling "class methods" are actually *instance*
methods, because they receive the instance "self" as the first parameter.
Python does have class methods, which receive the class, not the instance,
as the first parameter. These are usually written something like this:
class K(object):
@classmethod
def spam(cls, args):
print cls # always prints "class K", never the instance
Just like self, the name cls is a convention only. Class methods are usually
used for alternate constructors.
There are also static methods, which don't receive any special first
argument, plus any other sort of method you can invent, by creating
descriptors... but that's getting into fairly advanced territory. They're
generally specialised, and don't see much use.
As you can see, the terminology is not exactly the same as Java.
> It would make more sense to me if this
> was assumed by default, ...
Well here's the thing. Python methods are wrappers around function objects.
The method wrapper knows which instance is involved (because of the
descriptor magic which I alluded to above), but the function doesn't and
can't. Or at least not without horrible run-time hacks.
By treating "self" as an ordinary parameter which needs to be declared, you
can do cool stuff like bound and unbound methods:
f = "instance".upper # this is a bound method
g = str.upper # this is an unbound method
The bound method f already has the instance "self" filled in, so to speak.
So you can now just call it, and it will work:
f()
=> returns "INSTANCE"
The unbound method still needs the instance supplied. This makes it perfect
for code like this:
for instance in ("hello", "world"):
print g(instance)
especially if you don't know what g will be until run-time. (E.g. will it be
str.upper, str.lower, str.title?)
Because methods require that first argument to be given explicitly, unbound
methods are practically ordinary functions. They're so like functions that
in Python 3, they're done away with altogether, and the unwrapped function
object will be returned instead.
You can also do nifty stuff like dynamic method injections:
>>> def func(a, b):
... print(a, b)
...
>>> class K(object):
... pass
...
>>> K.func = func # dynamically inject a method
>>> instance = K()
>>> instance.func(23)
(<__main__.K object at 0xb7f0a4cc>, 23)
and it all just works. You can even inject a method onto the instance,
although it takes a bit more effort to make that work.
All this is possible without nasty hacks because self is treated as just an
ordinary parameter of functions. Otherwise, the compiler would need to know
whether the function was being called from inside a method wrapper or not,
and change the function signature appropriately, and that just gets too
ugly and messy for words.
So for the cost of having to declare self as an argument, we get:
* instant visual recognition of what's intended as a method ("the
first argument is called self") and what isn't
* a nicely consistent treatment of function signatures at all times
* clean semantics for the local variable namespace
* the same mechanism (with minor adjustments) can be used for class
and static methods
* bound and unbound methods semantics
plus as a bonus, plenty of ongoing arguments about whether or not having to
explicitly list "self" as a parameter is a good thing or not, thus keeping
people busy arguing on mailing lists instead of coding
<wink>
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | Chris Torek <nospam@torek.net> |
|---|---|
| Date | 2011-08-31 20:15 +0000 |
| Message-ID | <j3m4pg01enu@news4.newsguy.com> |
| In reply to | #12489 |
>In article <0dc26f12-2541-4d41-8678-4fa53f347acf@g9g2000yqb.googlegroups.com>
T. Goodchild asked, in part:
>>... One of the things that bugs me is the requirement that all class
>>methods have 'self' as their first parameter.
In article <4e5e5628$0$29977$c3e8da3$5496439d@news.astraweb.com>
Steven D'Aprano <steve+comp.lang.python@pearwood.info> wrote:
[Comprehensive reply, noting that these are actually instance
methods, and that there are class and static methods as well]:
>Python does have class methods, which receive the class, not the instance,
>as the first parameter. These are usually written something like this:
>
>class K(object):
> @classmethod
> def spam(cls, args):
> print cls # always prints "class K", never the instance
>
>Just like self, the name cls is a convention only. Class methods are usually
>used for alternate constructors.
>
>There are also static methods, which don't receive any special first
>argument, plus any other sort of method you can invent, by creating
>descriptors... but that's getting into fairly advanced territory. ...
[rest snipped]
I am not sure whether T. Goodchild was asking any of the above or
perhaps also one other possible question: if an instance method
is going to receive an automatic first "self" parameter, why require
the programmer to write that parameter in the "def"? For instance
we *could* have:
class K(object):
def meth1(arg1, arg2):
self.arg1 = arg1 # self is "magically available"
self.arg2 = arg2
@classmethod
def meth2(arg):
use(cls) # cls is "magically available"
and so on. This would work fine. It just requires a bit of implicit
sneakiness in the compiler: an instance method magically creates
a local variable named "self" that binds to the invisible first
parameter, and a class method magically creates a local variable
named "cls" that binds to the invisible first parameter, and so
on.
Instead, we have a syntax where you, the programmer, write out the
name of the local variable that binds to the first parameter. This
means the first parameter is visible. Except, it is only visible
at the function definition -- when you have the instance and call
the instance or class method:
black_knight = K()
black_knight.meth1('a', 1)
black_knight.meth2(2)
the first parameters (black_knight, and black_knight.__class__,
respectively) are magic, and invisible.
Thus, Python is using the "explicit is better than implicit" rule
in the definition, but not at the call site. I have no problem with
this. Sometimes I think implicit is better than explicit. In this
case, there is no need to distinguish, at the calls to meth1() and
meth2(), as to whether they are "class" or "instance" methods. At
the *calls* they would just be distractions.
At the *definitions*, they are not as "distraction-y" since it is
important to know, during the definition, whether you are operating
on an instance (meth1) or the class itself (meth2), or for that
matter on neither (static methods). One could determine this from
the absence or presence of "@classmethod" or "@staticmethod", but
the minor redundancy in the "def" statement seems, well, minor.
Also, as a bonus, it lets you obfuscate the code by using a name
other than "self" or "cls". :-)
--
In-Real-Life: Chris Torek, Wind River Systems
Intel require I note that my opinions are not those of WRS or Intel
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: gmail (figure it out) http://web.torek.net/torek/index.html
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2011-09-01 10:48 +1000 |
| Message-ID | <4e5ed670$0$29981$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #12524 |
Chris Torek wrote: >>There are also static methods, which don't receive any special first >>argument, plus any other sort of method you can invent, by creating >>descriptors... but that's getting into fairly advanced territory. ... > [rest snipped] > > I am not sure whether T. Goodchild was asking any of the above or > perhaps also one other possible question: if an instance method > is going to receive an automatic first "self" parameter, why require > the programmer to write that parameter in the "def"? Er, yes, just like I suggested in my opening paragraph, and as I answered following the bit you marked as snipped :) > For instance > we *could* have: > > class K(object): > def meth1(arg1, arg2): > self.arg1 = arg1 # self is "magically available" > self.arg2 = arg2 > > @classmethod > def meth2(arg): > use(cls) # cls is "magically available" > > and so on. This would work fine. It just requires a bit of implicit > sneakiness in the compiler: an instance method magically creates > a local variable named "self" that binds to the invisible first > parameter, and a class method magically creates a local variable > named "cls" that binds to the invisible first parameter, and so > on. It would need more than "a bit", because methods are just wrappers around functions. One way would be for Python to give that up, and require methods to be special built-in types like functions. That adds complexity to the compiler, and (very likely) would decrease the level of dynamism possible. Another way would be for the compiler to perform darkest black magic to determine whether the function was being called from inside a method or not. That would be complicated and fragile. [...] > At the *definitions*, they are not as "distraction-y" since it is > important to know, during the definition, whether you are operating > on an instance (meth1) or the class itself (meth2), or for that > matter on neither (static methods). One could determine this from > the absence or presence of "@classmethod" or "@staticmethod" classmethod and staticmethod are functions, not declarations. You can't assume that @classmethod is the only way to get a class method: the metaclass could do it, or you could inject one in from the outside. You can dynamically change the state of a method from instance method to class method and back again at run-time. Python classes have a lot of dynamism made possible by the fact that methods are just wrappers around functions with an explicitly declared "self". That dynamism is rarely used, but not *that* rarely, and is very useful when used. Implicit self would likely negate all that. -- Steven
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2011-09-01 11:47 +1000 |
| Message-ID | <mailman.640.1314841650.27778.python-list@python.org> |
| In reply to | #12536 |
On Thu, Sep 1, 2011 at 10:48 AM, Steven D'Aprano <steve+comp.lang.python@pearwood.info> wrote: > Python classes have a lot of dynamism made possible by the fact that methods > are just wrappers around functions with an explicitly declared "self". That > dynamism is rarely used, but not *that* rarely, and is very useful when > used. Implicit self would likely negate all that. > Hmm. Got any examples sitting around? I'm curious as to what you can do with this. I'm like a kid with a new chemistry set - "what happens if I mix a little of everything together?"... ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Eric Snow <ericsnowcurrently@gmail.com> |
|---|---|
| Date | 2011-08-31 20:07 -0600 |
| Message-ID | <mailman.641.1314842865.27778.python-list@python.org> |
| In reply to | #12536 |
On Wed, Aug 31, 2011 at 7:47 PM, Chris Angelico <rosuav@gmail.com> wrote:
> On Thu, Sep 1, 2011 at 10:48 AM, Steven D'Aprano
> <steve+comp.lang.python@pearwood.info> wrote:
>> Python classes have a lot of dynamism made possible by the fact that methods
>> are just wrappers around functions with an explicitly declared "self". That
>> dynamism is rarely used, but not *that* rarely, and is very useful when
>> used. Implicit self would likely negate all that.
>>
>
> Hmm. Got any examples sitting around? I'm curious as to what you can
> do with this. I'm like a kid with a new chemistry set - "what happens
> if I mix a little of everything together?"...
First thing that comes to mind is calling a base class's
implementation of a method:
class X(Y):
def __init__(self, value):
Y.__init__(self)
self.value = value
-eric
>
> ChrisA
> --
> http://mail.python.org/mailman/listinfo/python-list
>
[toc] | [prev] | [next] | [standalone]
| From | Chris Torek <nospam@torek.net> |
|---|---|
| Date | 2011-09-01 02:20 +0000 |
| Message-ID | <j3mq6801vlc@news4.newsguy.com> |
| In reply to | #12536 |
In article <4e5ed670$0$29981$c3e8da3$5496439d@news.astraweb.com>
Steven D'Aprano <steve+comp.lang.python@pearwood.info> wrote:
>Er, yes, just like I suggested in my opening paragraph, and as I answered
>following the bit you marked as snipped :)
Oops, so you did (went back and re-read it). Must have gotten
interrupted and lost track. :-)
>> [A different hack would] requires a bit of implicit
>> sneakiness in the compiler: an instance method magically creates
>> a local variable named "self" that binds to the invisible first
>> parameter, and a class method magically creates a local variable
>> named "cls" that binds to the invisible first parameter, and so
>> on.
>It would need more than "a bit", because methods are just wrappers
>around functions.
Well, depends on how the hack would be done. :-) For instance,
the @decorator might turn on something that "undoes" or "replaces"
the "self" parameter. That is, with ordinary class functions and
methods:
class HackyNotQuitePythonVersion:
def ordinary(arg):
self.arg = arg
would compile to (approximately):
class PythonVersion:
def __mrap(self, *args, **kwargs):
def ordinary(arg):
self.arg = arg
ordinary(*args, **kwargs)
ordinary = __mrap
(add the usual other manipulations to suit here, i.e., all the
stuff for making introspection work right, i.e., @functools.wraps).
@staticmethod would suppress the wrapper entirely, while @classmethod
would change it to one that binds the "cls" argument. (Any function
without some appropriate @whatever gets the Method Wrapper __mrap.
@staticmethod tells the class builder not to add any wrapper, and
@classmethod tells it to add the Class Wrapper __crap. [The name
tells you what I think of the above code. :-) ])
(Note subtle ground for bugs here: if you then actually define a
"self" parameter, it shadows the outer-scope one from the wrapper.
So while I am not even proposing that anyone should do this in the
first place, it has more downsides than mere implementation
complexity.)
>Another way would be for the compiler to perform darkest black magic to
>determine whether the function was being called from inside a method or
>not. That would be complicated and fragile.
Yes, even worse than my outlined implementation above, I think.
>classmethod and staticmethod are functions, not declarations.
They are decorator functions, but to someone *reading the code*
they are also "declarations" of sort. This is all I meant: they
tell the (human) reader/programmer which "secret arguments" to
expect.
>You can't assume that @classmethod is the only way to get a
>class method: the metaclass could do it, or you could inject
>one in from the outside.
Yes, but that would all still work, as in this not-quite-Python
(worsened-Python) language, whoever writes those metaclasses and
other decorators would continue to do whatever icky stuff was
required (e.g., __mrap and __crap above). It would mean yet more
things for people to know about, but then, metaclasses and decorators
*always* mean that:
@hmm
def spam():
return magic
Is "magic" something supplied by the decorator? You have to look
at the decorator to find out, as the rather horrid example I have
attached shows.
(Note: I am doing all this is python 2.x on the laptop. Using
global, in @hmm, is evil, but it works. I did not bother trying
to write a metaclass that inserts __mrap, etc., but I believe it
can be done.)
>Python classes have a lot of dynamism made possible by the fact that methods
>are just wrappers around functions with an explicitly declared "self". That
>dynamism is rarely used, but not *that* rarely, and is very useful when
>used. Implicit self would likely negate all that.
I do not believe it would *negate* it, just *complicate* it. But
that is not a good thing either. :-)
----- horrible example / test code below
import functools
def hmm(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
global magic, rlevel
try:
save = magic, rlevel
restore = True
rlevel += 1
except NameError:
restore = False
rlevel = 1
magic = func.__name__ + " and eggs"
ret = func(*args, **kwargs)
if restore:
magic, rlevel = save
else:
del magic, rlevel
return ret
return wrapper
@hmm
def ham():
if rlevel < 2:
print spam()
return magic
@hmm
def spam():
return magic
print ham()
try:
print magic
except NameError:
print 'name "magic" is not available here, as desired'
try:
print rlevel
except NameError:
print 'name "rlevel" is not available here, as desired'
class X(object):
def __mrap(self, *args, **kwargs):
def xset(arg):
self.arg = arg
xset(*args, **kwargs)
xset = __mrap
def __mrap(self, *args, **kwargs):
def show():
print self.arg
show(*args, **kwargs)
show = __mrap
x = X()
x.xset('value')
x.show()
--
In-Real-Life: Chris Torek, Wind River Systems
Intel require I note that my opinions are not those of WRS or Intel
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: gmail (figure it out) http://web.torek.net/torek/index.html
[toc] | [prev] | [next] | [standalone]
| From | Piet van Oostrum <piet@vanoostrum.org> |
|---|---|
| Date | 2011-09-05 16:15 +0200 |
| Message-ID | <m2wrdnf53u.fsf@cochabamba.vanoostrum.org> |
| In reply to | #12524 |
Chris Torek <nospam@torek.net> writes:
[snip]
> Instead, we have a syntax where you, the programmer, write out the
> name of the local variable that binds to the first parameter. This
> means the first parameter is visible. Except, it is only visible
> at the function definition -- when you have the instance and call
> the instance or class method:
>
> black_knight = K()
> black_knight.meth1('a', 1)
> black_knight.meth2(2)
>
> the first parameters (black_knight, and black_knight.__class__,
> respectively) are magic, and invisible.
>
> Thus, Python is using the "explicit is better than implicit" rule
> in the definition, but not at the call site. I have no problem with
> this. Sometimes I think implicit is better than explicit. In this
> case, there is no need to distinguish, at the calls to meth1() and
> meth2(), as to whether they are "class" or "instance" methods. At
> the *calls* they would just be distractions.
It *is* explicit also at the call site. It only is written at the left of the dot rather than at the right of the parenthesis. And that is necessary to locate which definition of the method applies. It would be silly to repeat this information after the parenthesis. Not only silly, it would be stupid as it would be a source of errors, and an example of DRY.
--
Piet van Oostrum <piet@vanoostrum.org>
WWW: http://pietvanoostrum.com/
PGP key: [8DAE142BE17999C4]
[toc] | [prev] | [next] | [standalone]
| From | Chris Torek <nospam@torek.net> |
|---|---|
| Date | 2011-09-06 01:10 +0000 |
| Message-ID | <j43rug02nqb@news1.newsguy.com> |
| In reply to | #12768 |
>Chris Torek <nospam@torek.net> writes:
>[snip]
>> when you have [an] instance and call [an] instance or class method:
[note: I have changed the names very slightly here, and removed
additional arguments, on purpose]
>> black_knight = K()
>> black_knight.spam()
>> black_knight.eggs()
>>
>> the first parameters ... are magic, and invisible.
>>
>> Thus, Python is using the "explicit is better than implicit" rule
>> in the definition, but not at the call site. ...
In article <m2wrdnf53u.fsf@cochabamba.vanoostrum.org>
Piet van Oostrum <piet@vanoostrum.org> wrote:
>It *is* explicit also at the call site. It only is written at the left
>of the dot rather than at the right of the parenthesis.
It cannot possibly be explicit. The first parameter to one of the
method functions is black_knight, but the first parameter to the
other method is black_knight.__class__.
Which one is which? Is spam() the instance method and eggs() the
class method, or is spam() the class method and eggs the instance
method? (One does not, and should not, have to *care*, which is
kind of the point here. :-) )
>And that is necessary to locate which definition of the method
>applies.
By "that" I assume you mean the name "black_knight" here. But the
name is not required to make the call; see the last line of the
following code fragment:
funclist = []
...
black_knight = K()
funclist.append(black_knight.spam)
funclist.append(black_knight.eggs)
...
# At this point, let's say len(funclist) > 2,
# and some number of funclist[i] entries are ordinary
# functions that have no special first parameter.
random.choice(funclist)()
>It would be silly to repeat this information after the parenthesis.
>Not only silly, it would be stupid as it would be a source of errors,
>and an example of DRY.
Indeed. But I believe the above is a demonstration of how the
"self" or "cls" parameter is in fact implicit, not explicit.
(I am using python 2.x, and doing this in the interpreter:
random.choice(funclist)
-- without the parentheses to call the function -- produces:
<bound method K.[name omitted] of <__main__.K object at 0x249f50>>
<bound method type.[name omitted] of <class '__main__.K'>>
<function ordinary at 0x682b0>
The first is the instance method, whose name I am still keeping
secret; the second is the class method; and the third is the ordinary
function I added to the list. The actual functions print their
own name and their parameters if any, and one can see that the
class and instance methods get one parameter, and the ordinary
function gets none.)
--
In-Real-Life: Chris Torek, Wind River Systems
Intel require I note that my opinions are not those of WRS or Intel
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: gmail (figure it out) http://web.torek.net/torek/index.html
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2011-09-06 14:31 +1000 |
| Message-ID | <4e65a21e$0$29969$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #12804 |
On Tue, 6 Sep 2011 11:10 am Chris Torek wrote:
>>> black_knight = K()
>>> black_knight.spam()
>>> black_knight.eggs()
>>>
>>> the first parameters ... are magic, and invisible.
>>>
>>> Thus, Python is using the "explicit is better than implicit" rule
>>> in the definition, but not at the call site. ...
>
> In article <m2wrdnf53u.fsf@cochabamba.vanoostrum.org>
> Piet van Oostrum <piet@vanoostrum.org> wrote:
>>It *is* explicit also at the call site. It only is written at the left
>>of the dot rather than at the right of the parenthesis.
>
> It cannot possibly be explicit. The first parameter to one of the
> method functions is black_knight, but the first parameter to the
> other method is black_knight.__class__.
I think you are expecting more explicitness than actually required. There
are degrees of explicitness:
- The current President of the United States is a black man.
- On 6th September 2011, the duly constituted President of the United
States of America is a black man.
- On 6th September 2011, the duly constituted government official with
the title of President of the nation known as the United States of
America is an individual member of the species Homo sapiens with XY
chromosomes and of recent African ancestry.
As opposed to implicit:
- He is a black guy.
There is no requirement for every last gory detail to be overtly specified
in full. I quote from WordNet:
explicit
adj 1: precisely and clearly expressed or readily observable;
leaving nothing to implication; "explicit
instructions"; "she made her wishes explicit";
"explicit sexual scenes" [syn: expressed] [ant: implicit]
2: in accordance with fact or the primary meaning of a term
[syn: denotative]
Note the second definition in particular: in accordance with the primary
meaning of a term: the primary meaning of "class method" is that it
receives the class rather than the instance as first argument.
The "explicit is better than implicit" Zen should, in my opinion, be best
understood as a recommendation that code should, in general, avoid getting
input from context. In general, functions should avoid trying to decide
which behaviour is wanted according to context or the environment:
def func(x):
if running_in_a_terminal():
print "The answer is", (x+1)/2
else:
printer = find_a_printer()
if printer is not None:
printer.send((x+1)/2, header="func(%r)"%x, footer="Page 1")
else:
# Try sending email to the current user, the default user,
# postmaster or root in that order.
msg = make_email("The answer is", (x+1)/2)
for user in [get_current_user(), DEFAULT_USER,
"root@localhost.localdomain", ...]:
result = send_mail(msg, to=user)
if result == 0: break
else:
# Fall back on beeping the speakers in Morse code
...
(what if I want to beep the speakers from the terminal?), but not as a
prohibition against code like this:
def factorial(x):
# Return the factorial of the integer part of x.
n = int(x)
if n <= 1: return 1
return n*factorial(n-1)
There's no need to require the user to explicitly call int(x) before calling
factorial just to satisfy the Zen.
A function is free to process arguments as required, even to throw out
information (e.g. float -> int, instance -> class). What it shouldn't do is
*add* information implied by context (or at least, it should be very
cautious in doing so, and document it carefully, and preferably allow the
caller to easily override such implied data).
> Which one is which? Is spam() the instance method and eggs() the
> class method, or is spam() the class method and eggs the instance
> method? (One does not, and should not, have to *care*, which is
> kind of the point here. :-) )
You can't tell just from the syntax used to call them:
function(arg)
bound_method(arg)
builtin_function_or_method(arg)
callable_instance(arg)
type(arg)
all use the same syntax. There is no requirement that you should be able to
tell *everything* about a line of code just from the syntax used. If you
want to know whether black_knight.spam is an instance method or a class
method, or something else, use introspection to find out.
> By "that" I assume you mean the name "black_knight" here. But the
> name is not required to make the call; see the last line of the
> following code fragment:
>
> funclist = []
> ...
> black_knight = K()
> funclist.append(black_knight.spam)
> funclist.append(black_knight.eggs)
> ...
> # At this point, let's say len(funclist) > 2,
> # and some number of funclist[i] entries are ordinary
> # functions that have no special first parameter.
> random.choice(funclist)()
Irrelevant. The instance used for the bound method is explicitly specified
when you create it. But there's no requirement that you need to explicitly
specify the instance every single time you *use* the bound method. The
instance is part of the bound method, it isn't implied by context or
history or guessed from the environment.
Contrast what Python actually does with a hypothetical language where bound
methods' instances are implicitly assigned according to the most recent
instance created:
black_knight = Knight()
funclist.append(spam) # refers to black_knight.spam
white_knight = Knight()
funclist.append(spam) # refers to white_knight.spam
baldrick = Knave()
funclist.append(eggs) # oops, Knaves don't have an eggs attribute
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | Terry Reedy <tjreedy@udel.edu> |
|---|---|
| Date | 2011-08-31 12:30 -0400 |
| Message-ID | <mailman.614.1314808320.27778.python-list@python.org> |
| In reply to | #12483 |
On 8/31/2011 10:35 AM, T. Goodchild wrote:
> But one of the things that bugs me is the requirement that all class
> methods have 'self' as their first parameter. On a gut level, to me
> this seems to be at odds with Python’s dedication to simplicity.
Actually, it is a consequence of Python's dedication to simplicity. A
method is simply a function that is an attribute of a class. (This is
even clearer in Py 3.) Hence, there is no special syntax for methods.
Consider
def double(obj): return 2*obj.value
class C:
def __init__(self, val):
self.value = val
c = C(3)
C.double = double
c.doub = double
# not c.double as that would mask access to C.double in c.double() below
print(double(c), C.double(c), c.double(), c.doub(c))
# 6 6 6 6
--
Terry Jan Reedy
[toc] | [prev] | [next] | [standalone]
| From | "Prasad, Ramit" <ramit.prasad@jpmorgan.com> |
|---|---|
| Date | 2011-08-31 13:12 -0400 |
| Message-ID | <mailman.619.1314810786.27778.python-list@python.org> |
| In reply to | #12483 |
>def double(obj): return 2*obj.value > >class C: > def __init__(self, val): > self.value = val > >c = C(3) >C.double = double >c.doub = double ># not c.double as that would mask access to C.double in c.double() below >print(double(c), C.double(c), c.double(), c.doub(c)) Sorry if I get some of the following terminology wrong, I get a bit confused on Python terms. I hope the following is still coherent. (Is there a dictionary of Python terminology?) Given the above example I get this >>> print c.double(c) TypeError: double() takes exactly 1 argument (2 given) >>> print c.doub(c) 6 It seems to me that if I add a function to the list of class attributes it will automatically wrap with "self" but adding it to the object directly will not wrap the function as a method. Can somebody explain why? I would have thought that any function added to an object would be a method (unless decorated as a class method). Hmm, or does the decoration just tell Python not to turn an object's function into a method? I.e. Is the decorator basically just the syntactic sugar for doing the above? Ramit Ramit Prasad | JPMorgan Chase Investment Bank | Currencies Technology 712 Main Street | Houston, TX 77002 work phone: 713 - 216 - 5423 This email is confidential and subject to important disclaimers and conditions including on offers for the purchase or sale of securities, accuracy and completeness of information, viruses, confidentiality, legal privilege, and legal entity disclaimers, available at http://www.jpmorgan.com/pages/disclosures/email.
[toc] | [prev] | [next] | [standalone]
| From | Piet van Oostrum <piet@vanoostrum.org> |
|---|---|
| Date | 2011-09-08 01:01 +0200 |
| Message-ID | <m2vct4arf0.fsf@cochabamba.vanoostrum.org> |
| In reply to | #12503 |
"Prasad, Ramit" <ramit.prasad@jpmorgan.com> writes: > It seems to me that if I add a function to the list of class attributes it will automatically wrap with "self" but adding it to the object directly will not wrap the function as a method. Can somebody explain why? I would have thought that any function added to an object would be a method (unless decorated as a class method). The special magic to transform a function into a method is only applied for functions found as attributes of the class, not for instance attributes. It is a matter of design. > Hmm, or does the decoration just tell Python not to turn an object's function into a method? I.e. Is the decorator basically just the syntactic sugar for doing the above? The classmethod decorator transforms the method (or actually the function) into a different kind of object (a class method). -- Piet van Oostrum <piet@vanoostrum.org> WWW: http://pietvanoostrum.com/ PGP key: [8DAE142BE17999C4]
[toc] | [prev] | [next] | [standalone]
| From | Chris Rebert <clp2@rebertia.com> |
|---|---|
| Date | 2011-08-31 11:31 -0700 |
| Message-ID | <mailman.627.1314815483.27778.python-list@python.org> |
| In reply to | #12483 |
On Wed, Aug 31, 2011 at 10:12 AM, Prasad, Ramit <ramit.prasad@jpmorgan.com> wrote: >>def double(obj): return 2*obj.value >> >>class C: >> def __init__(self, val): >> self.value = val >> >>c = C(3) >>C.double = double >>c.doub = double >># not c.double as that would mask access to C.double in c.double() below >>print(double(c), C.double(c), c.double(), c.doub(c)) > > Sorry if I get some of the following terminology wrong, I get a bit confused on Python terms. I hope the following is still coherent. (Is there a dictionary of Python terminology?) The documentation has a glossary: http://docs.python.org/glossary.html It's not entirely comprehensive though. Cheers, Chris
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | comp.lang.python
csiph-web