Hello! I have some proposal for Python 3.0 (interesting one, from my point of view). I'm sorry for my English, it is not very good.
Abstract ======== There are three different peculiarity in Python 2.x in respect of 'self' method argument: 1. Each method must have explicit 'self' argument in its argument list 2. This argument must be used explicitly for instance's attribute value assignment 3. The count of explicit arguments in method definition differs from count of explicit parameters when method is called Example 1 (Python 2.x): ----------------------- class Foo: def __init__(self, x): # 1: Explicit 'self' argument self.x = x # 2: 'self' must be used explicitly def bar(self, a, b): # 3: There are three arguments... print self.x + a + b Foo(10).bar(20, 30) # ...but only two explicit parameters # is presented This document proposes to change this, as the next example shows: Example 2 (Python 3.0): ----------------------- class Foo: def __init__(x): # 1: Implicit self .x = x # 2: Brief form of: self.x = x def bar(a, b): # 3: Two arguments... print .x + a + b Foo(10).bar(20, 30) # ...and exactly two parameters According Python Zen, "Explicit is better then implicit", but "practicality beats purity" and "Readability counts" ;-) This draft document describes high-level semantic of proposed changes and doesn't discuss details of C implementation. Rationale ========= When programmer tries to pick up some new programming language from different possibilities (e.g. Smalltalk, Python, Perl, ...), he often bases his choice on secondary and non-essential details. Almost any language has peculiarities, which can distract potential users from language evaluation. Examples of such warts may be [EMAIL PROTECTED]&% perlish syntax in Ruby, abundance of parenthesis in Lisp and Schema, and explicit 'self' argument in Python. Of course, from technical point of view, such peculiarities are completely non-issue. Parenthesis is not problem in Lisp if you use a good text editor, perlisms in Ruby can be avoided, etc. But from sociological and usability points of view, such warts can cause remarkable hurt, because they affect first impression about language. In many superficial language comparisons Python's OO approach dismissed as after-thought because of the explicit 'self'. Example: But the most important aspect, why I am using Ruby instead of Python or Perl are the object-orientated features of Ruby, and that Ruby was designed object-oriented right from beginning, unlike Python and Perl where object-orientation was added on later. You can recognize this in e.g. in Python very good, because the first parameter (often named self) of every method of a class is the object on which the method is called (http://www.ntecs.de/old-hp/s-direktnet/rb/ruby.pdf) Of course, this words about Python are not true. Python was object-oriented from the beginning, and explicit 'self' is intentional design decision, which is elegant in some aspects. But from pragmatical point of view, implicit 'self' in Python 3.0 may lower entry barrier for many people and assist Python's wide adoption. The proposed change is not backward-compatible with Python 2.x Detailed proposals ================== 1. 'self' becomes a keyword, and may be used inside function definition to denote a special implicit function argument 2. New syntax shortcut is introduced: '.attr' inside a function is exact equivalent to 'self.attr'. Full syntax can be used as well 3. 'class' keyword can be used in two different syntactical construction: a) If 'class' keyword immediately followed by identifier, then it is usual class definition. b) In all other cases (inside a function) 'class' keyword denotes value of implicit function argument >>> # in Python 3.0: >>> def sample(a, b): ... class C: pass # ordinary class definition ... print class.__name__ # 'class' is implicit argument ... 4. Each function (not only class methods) accepts two implicit arguments, 'class' and 'self'. With ordinary function call, this arguments has 'None' value >>> def f(a, b): ... return [class, self, a, b] ... >>> f(1, 2) [None, None, 1, 2] Implicit 'class' and 'self' attributes don't participates in partial function application 5. Each function have two constant attributes, __class__ and __self__, both of them have value 'None' >>> f.__class__, f.__self__ (None, None) 6. New builtin function bind(func, self_, [class_]) is introduced. The result is a new function with the same name, __self__ and __class__ attributes of which are equal to self_ and class_, correspondly. If bind function is called without class_ argument, then __class__ value in new function remains the same as in previous ones. >>> f <function f[None, None] at 0x01636F30> >>> g = bind(f, 'foo', 'bar') >>> g <function f['foo', 'bar'] at 0x01640770> >>> g.__class__, g.__self__ ('bar', 'foo') When function is called, its __class__ and __self__ attributes are accessible inside function body as 'class' and 'self': >>> g(10, 20) ['foo', 'bar', 10, 20] Once bounded function can be rebinded easily: >>> bind(g, 100, 200) <function f[100, 200] at 0x0165CAB0> 7. In process of function extraction from class or instance dictionary it became bound automatically (the machinery is in object.__getattribute__ and type.__getattribute__ methods): >>> def func(a, b): ... return [class, self, a, b] ... >>> def Class: ... func = func ... >>> instance = Class() >>> func(10, 20) [None, None, 10, 20] >>> Class.func(10, 20) [<class '__main__.Class'>, None, 10, 20] >>> instance.func(10, 20) [<class '__main__.Class'>, <__main__.Class object at 0x016434F0>, 10, 20] More examples with metaclasses: >>> def func(a, b): ... return [class, self, a, b] ... >>> class Meta(type): ... func = func ... >>> class Class: ... __metaclass__ = Meta ... >>> instance = Class() >>> func(10, 20) [None, None, 10, 20] >>> Meta.func(10, 20) [<class '__main__.Meta'>, None, 10, 20] >>> Class.func(10, 20) [<class '__main__.Meta'>, <class '__main__.Class'>, 10, 20] >>> instance.func(10, 20) Traceback (most recent call last): ... AttributeError: 'Class' object has no attribute 'func' 9. Methods can be overloaded this way: >>> class MyList(list): ... def __getitem__(key): ... print "overloaded method!" ... return super(MyList, self).__getitem__(key) ... def __setitem__(key, value): ... print "overloaded without super" ... bind(list.__setitem__, self)(key, value) ... 10. It is interesting that with this semantics there are no need in @classmethod and @staticmethod decorators: - If you want to create class method, simply don't use 'self' argument - If you want to create static method, don't use 'class' and 'self' argument >>> class Example: ... class_var = 100 ... def my_class_method(): # no need for @classmethod ... class.class_var += 1 ... def my_static_method(): # no need for @staticmethod ... print "hello!" ... def usual_method(): ... print .name ... What do you think about this? Best regards, Alexander mailto:[EMAIL PROTECTED] _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com