[Python-ideas] type/instance method syntax

spir denis.spir at free.fr
Sun Nov 2 15:40:06 CET 2008


Below a more compact reformulation and a different point of view on the same topic.

=== Summary ===

-0- Inside a type definition are decribed both the type and its potential 
instances; a syntactic rule is thus needed to distinguish type and instance 
attributes.
-1- A pattern is used to address that point: namely, the rule is to prefix 
instance attributes with an instance 'pseudonyme', for example "self.a" or 
"self.f(x)". Which is /very/ good: the pseudonyme simply takes the place of a 
not-yet-existing-object-name. Right? This pattern is consistent with overall 
python & OOP syntax, close to 'natural', used both for non-callable attributes 
and methods; except...
-2- For method definition, the following pattern is used: "def f(self,x)"; 
where "def self.f(x)" would be expected instead, accordind to -1-. Problem #1: 
as a simple pattern is broken, the code's clarity/legibility is suffers. Is 
there any advantage to balance that? Note: as the regular pattern does not seem 
to conflict with any other syntactic feature, can we consider allowing it?
-3- As a rather unfortunate side-effect, it happens that the pattern used to 
define instance methods is precisely the one that could be used for type 
methods. Problem #2:  how do we define them, then? The builtin instancemethod() 
introduced in python 2.2 is needed only because of this irregularity (**)(***). 
See below under "proposal" for alternatives.

(*) This does not apply when attributes are adressed from outside the type's 
scope, where ordinary object-name prefixing has to be used, as well as inside 
methods for type attributes.
(**) This applies, of course, to @classmethod.
(***) @staticmethod/staticmethod() instead really introduces a new kind of 
object. As a syntactic feature, its sense is to let python 'know' it. From PEP 
318: "[Decorators] are storing additional information on a function object." 
What is the additional information for a type method? A syntax notation 
conflict with instance methods. A type method is an ordinary method that we 
simply could not write down before.
PEP 318: Decorators for Functions and Methods 
http://www.python.org/doc/2.4.4/whatsnew/node6.html

=== alternative approach ===

In http://www.python.org/dev/peps/pep-0318/, decorators are also called 
'transformators': they return a transformed version of the argument. Decorators 
can be built-in or user-defined. They allow special versions of a main type of 
objects -- presently functions or methods. This is in a way similar to sub-typing:
method
     standard/default
     static
     further built-in sub-type
     user-defined sub-type
In the case of the standard sub-type, the @standard decorator would be the 
(mathematical) identity function that returns its parameter unchanged. Which is 
pointless, needs not beeing implemented, so that the standard sub-type is the 
default one, i.e. identical to the super-type. Right?
An ordinary type method is a method of the standard type. There needs no 
decorator for it. As types are object, they can hold methods (even functions 
can...).  We may consider type methods as special because, due to the syntactic 
conflict described above, there was previously no way to express them. 
Additionally, as classes are mainly regarded as 'real' object generators, they 
are rather seen as static, so that class methods do not belong to everyday 
programming. Still, type methods are standard objects: their syntax should be 
standard.

Denis

PS: Do you know about a site, list, forum about programming language design?
(Answer in private message, please.)


Hello,

[New to the list. I spent some time exploring the archives, still I'm not 
really sure of what kind of subjects fit here -- or not. If ever this post, or 
a further one, is out of topic, just tell me.
Also, I'm a self-trained amateur, and neither python nore english is my native 
language, thus I may use non-standard idioms. ;-)]

-1- real-life case (can safely be skipped)

I'm writing an application that should allow a user to chose between several 
wiki languages, including customized versions, on one side; and uses either a 
subset of xhtml, or simple plain text tables (simulation of DB import/export), 
as saving/exchange/standard format.
To do this, I have a whole lot of configurable "Symbol" sub-types, each 
representing a common language feature. (I imagine there are tons of more 
professional approaches, but this is not my point -- I do it for pleasure.) A 
list of symbols (instances), parsed from a source text, build an abstract, 
language-independant, image of the text. The types have to take the (wiki-side) 
configuration into account; I also wish this config to be "switchable" at 
run-time. An example use of this feature is to "transcode" a wiki source text 
into another wiki format.
The pattern of a symbol type is then:

class BlockFormat(Symbol):
     def config():
         <set type attributes>
     def __init__(self, source, ...):
         <read instance attributes from source doc>
     <read/write methods from/into known languages>

I /really/ expected this to work. config() obviously was, for me, a type/class 
method. I intended to call it and its sisters from a module top-level function:
def config():
     wiki_config.build(config_file_name)
     for symbol_type in symbol_types:
         symbol_type.config()

As a consequence, I happily discovered both classmethod() and 
@classmethod.(Actually, I hadn't programmed for a long time, had forgotten some 
idiomatic "details", and knew about nothing of python >= 2.0, except for the 
overall new_style_classes pattern.)

-2- type/instance attribute pattern

(Below is called 'property' a non-callable object attribute, as opposed to 
'method'. I do not know if a better, standard, term is used in the python 
community.)

                 type/class          instance
property        prop                self.prop
method call     f(args)             self.f(args)
method def      def f(args)+X       def f(self,args)

(where X means either classmethod() or @classmethod)

I wondered where the point is before writing down this table. Why (1) I 
intended my code to work as is (2) we need to add a line of code to define a 
class method.
In order to distinguish an instance property from a type one, the former is 
simply prefixed with 'self' -- or any placeholder for a potential instance name 
--, later with the actual instance's name. This pattern fully applies to method 
call. But is broken for method definition, for any reason I'm unable to guess. 
I think this explains why I wrote the code above.
Now, watching such a table, the additional instruction looks to my eyes like a 
workaround rather than a feature. Actually, the instance method definition 
syntax takes the place of
the one that may be expected for class methods instead. Lets imagine this 
slight change:

                 type/class          instance
property        prop                self.prop
method call     f(args)             self.f(args)
method def      def f(args)         def self.f(args)       <==

Doesn't this deliciously fit in the table? Not only the syntax for instance 
method definition matches the call syntax; but also the whole method pattern 
matches the one for properties.

-3- proposal(s)

I am fully conscious that this syntax cannot be introduced: this would have as 
magic side-effect to transform all instance methods into class methods ;-)

I wonder if the following may be considered: Allow prefixing of class 
attributes (esp. methods) with the classe's name -- even in the classe's own scope:
class C(object):
     C.a = 1
     def C.f():
         <method body>
This syntax presently launches NameError and SyntaxError, which is correct as C 
is not yet defined, and the second syntax is unknown. But... it would allow a 
nicer syntax to define class method, and more: this syntax is precisely the one 
that will later be used to call the method.

An alternative may be to prefix a class method defintition with either 'type' 
or 'class', used as a pseudo keyword:
class C(object):
     def type.f():
         <method body>

Denis


spir a écrit :
> Hello,
> 
> [New to the list. I spent some time exploring the archives, still I'm 
> not really sure of what kind of subjects fit here -- or not. If ever 
> this post, or a further one, is out of topic, just tell me.
> Also, I'm a self-trained amateur, and neither python nore english is my 
> native language, thus I may use non-standard idioms. ;-)]
> 
> -1- real-life case (can safely be skipped)
> 
> I'm writing an application that should allow a user to chose between 
> several wiki languages, including customized versions, on one side; and 
> uses either a subset of xhtml, or simple plain text tables (simulation 
> of DB import/export), as saving/exchange/standard format.
> To do this, I have a whole lot of configurable "Symbol" sub-types, each 
> representing a common language feature. (I imagine there are tons of 
> more professional approaches, but this is not my point -- I do it for 
> pleasure.) A list of symbols (instances), parsed from a source text, 
> build an abstract, language-independant, image of the text. The types 
> have to take the (wiki-side) configuration into account; I also wish 
> this config to be "switchable" at run-time. An example use of this 
> feature is to "transcode" a wiki source text into another wiki format.
> The pattern of a symbol type is then:
> 
> class BlockFormat(Symbol):
>    def config():
>        <set type attributes>
>    def __init__(self, source, ...):
>        <read instance attributes from source doc>
>    <read/write methods from/into known languages>
> 
> I /really/ expected this to work. config() obviously was, for me, a 
> type/class method. I intended to call it and its sisters from a module 
> top-level function:
> def config():
>    wiki_config.build(config_file_name)
>    for symbol_type in symbol_types:
>        symbol_type.config()
> 
> As a consequence, I happily discovered both classmethod() and 
> @classmethod.(Actually, I hadn't programmed for a long time, had 
> forgotten some idiomatic "details", and knew about nothing of python >= 
> 2.0, except for the overall new_style_classes pattern.)
> 
> -2- type/instance attribute pattern
> 
> (Below is called 'property' a non-callable object attribute, as opposed 
> to 'method'. I do not know if a better, standard, term is used in the 
> python community.)
> 
>                type/class          instance
> property        prop                self.prop
> method call     f(args)             self.f(args)
> method def      def f(args)+X       def f(self,args)
> 
> (where X means either classmethod() or @classmethod)
> 
> I wondered where the point is before writing down this table. Why (1) I 
> intended my code to work as is (2) we need to add a line of code to 
> define a class method.
> In order to distinguish an instance property from a type one, the former 
> is simply prefixed with 'self' -- or any placeholder for a potential 
> instance name --, later with the actual instance's name. This pattern 
> fully applies to method call. But is broken for method definition, for 
> any reason I'm unable to guess. I think this explains why I wrote the 
> code above.
> Now, watching such a table, the additional instruction looks to my eyes 
> like a workaround rather than a feature. Actually, the instance method 
> definition syntax takes the place of
> the one that may be expected for class methods instead. Lets imagine 
> this slight change:
> 
>                type/class          instance
> property        prop                self.prop
> method call     f(args)             self.f(args)
> method def      def f(args)         def self.f(args)       <==
> 
> Doesn't this deliciously fit in the table? Not only the syntax for 
> instance method definition matches the call syntax; but also the whole 
> method pattern matches the one for properties.
> 
> -3- proposal
> 
> I am fully conscious that this syntax cannot be introduced: this would 
> have as magic side-effect to transform all instance methods into class 
> methods ;-)
> 
> I wonder if the following may be considered: Allow prefixing of class 
> attributes (esp. methods) with the classe's name -- even in the classe's 
> own scope:
> class C(object):
>    C.a = 1
>    def C.f():
>        <method body>
> This syntax presently launches NameError and SyntaxError, which is 
> correct as C is not yet defined, and the second syntax is unknown. 
> But... it would allow a nicer syntax to define class method, and more: 
> this syntax is precisely the one that will later be used to call the 
> method.
> 
> An alternative may be to prefix a class method defintition with either 
> 'type' or 'class', used as a pseudo keyword:
> class C(object):
>    def type.f():
>        <method body>
> 
> Denis
> 
> 
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> http://mail.python.org/mailman/listinfo/python-ideas
> 
> 





More information about the Python-ideas mailing list