Attack a sacred Python Cow

R

Russ P.

I presume you are proposing the opposite also, that ".member" would
internally be expanded to "self.member".

As I said before, that, or something near like it (it is hard to exactly
compare underspecified proposals) has be suggested and rejected, even if
someone gave you not the exact reference. For one thing, as Guido
noted, a single . can be hard to see and easy to miss, depending on
one's eyesight, environmental lighting, and exact display medium,
including font.

I suspect Guido's other reasons have been covered, but I do not want
misquote him. I will leave you to search the pydev list archives.


If I understand you, that would mean that .attribute would raise
NameError: name 'self' is not defined
if used anywhere where 'self' was not defined.

After thinking about this a bit more, let me try to be more specific.

Forget about the empty first argument and the "." for the first
argument. Just let the first argument be "self" or anything the
programmer chooses. No change there.

If access is needed to "self.var", let it be accessable as either
"self.var" or simply ".var". Ditto for "self.method()", which would be
accessible as ".method()".

In other words, wherever ".var" appears, let it be interpreted as
"<arg1>.var". If the first argument is "self", then it should be
equivalent to "self.var". If the first argument is "snafu", then
".var" should be equivalent to "snafu.var".

I can't think of any technical problem with this proposal, but I may
be overlooking something. If so, please let me know.

This proposal should be relatively easy to implement, and it would
reduce code clutter significantly. (I could probably write a pre-
processor to implement myself it in less than a day.)
 
R

Russ P.

What Guido rejected there is most certainly *not*
what I suggested. I agree with Guido on that one.

Orly?

Ian Bicking wrote: "I propose that the self argument be removed from

method definitions."

Philip Eby suggested:
def .aMethod(arg1, arg2):
return .otherMethod(arg1*2+arg2)

Guido shot them all down by stating:
[Y]ou're proposing to hide a
fundamental truth in Python, that methods are "just" functions whose
first argument can be supplied using syntactic sugar

Any more reading comprehension we can do for you?

Dude, I agree with Guido completely on this one. You
seem to be clueless about the issue here. You're the
one with the reading comprehension problem. Please
quit wasting my time with your irrelevant crap.
 
A

alex23

Dude, I agree with Guido completely on this one. You
seem to be clueless about the issue here. You're the
one with the reading comprehension problem. Please
quit wasting my time with your irrelevant crap.

I pointed you at a thread -where it had been suggested and rejected-.
And I'm the clueless one?

I don't think I'm the one wasting anyone's time here, but fine. I've
got far better things to do with my time than waste it talking to you.
 
R

Russ P.

I pointed you at a thread -where it had been suggested and rejected-.
And I'm the clueless one?

I don't think I'm the one wasting anyone's time here, but fine. I've
got far better things to do with my time than waste it talking to you.

What was "suggested in rejected" on the thread you pointed me to was
not what I suggested. Not even close. Get it, genius?
 
M

Michael Torrie

Derek said:
Regardless of how it's implementd, it's such a common idiom to use
self to refer to object instances within a class in Python that it
ought to be more automatic. Personally, I kind of like the idea of
using @ and thinking of it more like an operator... Kind of like
dereferencing a pointer, only with an implied pointer name.

class foo:
def __init__():
@.increment = 2

def bar(a)
return a + @.increment

I'm sure all the Pythonistas will hate this idea though... ;-) To be
honest, it smacks a little of Perl's magic variables, which I actually
hate with a passion. This is the only place in Python I'd consider
doing something like this.

I think the biggest reason why an implicit self is bad is because it
prevents monkey-patching of existing class objects. Right now I can add
a new method to any existing class just with a simple attribute like so
(adding a new function to an existing instance object isn't so simple,
but ah well):

def a(self, x, y):
self.x = x
self.y = y

class Test(object):
pass

Test.setxy = a

b = Test()

b.setxy(4,4)

print b.x, b.y

If self was implicit, none of this would work. Now this contrived
example is not useful, and maybe not even correct, but I have patched
existing classes on several occasions using this method. How could
python retain it's dynamic nature and still have an implicit self? How
would the interpreter know when to add the self variable and when not to?
 
T

Terry Reedy

Derek said:
Furthermore, as you described, defining the function within the scope
of a class binds a name to the function and then makes it a method of
the class. Once that happens, *the function has become a method*.

If you mean that a user-defined function object becomes a different
class of object when bound to a class attribute name, that is wrong.
Once a function, always a function. It may be called an 'instance
method' but it is still a function. Any function object can be an
attribute of multiple classes, without inheritance, or of none.

When a function attribute is accessed via an instance of the class, it
is *wrapped* with a bound method object that basically consists of
references to the function and instance. When the 'bound method' is
called, the instance is inserted in front of the other arguments to be
matched with the first parameter.

In 2.0, functions accessed through the class were rather uselessly
wrapped as an 'unbound method', but those wrappers have been discarded
in 3.0.
To be perfectly honest, the idea that an object method can be defined
outside the scope of an object (i.e. where the code has no reason to
have any knowledge of the object) seems kind of gross to me...

I happen to like the simplicity that "def statements (and lambda
expressions) create function objects." Period.

....
It does indeed -- it does more than imply. It states outright that
the function is defined within the namespace of that object,
True.

and as such that it is inherently part of that object.

False. That does not follow. Python objects generally exist
independently of each other. Think of them as existing in a nameless
dataspace if you want. Collection/container objects collect/contain
references to their members, just as a club roster does, but they only
metaphorically 'contain' their members. Any object can be a member of
any number of collections, just as humans can join any number of clubs
and groups. In mathematical set theory, membership is also non-exclusive.
So why should it need
to be explicitly told about the object of which it is already a part?

Because it is not a 'part' of a class in the sense you seem to mean.

What is true is that functions have a read-only reference to the global
namespace of the module in which they are defined. But they do not have
to be a member of that namespace.

Terry Jan Reedy
 
M

Michael Torrie

Colin said:
I don't see the need for the comma in fun.

It (the entire first variable!) is needed because a method object is
constructed from a normal function object:

def method(self,a,b):
pass

class MyClass(object):
pass

MyClass.testmethod=method

That's precisely the same as if you'd defined method inside of the class
to begin with. A function becomes a method when the lookup procedure in
the instance object looks up the attribute and returns (from what I
understand) essentially a closure that binds the instance to the first
variable of the function. The result is known as a bound method, which
is a callable object:
<bound method MyClass.testmethod of <__main__.instance object at xxx>>


How would this work if there was not first parameter at all?

In short, unlike what most of the implicit self advocates are saying,
it's not just a simple change to the python parser to do this. It would
require a change in the interpreter itself and how it deals with classes.
 
R

Russ P.

If you mean that a user-defined function object becomes a different
class of object when bound to a class attribute name, that is wrong.
Once a function, always a function. It may be called an 'instance
method' but it is still a function. Any function object can be an
attribute of multiple classes, without inheritance, or of none.

When a function attribute is accessed via an instance of the class, it
is *wrapped* with a bound method object that basically consists of
references to the function and instance. When the 'bound method' is
called, the instance is inserted in front of the other arguments to be
matched with the first parameter.

In 2.0, functions accessed through the class were rather uselessly
wrapped as an 'unbound method', but those wrappers have been discarded
in 3.0.


I happen to like the simplicity that "def statements (and lambda
expressions) create function objects." Period.

...


False. That does not follow. Python objects generally exist
independently of each other. Think of them as existing in a nameless
dataspace if you want. Collection/container objects collect/contain
references to their members, just as a club roster does, but they only
metaphorically 'contain' their members. Any object can be a member of
any number of collections, just as humans can join any number of clubs
and groups. In mathematical set theory, membership is also non-exclusive.


Because it is not a 'part' of a class in the sense you seem to mean.

What is true is that functions have a read-only reference to the global
namespace of the module in which they are defined. But they do not have
to be a member of that namespace.

Terry Jan Reedy

This whole discussion reminds me of discussions I saw on comp.lang.ada
several years ago when I had a passing interest in Ada.

My memory on this is a bit fuzzy, but IFIRC Ada 95 did not support
standard OO "dot" syntax of the form

myObject.myFunction(args)

Instead, "myfunction" was just a "regular" function that took
"myObject" and "args" as arguments. It was called as

myFunction(myObject, args)

It was put into the appropriate package or subpackage where it
belonged rather than in a class definition. Namespaces were defined by
a package hierarchy rather than by classes (which is actually more
logical, but that's another topic).

Well, so many people demanded the "dot" notation that it was finally
implemented in Ada 2005. So now user can use the more familiar dot
notation, but my understanding is that it is just "syntactic sugar"
for the old notation.

So when Python people go out of their way to point out that class
"methods" in Python are implemented as regular functions, that seems
fairly obvious to me -- but perhaps only because of my passing
familiarity with Ada.
 
S

s0suk3

In message






Because it was one of the things the OP was complaining about (see above).

Wrong. What the OP complains about has no relevance on what makes a
language OO or not.
 
C

Carl Banks

Whether or not one should write 'if x' or 'if x != 0' [typo corrected]
depends on whether one means the general 'if x is any non-null object
for which bool(x) == True' or the specific 'if x is anything other than
numeric zero'. The two are not equivalent. Ditto for the length
example.
Can you think of any use cases for the former? And I mean something
where it can't be boiled down to a simple explicit test for the sorts of
arguments you're expecting; something that really takes advantage of the
"all objects are either true or false" paradigm.

But why do you need the explicit test?

I asked you first, buddy.


[snip attempt to reverse argument]
You might find it pretty weak, but I find it a wonderful, powerful
feature.

Powerful? You've got to be kidding me. If I have a function

create_object(name)

where one creates an anonymous object by passing an empty string,
behold! now I can also create an anonymous object by passing None.
You call that powerful? I call it simple convenience, and not
something that we'd suffer much for for not having. But it's still
the one thing I can think of that can't be replaced by a simple
explicit test.

I recently wrote a method that sequentially calls one function after
another with the same argument, looking for the first function that
claims a match by returning a non-false result. It looked something like
this:

def match(arg, *functions):
for func in functions:
if func(arg):
return func

I wanted the function itself, not the result of calling the function. I
didn't care what the result was, only that it was something (indicates a
match) or nothing (no match). In one application, the functions might
return integers or floats; in another they might return strings. In a
third, they might return re match objects or None. I don't need to care,
because my code doesn't make any assumptions about the type of the result.

Couldn't you write the function to return None on no match, then test
if func(arg) is None? That way would seem a lot more natural to me.
As an added bonus, you don't have to return some sort of wrapped
object if suddenly you decide that you want to match a zero.

Sorry, can't give it credit for the use case I was asking for. I want
something where "if x" will do but a simple explicit test won't.


Carl Bannks
 
N

Nikolaus Rath

castironpi said:
There's a further advantage:

class A:
def get_auxclass( self, b, c ):
class B:
def auxmeth( self2, d, e ):
#here, ...
return B

In auxmeth, self would refer to the B instance. In get_auxclass, it
would refer to the A instance. If you wanted to access the A instance
in auxmeth, you'd have to use

class A:
def get_auxclass(b, c ):
a_inst = self
class B:
def auxmeth(d, e ):
self # the B instance
a_inst # the A instance
return B


This seems pretty natural to me (innermost scope takes precedence),
and AFAIR this is also how it is done in Java.


Best,

-Nikolaus

--
»It is not worth an intelligent man's time to be in the majority.
By definition, there are already enough people to do that.«
-J.H. Hardy

PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6 02CF A9AD B7F8 AE4E 425C
 
N

Nikolaus Rath

Michael Torrie said:
It (the entire first variable!) is needed because a method object is
constructed from a normal function object:

def method(self,a,b):
pass

class MyClass(object):
pass

MyClass.testmethod=method

That's precisely the same as if you'd defined method inside of the class
to begin with. A function becomes a method when the lookup procedure in
the instance object looks up the attribute and returns (from what I
understand) essentially a closure that binds the instance to the first
variable of the function. The result is known as a bound method, which
is a callable object:

<bound method MyClass.testmethod of <__main__.instance object at xxx>>


How would this work if there was not first parameter at all?

In short, unlike what most of the implicit self advocates are
saying, it's not just a simple change to the python parser to do
this. It would require a change in the interpreter itself and how it
deals with classes.


Thats true. But out of curiosity: why is changing the interpreter such
a bad thing? (If we suppose for now that the change itself is a good
idea).


Best,


-Nikolaus

--
»It is not worth an intelligent man's time to be in the majority.
By definition, there are already enough people to do that.«
-J.H. Hardy

PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6 02CF A9AD B7F8 AE4E 425C
 
N

Nikolaus Rath

Michael Torrie said:
I think the biggest reason why an implicit self is bad is because it
prevents monkey-patching of existing class objects. Right now I can add
a new method to any existing class just with a simple attribute like so
(adding a new function to an existing instance object isn't so simple,
but ah well):

def a(self, x, y):
self.x = x
self.y = y

class Test(object):
pass

Test.setxy = a

b = Test()

b.setxy(4,4)

print b.x, b.y

If self was implicit, none of this would work.

No, but it could work like this:

def a(x, y):
self.x = x
self.y = y

class Test(object):
pass

Test.setxy = a
b = Test()

# Still all the same until here

# Since setxy is called as an instance method, it automatically
# gets a 'self' variable and everything works nicely
b.setxy(4,4)

# This throws an exception, since self is undefined
a(4,4)


Best,

-Nikolaus

--
»It is not worth an intelligent man's time to be in the majority.
By definition, there are already enough people to do that.«
-J.H. Hardy

PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6 02CF A9AD B7F8 AE4E 425C
 
N

Nikolaus Rath

Bruno Desthuilliers said:
The fact that a function is defined within a class statement doesn't
imply any "magic", it just creates a function object, bind it to a
name, and make that object an attribute of the class. You have the
very same result by defining the function outside the class statement
and binding it within the class statement, by defining the function
outside the class and binding it to the class outside the class
statement, by binding the name to a lambda within the class statement
etc...

But why can't the current procedure to resolve method calls be changed
to automatically define a 'self' variable in the scope of the called
function, instead of binding its first argument?


Best,

-Nikolaus

--
»It is not worth an intelligent man's time to be in the majority.
By definition, there are already enough people to do that.«
-J.H. Hardy

PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6 02CF A9AD B7F8 AE4E 425C
 
N

Nikolaus Rath

Russ P. said:
The issue here has nothing to do with the inner workings of the Python
interpreter. The issue is whether an arbitrary name such as "self"
needs to be supplied by the programmer.

All I am suggesting is that the programmer have the option of
replacing "self.member" with simply ".member", since the word "self"
is arbitrary and unnecessary. Otherwise, everything would work
*EXACTLY* the same as it does now. This would be a shallow syntactical
change with no effect on the inner workings of Python, but it could
significantly unclutter code in many instances.

The fact that you seem to think it would change the inner
functioning of Python just shows that you don't understand the
proposal.


So how would you translate this into a Python with implicit self, but
without changing the procedure for method resolution?

def will_be_a_method(self, a)
# Do something with self and a

class A:
pass

a = A()
a.method = will_be_a_method


It won't work unless you change the interpreter to magically insert a
'self' variable into the scope of a function when it is called as a
method.

I'm not saying that that's a bad thing, but it certainly requires some
changes to Python's internals.


Best,

-Nikolaus

--
»It is not worth an intelligent man's time to be in the majority.
By definition, there are already enough people to do that.«
-J.H. Hardy

PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6 02CF A9AD B7F8 AE4E 425C
 
S

s0suk3

In message






Reread what the OP said.

Stop quoting only portions of my posts that lead to misinterpretation
of them. Next time you quote, be sure to quote this (which I also
mentioned in the previous post):

What the OP complains about has no relevance on what makes a language
OO or not.

Do you believe otherwise?
 
M

Michael Torrie

Nikolaus said:
No, but it could work like this:

def a(x, y):
self.x = x
self.y = y

Frankly this would make reading and debugging the code by a third party
to be a nightmare. Rather than calling the variable self as I did in my
example, I could it in a much better way:

def method(my_object, a, b):
my_object.a = a
my_object.b = b


Now if I saw this function standalone, I'd immediately know what it was
doing. In fact, I can even unit test this function by itself, without
even having to know that later on it's monkey-patched into an existing
class.

With your idea, I might get the picture this function should be used as
a method in some object because of the self reference, but I can't test
the method by itself. Trying to call it would instantly result in an
exception. And if this was a large function, I might not even see the
self reference right away.
 
M

Michael Torrie

Nikolaus said:
Thats true. But out of curiosity: why is changing the interpreter such
a bad thing? (If we suppose for now that the change itself is a good
idea).

Round and round and round we go.

Because by doing as you suggest you'd be altering the internal
consistency of how python deals with objects, particularly function
objects. By keeping all functions as function objects, we're able to
provide a consistent view of things both to the programmer and the
interpreter. If we break this consistency then we're saying, well this
is always a function, except in this case, and except in this case, when
it's dealt with specially. This does not fit at all with python's
established mantras.

In python, "def" does only one thing: it creates a function object and
binds it to a name. That's it! Making what def does context-sensitive
seems pretty silly to me, and without any real benefit. As said before,
adding attributes after the fact that are functions is a chore, because
those functions can't be unit tested, and can't be clearly read and
understood by other programmers.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,149
Latest member
Vinay Kumar Nevatia0
Top