The Artima Developer Community
Sponsored Link

Weblogs Forum
Self in the Argument List: Redundant is not Explicit

43 replies on 3 pages. Most recent reply: Nov 30, 2011 2:26 AM by ilian zapryanov

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 43 replies on 3 pages [ « | 1 2 3 ]
James Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: Self in the Argument List: Redundant is not Explicit Posted: Sep 26, 2008 6:11 AM
Reply to this message Reply
Advertisement
Thanks Atilla and Kay for humoring me. I understand the issues much better now.

I have to ask though, are some of these things even useful? They seem accidental to me. Especially with regard to the 'surprise' behavior Atilla demonstrated above. How would I use this feature? What value does it provide?

Kay Schluehr

Posts: 302
Nickname: schluehk
Registered: Jan, 2005

Re: Self in the Argument List: Redundant is not Explicit Posted: Sep 27, 2008 2:53 AM
Reply to this message Reply
> Thanks Atilla and Kay for humoring me. I understand the
> issues much better now.
>
> I have to ask though, are some of these things even
> useful? They seem accidental to me. Especially with
> regard to the 'surprise' behavior Atilla demonstrated
> above. How would I use this feature? What value does it
> provide?

Metaprogramming, abstraction, reflection, adaption ...

There was a popular claim for a long time that OO was "bolted on" Python and 'self' was this visible bolt but I rather do think it's there for linking first class OO, higher order OO and the procedural/functional layer - with no extra syntax, just using a convention.

Untangling the levels can be confusing at times as we have seen here but I'm not sure this is entirely avoidable? The question "how would I design it myself when starting from scratch" is hard to answer because I don't think it's all just about syntax but about designing an object system and a metaobject system at the same time.

Maybe Michele Simionato [1] gets anywhere when he tries to approach Python from Scheme? I don't believe in cheap shots.

[1] http://www.artima.com/weblogs/viewpost.jsp?thread=238789

James Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: Self in the Argument List: Redundant is not Explicit Posted: Sep 27, 2008 10:57 AM
Reply to this message Reply
> > Thanks Atilla and Kay for humoring me. I understand
> the
> > issues much better now.
> >
> > I have to ask though, are some of these things even
> > useful? They seem accidental to me. Especially with
> > regard to the 'surprise' behavior Atilla demonstrated
> > above. How would I use this feature? What value does
> it
> > provide?
>
> Metaprogramming, abstraction, reflection, adaption ...

Maybe you think I mean the ability to pass the self instance explicitly. I understand how that is useful. I mean the specific case of assigning an unbound method of one type to an object of another the way it works in Python.

I don't see how having to pass an object of the type of the class where an unbound method was defined to that method from another object is useful for anything (see Atilla's first example in response to me.) Can you (or anyone) give a specific example where this feature is useful? I can see how it would be useful if it worked in the more intuitive (to me) way but this requirement (which seems illogical to me) makes it useless.

It seems to me that this makes it basically impossible to assign an unbound method to an object of another type in a way that is useful. Any code that would try to call that would have to know where it was defined and pass an object of that type to it. I'm having a hard time imagining a situation where this would work well with duck-typed calls.

It's clear that mistakes have been made in Python. There have been too many changes in direction to deny that. I see Python as being like a really nice old house. It's great but to really fix it up the right way, you'd have to rip it down to the studs and rerun all the wiring and plumbing.

Kay Schluehr

Posts: 302
Nickname: schluehk
Registered: Jan, 2005

Re: Self in the Argument List: Redundant is not Explicit Posted: Sep 27, 2008 11:56 AM
Reply to this message Reply
> I don't see how having to pass an object of the type of
> the class where an unbound method was defined to that
> method from another object is useful for anything (see
> Atilla's first example in response to me.)

The behaviour shown in Atilla's first example is a wart. I checked this out in Python 3.0 and there we have now a bound method and the exception is gone. Some python-dev guy ensured me that Python 3.0 is wart-free. So it is a rather definite assertion ;-)

Michele Simionato

Posts: 222
Nickname: micheles
Registered: Jun, 2008

Re: Self in the Argument List: Redundant is not Explicit Posted: Sep 28, 2008 10:24 PM
Reply to this message Reply
> Maybe Michele Simionato gets anywhere when he tries to
> approach Python from Scheme?

Uh? Actually I am trying to approach Scheme from Python,
not the other way around.
Anyway, to answer a question I was not asked, if I was free to rewrite the Python object system from scratch, probably I would keep the self and remove the methods: I would use a CLOS-like approach based on generic functions defined outside classes.

Jan Samohyl

Posts: 14
Nickname: asgard
Registered: Feb, 2008

I wonder why this bothers people so much Posted: Sep 28, 2008 11:24 PM
Reply to this message Reply
I wonder why this topic (self in argument list) bothers people so much. I think it's just a matter of habit and syntactical difference.

It is certainly not a typing problem - in my experience, you write "self." to access class attributes much more often. Unless of course, you are creating large bunch of useless getter/setter methods (which is IMHO a bad practice in Python, since in Python calls are expensive and cannot be inlined).

So, Bruce, if you are bothered with self in argument list, why are you not bothered with having to write self to class attributes more? I think we came around to your original problem - Python has just different syntax.

P.S. If I were in charge, I would make a new standard which would simply shorten "self" to "s", which is as reasonable as you may get. And backwards compatible too.

James Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: I wonder why this bothers people so much Posted: Sep 29, 2008 7:03 AM
Reply to this message Reply
> So, Bruce, if you are bothered with self in argument list,
> why are you not bothered with having to write self to
> class attributes more? I think we came around to your
> original problem - Python has just different syntax.

I think a lot of people are bothered by this because there is a disconnect between the number of arguments in the declaration and the number of arguments in the call.

It bothered me a little at first too. Maybe 'puzzled' is a better word for how I felt. Even though it's confusing, it also acts a bit like a lesson in OO. A lot of languages work this way under the hood but hide it from you. I think a lot of procedural developers would have an easier time making the transition to OO in Python because it's a little more transparent in this regard. So I guess I am saying I have mixed feelings about this. Overall, I find both having to declare self in the arguments and refer to it on access annoying when I am coding. I would prefer to have to explicitly reference things outside of the current scope instead. Python seems upside-down in this regard.

Will Pierce

Posts: 2
Nickname: willp
Registered: Jul, 2008

Re: I wonder why this bothers people so much Posted: Oct 1, 2008 6:04 PM
Reply to this message Reply
@J.Watson: I agree with your "mixed feelings" on this syntax, and think you've hit upon something important I'd like to underscore:

The particulars of the implementation of OOP methods are exposed, with self being explicitly received as a method parameter.

When you compare Perl's OOP to Python, the previous posters' references to currying make sense to me.

Because perl does not support bound-methods, there's two common ways to get around this limitation when you need to call an instance's method. One is to hang on to the function reference and the object and explicitly pass the instance reference ($self) as the first argument to the function reference ( $func_ref($obj_ref, @args); ). The second workaound is by using an anonymous subroutine reference as a closure that contains the instance object reference. For example:


# for object "$obj" with method "func"
$obj_bound_ref = sub { $obj->func(@_); };
# now you can call:
$obj_bound(42, "life");
# and it will invoke $obj->func(42, "life");


To me, that looks like currying in perl. I'm not saying this is good or bad or pretty, just showing the differences. (And how much we can appreciate bound-methods in Python.)

I think it does make a lot of sense to eliminate the mapping of obj.method(...) -> method(self, ...) and make "self" a keyword. I don't understand decorators (yet), as I'm returning to Python from 10 years away, and have a lot of catching up to do. So, I don't really understand what would prevent a language change that converted the explicit receipt of 'self' into an implicit receipt.

Are there other cases of this kind of pattern within python's history that we can learn from and follow, as a general form, or more self-consistent evolution? The only thing that comes to mind, for me, is the addition of yield() which changes a plain method into a generator.

Assuming yield() and generators are now well-loved, is there a lesson or pattern in there that we could follow?

What if instead of explicitly receiving the "self" reference as the first method parameter, what if instead we had to explicitly obtain the self reference?


class C(object):
def set_x(x):
s=self()
s.x = x

def get_x():
s=self()
return s.x


Now, I'm not particularly fond of this syntax, but it would move the "self" reference outside the method parameters... Maybe this would even help bypass the keyword issue, and perhaps the presence of a call to self() within a class method can deal with these decorator issues that I don't understand.

Obviously this would break all existing code, so that probably is enough reason to nix this suggestion. I'm just trying to toss some ideas around. Maybe this particular option doesn't actually boil down to anything different from jsut making 'self' a keyword, versus a function that only works in the context of an instance method.

What are some other ideas on how to pull 'self' out of the parameter list, in the most elegant and self-consistent (pythonic I suppose) way?

David Newton

Posts: 2
Nickname: davenewton
Registered: Dec, 2007

Re: Self in the Argument List: Redundant is not Explicit Posted: Oct 13, 2008 5:44 PM
Reply to this message Reply
The "self" thing is one of the few things in Python that drive me absolutely batshit crazy... It's petty, but yeesh... we all have our quirks, and this one has always rubbed me the wrong way.

Xan Gregg

Posts: 2
Nickname: xangregg
Registered: Dec, 2005

Re: Self in the Argument List: Redundant is not Explicit Posted: Oct 15, 2008 7:08 AM
Reply to this message Reply
Article: "why is implicit better than explicit when you define the method, but it's OK to be implicit when you call the method?"

Shouldn't that be "why is explicit better than implicit..."?

Guido van van Rossum

Posts: 359
Nickname: guido
Registered: Apr, 2003

Re: Self in the Argument List: Redundant is not Explicit Posted: Oct 26, 2008 10:54 AM
Reply to this message Reply
I have blogged a response: http://neopythonic.blogspot.com/2008/10/why-explicit-self-has-to-stay.html

Lennart Regebro

Posts: 5
Nickname: regebro
Registered: Feb, 2006

Re: Self in the Argument List: Redundant is not Explicit Posted: Oct 27, 2008 2:54 AM
Reply to this message Reply
> why is implicit better than explicit when
> you <em>define</em> the method, but it's OK to be implicit
> when you <em>call</em> the method?</p>

Que? Where is the implictness in that call? I don't get it. That's completely explicit. Yes, you do not specify which object shuld be passed in as the first parameter within the parenthisis, but before the method name. But obj.__class__.m2(obj) is silly, and you need to spcify the object twice, which is reduntant.

ian o

Posts: 8
Nickname: iano
Registered: Aug, 2007

Elegant Solution Posted: Oct 27, 2008 3:29 PM
Reply to this message Reply
The proposal to allow the syntax

class foo(object):
def foo.__init__():
.......


I feel is a really elegant solution. It requires only compiler revision to implement, but changes how the code feels. With this change, ommitting 'self' in the definition is just like omitting self in an assignment Generally when we write
a= 3
as opposed to
self.a=3
we immediately know the difference and it is something you simply dont forget.

Currently putting 'self' in the parameter list is something we DO forget. Partially because it doesnt appear in the call so it feels inconsistent. Defining the using

def self.bar()

makes the def MORE consistent with the call, as opposed to less consistent and i feel solves the whole issue elegantly. If the 1st parameter in the call is the object left of the "." then the same can be done in the definition

It also then follows that
def bar(....)

logically is a local method, not a property of the object

ilian zapryanov

Posts: 1
Nickname: heatblazer
Registered: Nov, 2011

Re: Self in the Argument List: Redundant is not Explicit Posted: Nov 30, 2011 2:26 AM
Reply to this message Reply
I am learning python for 1 week. I was trying to create a class Player(object) in which there are player creation function , player print stats, player attacks enemy and so and so... but I got so many strange issues with classes, this might be my little knowing the language or just it`s more complicated than it looks...You can review a simple prototype here
# for dices
from random import randint

class Player(object):
#player must have attribites:
#HP, ATK, DEF, SPD and S.Skill!
def __init__(self):
self.player={ "Name": " ",
"Class":" ",
"HP": 0,
"ATK":0,
"DEF":0,
"SPD":0,
"SKILL": " "} #container for the player

def class_atributes(self, HP, ATK, DEF, SPD, SKILL):
self.player["HP"] = randint(1,10)+HP # 5 for thieves, 10 for fighters, 15 for defenders
self.player["ATK"] = randint(1,6)+ATK #2 for thieves, 5 for fiighters, 3 for defenders
self.player["DEF"] = randint(1,6)+DEF #2 for thieves, 3 for fighters, 5 for defenders
self.player["SPD"] = randint(1,6)+SPD #6 for thieves 2 for fighters and defenders
self.player["SKILL"] = SKILL

def player_creation(self):
self.name = str(input("Enter your name: "))
self.class_p = str(input("Enter your class: "))
if self.class_p == "fighter":
self.player["Name"] = self.name
self.player["Class"] = self.class_p
self.class_atributes(10, 5,3,2,"Charge!")
elif self.class_p == "thief":
self.player["Name"] = self.name
self.player["Class"] = self.class_p
self.class_atributes(5, 2,2,6,"Critical!")
elif self.class_p == "defender":
self.player["Name"] = self.name
self.player["Class"] = self.class_p
self.class_atributes(15,3,5,2,"Counter!")
else:

print("Unknown class! Please refer to:\nfighter, thief, defender\n")
return "player_creation"

def player_print(self):
print("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
print("Name: %s \t|Class: %s"%(self.player["Name"], self.player["Class"]))
print("HP :%r"%("#"*self.player["HP"]))
print("ATK:%r"%("#"*self.player["ATK"]))
print("DEF:%r"%("#"*self.player["DEF"]))
print("SPD:%r"%("#"*self.player["SPD"]))
print("SKILL:%s"%(self.player["SKILL"]))
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n")

def player_turn(self, player, enemy):
print("It`s %s turn. Take a wise action\n"%(self.player["Name"]))
self.action = str(input("(A)ttack, (S)pecial, (M)enu: "))
if self.action == 'a' or self.action == 'A':
self.attack = randint(1,6)+self.player["ATK"]
self.attack -= enemy.player["DEF"]
enemy.player["HP"] -= self.attack # damage enemy
return 0
elif self.action == 'm' or self.action == 'M':
self.player_print()
else:
print("Error usage, turn wasted... Be more wise")
return 0
def player_death(self, player, enemy):
print("""It was a gruesome battle.... but after hevy damages and deep wounds %s didn`t make it and fell under %s the cunning tactics and peerless skill"""%(self.player["Name"], enemy.player["Name"]))

def battle(self, enemy):
#init player speeds
self.p1turn = self.player["SPD"]
self.p2turn = enemy.player["SPD"]
while self.player["HP"] >=0 or enemy.player["HP"] >=0:
self.p1turn += self.player["SPD"]
self.p2turn += enemy.player["SPD"]
if self.p1turn >= 100:
self.p1turn = self.player_turn(player,enemy)
if self.p2turn >= 100:








############################################################################# ##############################

p1 = Player()
p2 = Player()
p3 = Player()
p1.player_creation()
p2.player_creation()
p1.player_print()
p2.player_ print()
p1.battle(p2)

Flat View: This topic has 43 replies on 3 pages [ « | 1  2  3 ]
Topic: Some Insights From Europe Previous Topic   Next Topic Topic:

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use