[Python-Dev] Draft proposal: Implicit self in Python 3.0
Alexander Kozlovsky
alexander.kozlovsky at gmail.com
Fri Jan 6 21:26:55 CET 2006
Hello!
Ian Bicking wrote:
> (As an aside directed at the original PEP, I think discussion of leaving
> self out of expressions, e.g., ".x" for "self.x", should be separate
> from the rest of this PEP).
Yes, I'm fully agree.
Nick Coghlan wrote:
> The main concern I have is with the answer to the question "How many
> positional arguments does the function have if I retrieve it from the class,
> rather than from an instance?" (this is the common concern for almost all
> proposals to remove the explicit self and class_ slots).
In this case, the function always (!!!) has fixed number of
positional arguments equal to number of positional parameters
inside the function definition:
>>> def func(a, b):
... print class, self, a, b
...
>>> class Foo:
... bar = func
...
>>> instance = Foo()
>>> func(1, 2) # there are 2 arguments
None None 1 2 # <- class and self both equal to None
>>> Foo.bar(1, 2) # 2 arguments again!!
<class Foo> None 1 2 # <- self is equal to None
>>> instance.bar(1, 2) # 2 arguments always!!!
<class Foo> <Foo object at 0x016434F0> 1 2
Nick Coghlan wrote:
> To sum the proposal up in my own words:
> Eliminate the need for explicit class and self slots in class
> and instance methods by implicitly providing those slots on all
> functions.
Yes, I think, it is what I mean.
With my proposal, 'self' is no longer the first explicit or implicit
positional argument (!), instead, it is 'pseudo-argument', the value
of which is equal to function's 'im_self' attribute. Any function
contains two special read-only attributes: 'im_class' and 'im_self',
and values of this attributes are accessible inside function body
as values of 'class' and 'self' pseudo-arguments.
Any function has this attributes, for ordinary function their values
are set to 'None'. Example:
>>> # Python 3.0
>>> def f(): return class, self
>>> f()
(None, None)
There is new built-in function:
bind(old_function, self_, class_=None) -> new_function
The result is the new function with the same code object which the
old function had, but with different im_class and im_self attributes
values.
- If both self_ and class_ arguments are None, then 'im_class' and
'im_self' attributes of new function is set to equal to None.
- If self_ is not None, then class_ must be None or self_.__class__.
'im_self' attribute of new function is set to self_, and im_class
attribute is set to self_.__class__
- If self_ is None but class_ is not None, then 'im_self' attribute
is set to None, and 'im_class' attribute is set to class_
Consider this expression (extraction of a method from a class):
x = Foo.bar
This expression is equivalent of:
x = bind(Foo.__dict__["bar"], None, Foo)
After this, x.im_class is Foo and x.im_self is None
The type.__getattribute__ contains implementation of this
Consider next expression (extraction of a method from an instance):
y = instance.bar
This expression is equivalent of:
y = bind(instance.__class__.__dict__["bar"], instance)
After this, y.im_class is instance.__class__ and y.im_self is instance.
The object.__getattribute__ is responsible for this
Ian Bicking wrote:
> Well... it becomes more complex for decorators, I guess:
>
> def printargs(func):
> def replacement(*args, **kw):
> print args, kw
> return func(*args, **kw)
> return replacement
> class Foo:
> @printargs
> def null(a): pass
>
> What is printargs going to print? Will it even work? I'd guess you'd
> have to do:
>
> def printargs(func):
> def replacement(*args, **kw):
> print args, kw
> return bind(func, self)(*args, **kw)
> return replacement
I think, it should be:
def printargs(func):
def replacement(*args, **kw):
print args, kw
return bind(func, self, class)(*args, **kw)
return replacement
Yep, the code in decorators will be more complicated than it is today.
I did not get it before...
> I guess it depends on what bind(func, self) does outside of
> a method invocation. I think self should be undefined in that case.
'self' will be None in that case. Any function has 'self' pseudo-argument,
but in a plain function (not a method) 'self' and 'class' both equal
to None.
--
Best regards,
Alexander mailto:alexander.kozlovsky at gmail.com
More information about the Python-Dev
mailing list