Why the 'self' argument?

  • Thread starter Grzegorz Staniak
  • Start date
J

John Roth

Harri Pesonen said:
John said:
Thanks guys, I hadn't heard of __slots__ before. Perhaps I am reading a
too old book. Of course, a compile time check would be better...

__slots__ came in with 2.2 new style classes, and it's definitely
an advanced feature. There's also some thought that it may not
be the best way to do the job.
I think that Python already has run time type checking. It does not
allow "a" + 1, for example.

Actually, it doesn't. It has run time strong typing, which is a different
thing.

To me, at least, "type checking" implies a meta-operation, that is,
something that is outside of the operation itself insuring that the correct
types are used. In languages with static typing, that something is the
compiler.

Runtime type checking means that there is additional code somewhere
that checks that the object you are trying to bind is of an allowable
type; that code is basically supervisory in nature.
It would be quite simple to have "option explicit" like in Visual Basic,
I believe. Like the following:

option explicit
var a = "asdf"
b = 1 # error at compile time
a = 123
(var b, var c, var d) = (1, 2, 3)
e = "asdf" # error at compile time

Things are not so simple. To do compile time type
checking, the compiler has to know the actual type
of the result of the expressions on the right hand side
of the assignments. In a dynamic language like Python,
that's not possible without very fundamental changes
to the nature of the language.

It's not a simple thing to do, and the fact that ML
family languages manage to do it without having
to have explicit type declarations (well, most of the
time anyway) is a major achievement, IMO.

The fact that Bicycle Repair Man manages to do it
as well as it does for Python is an even more
impressive achievement.

John Roth
 
T

Terry Reedy

John Roth said:
It's not a simple thing to do, and the fact that ML
family languages manage to do it without having
to have explicit type declarations (well, most of the
time anyway) is a major achievement, IMO.

As I remember, part of the cost (for ML at least) is having separate
operators for ints and floats. Bye bye generic functions. I don't
remember if there was any escape from the type straightjacket (like
#define max(a,b) ... in C). And one has to adjust to and feel
comfortable enough with the view that multiparam functions are a
composition of single param functions. But I agree that the type
inferencing is an interesting achievement.

Terry J. Reedy
 
J

John Roth

Terry Reedy said:
As I remember, part of the cost (for ML at least) is having separate
operators for ints and floats.

As well as separate operators for a number of other things. This
isn't unique to ML, though. For other reasons, Perl has a seperate
set of operators for string versus numeric comparisons, and even
Python has separate operators for division.
Bye bye generic functions.

Actually, they seem to be able to have generic functions, at least
in some restricted cases.
I don't
remember if there was any escape from the type straightjacket (like
#define max(a,b) ... in C). And one has to adjust to and feel
comfortable enough with the view that multiparam functions are a
composition of single param functions.

I'm not sure how central currying is to the type inference
mechanism.
But I agree that the type
inferencing is an interesting achievement.

Yes, it is. That is, I think, my point. If we want to have some
form of static typing and still keep Python reasonably close to the
streamlined language we all know and love, this seems like an
interesting research direction.

John Roth
 
H

Harri Pesonen

John said:
Things are not so simple. To do compile time type
checking, the compiler has to know the actual type
of the result of the expressions on the right hand side
of the assignments. In a dynamic language like Python,
that's not possible without very fundamental changes
to the nature of the language.

In fact I didn't mean *type* checking above but checking that the
variable has been declared. Adding "option explicit" would not be so
hard, I believe.

Then you could have (to almost get back to the subject):

class A:
var a # declare member variables
def __init__(self, a): # should be __init__(a) :)
self.a = a # OK because a has been defined

a1 = A("test")
a1.a # OK
a1.b = 1 # error at compile time

Type checking could be an extension to the above...

var a as str

Harri
 
T

Terry Reedy

John Roth said:
I'm not sure how central currying is to the type inference
mechanism.

Completely central in that the type of functions *is* a curried type
(in the *MLs I have looked at). For instance, the type of a binary
int function is displayed something like:

func(int)==>func(int)==>int

with ==> associative right to left. The type of f(i,j)=>int is 'a
function (of i) returning [a function (of j) returning an int]'. As I
said, takes some adjustment for most. But occasional mental exercise
like this is probably good for the brain.

Terry J. Reedy
 
B

Bengt Richter

To sum up what I've learnt here and from the FAQ: 'self' could actually be
any string (it is 'self' by convention), as its role is only to serve as
the first argument of methods in order to facilitate the process of
associating method calls with their context. It would be possible (even if
not obviously desirable) to implement method definitions in such a way
as to avoid the first argument completely, i.e.

def something():
...

so actually it's just a question of implementation. Having little
experience with object-oriented programming, I won't try to relate to
pro and contra arguments that have been given in the discussion, I just
have one more question: isn't it a little superfulous to have to use the
'classmethod()' builtin to declare class methods? I'd think giving a
class object name as the first argument should suffice?
I think you may have misunderstood classmethod. Rebinding a class attribute
with the result of classmethod makes a method that
works differently from an ordinary method. It means that the class itself will
be bound to the first argument, even if the method is called as an attribute
of an instance of the class. E.g.,
... def cm(*args): return args
... cm = classmethod(cm)
... def m(*args): return args
... (<__main__.B object at 0x008F9690>,)

and note:
(<class '__main__.B'>,)

but: Traceback (most recent call last):
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: unbound method m() must be called with B instance as first argument (got nothing instead)

also, you don't have to do it inside the class definition, and it's not about a specific
attribute name -- i.e. you don't have to write xxx = classmethod(xxx) as is conventional,
unless the following is fooling me.
(<__main__.C object at 0x00902170>,)

Of course the result is not *identical*, since you can see the original function name
(note that you get a *bound* method either way with a classmethod, vs the ordinary C.m/c.m)
<bound method C.m of <__main__.C object at 0x00902170>>

Regards,
Bengt Richter
 

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,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top