Re: About __class__ of an int literal

Discussion in 'Python' started by MRAB, Sep 29, 2010.

  1. MRAB

    MRAB Guest

    On 29/09/2010 01:19, Terry Reedy wrote:
    > On 9/28/2010 5:27 AM, AlexWalk wrote:
    >> In python 3.1.2(I'm using windows edition, 32bit), accessing __class__
    >> of an int literal will raise a SyntaxException, while other literals
    >> will not. For example. 1.__class__ is an error, while 1.1.__class__ runs
    >> ok.

    >
    > Third solution:
    > >>> type(0) is 0 .__class__

    > True
    >
    > A person using instances of a class should seldom use special names
    > directly. They are, in a sense, implementation details, even if documented.
    > The idiom "if __name__ == '__main__':" is an exception.
    >

    __file__ is another exception.
     
    MRAB, Sep 29, 2010
    #1
    1. Advertising

  2. On Wed, 29 Sep 2010 02:20:55 +0100, MRAB wrote:

    > On 29/09/2010 01:19, Terry Reedy wrote:


    >> A person using instances of a class should seldom use special names
    >> directly. They are, in a sense, implementation details, even if
    >> documented. The idiom "if __name__ == '__main__':" is an exception.
    >>

    > __file__ is another exception.



    As are __iter__, __next__, __add__, __dict__, and, yes, __class__, to say
    nothing of all the other special methods.

    I'm afraid that I have to disagree with Terry here. Double-underscore
    special variables don't start with double underscores because they're
    implementation details, or to indicate that they're private. They are
    reserved names for attributes or methods that have special meaning to
    Python.

    An implementation that didn't use __dict__ for the namespace of an
    ordinary class, or didn't call __add__ for the + operator, would be
    considered to be buggy.

    Naturally one has to be careful about the assumptions you make with such
    special methods. You shouldn't assume, for example, that all classes will
    have a __dict__ attribute. If the class has __slots__ defined, it may
    not. But I think that it is safe to assume any object will have a
    __class__ attribute. At least, I'd report it as a bug if I found one that
    didn't.

    (This may change in the future. Given type(), and isinstance(), I'm not
    sure what value __class__ adds.)




    --
    Steven
     
    Steven D'Aprano, Sep 29, 2010
    #2
    1. Advertising

  3. Steven D'Aprano <> writes:

    > On Wed, 29 Sep 2010 02:20:55 +0100, MRAB wrote:
    >
    >> On 29/09/2010 01:19, Terry Reedy wrote:

    >
    >>> A person using instances of a class should seldom use special names
    >>> directly. They are, in a sense, implementation details, even if
    >>> documented. The idiom "if __name__ == '__main__':" is an exception.
    >>>

    >> __file__ is another exception.

    >
    >
    > As are __iter__, __next__, __add__, __dict__, and, yes, __class__, to
    > say nothing of all the other special methods.


    I think by "person using instances of a class" Terry referred to the
    user of a class as opposed to the implementor. In that sense the user
    should be calling iter(foo) instead of foo.__iter__(), next(foo) instead
    of foo.__next__(), and foo+bar instead of foo.__add__(bar). Direct
    calls to special-name methods, such as __len__, often indicate that the
    programmer hasn't grasped how those methods are intended to be used in
    Python.

    Obviously, none of this applies to __dict__, __class__, and friends, nor
    does it apply to cases where you know what you're doing, such as
    invoking __<method>__ of a superclass.

    > (This may change in the future. Given type(), and isinstance(), I'm not
    > sure what value __class__ adds.)


    None whatsoever. __class__ used to be necessary to tell the appart
    instances of different old-style classes:

    >>> class X: pass # old-style

    ....
    >>> X().__class__

    <class __main__.X at 0xb772f2fc>
    >>> type(X())

    <type 'instance'>

    Now that classes produce real types, they are equivalent.
     
    Hrvoje Niksic, Sep 29, 2010
    #3
  4. MRAB

    Terry Reedy Guest

    On 9/29/2010 8:34 AM, Hrvoje Niksic wrote:
    > Steven D'Aprano<> writes:
    >
    >> On Wed, 29 Sep 2010 02:20:55 +0100, MRAB wrote:
    >>
    >>> On 29/09/2010 01:19, Terry Reedy wrote:

    >>
    >>>> A person using instances of a class should seldom use special names
    >>>> directly. They are, in a sense, implementation details, even if
    >>>> documented. The idiom "if __name__ == '__main__':" is an exception.
    >>>>
    >>> __file__ is another exception.


    >> As are __iter__, __next__, __add__, __dict__, and, yes, __class__, to
    >> say nothing of all the other special methods.


    I strongly disagree.

    > I think by "person using instances of a class" Terry referred to the
    > user of a class as opposed to the implementor.


    Yes.

    > In that sense the user
    > should be calling iter(foo) instead of foo.__iter__(), next(foo) instead
    > of foo.__next__(), and foo+bar instead of foo.__add__(bar).


    Yes. Guido added iter() and next() to the list of built-in functions,
    even though they seem reduncant.. I believe it is his intention that the
    use of special names outside of class statements should be fairly rare.

    If I remember right, in the old, pre-2.2 system that separated built-in
    types and user-written classes, the builtins did not have accessible
    special method attributes. They are only for customizing user classes.
    So one could not have generically written foo.__add__(bar).
    Special-method attribute were added to builtins so that they could be
    inherited (or replaced) by user-written subclasses, not so that one
    could replace normal syntax.

    > Direct
    > calls to special-name methods, such as __len__, often indicate that the
    > programmer hasn't grasped how those methods are intended to be used in
    > Python.


    Right. That fact that *Python* interpreters implement syntax with
    special methods is an implementation detail of the *language*. The
    importance is that it allow *writers* of new classes to rather easily
    imitate built-in classes so that their classes seamlessly plug into the
    syntax.

    --
    Terry Jan Reedy
     
    Terry Reedy, Sep 29, 2010
    #4
  5. On Wed, 29 Sep 2010 14:46:18 -0400, Terry Reedy wrote:

    >> In that sense the user
    >> should be calling iter(foo) instead of foo.__iter__(), next(foo)
    >> instead of foo.__next__(), and foo+bar instead of foo.__add__(bar).

    >
    > Yes. Guido added iter() and next() to the list of built-in functions,
    > even though they seem reduncant.. I believe it is his intention that the
    > use of special names outside of class statements should be fairly rare.


    Fairly rare but not non-existent.

    For example, there's nothing wrong with using a callback function of
    (say) instance.__sub__ instead of lambda b, a=instance: a - b. Not only
    is the direct call to the method slightly faster, but more importantly
    it's easier to read and more clear to intent.

    Admittedly beginners may find instance.__sub__ to be a tad mysterious,
    but then beginners are likely to find the lambda form with its two
    arguments and default value mysterious too.



    > If I remember right, in the old, pre-2.2 system that separated built-in
    > types and user-written classes, the builtins did not have accessible
    > special method attributes.


    Yes, that's correct. But we're talking about Python *now*, not back in
    the mists of time before new-style classes. Would you argue that users
    shouldn't use decorators, iterators or closures because Python 2.1 didn't
    have them? I don't think so.


    > They are only for customizing user classes.


    Say "were" rather than "are" and I will agree with you.

    Say "primarily for" rather than "only" and I will also agree with you.


    > So one could not have generically written foo.__add__(bar).
    > Special-method attribute were added to builtins so that they could be
    > inherited (or replaced) by user-written subclasses, not so that one
    > could replace normal syntax.


    Of course one shouldn't prefer seq.__len__() over len(seq). But that's a
    readability issue, and not because Python implementations are free to
    change __len__ to something else.

    If I gave the opposite impression, that was not my intention and I'm
    sorry for the failure to be more clear.



    >> Direct
    >> calls to special-name methods, such as __len__, often indicate that the
    >> programmer hasn't grasped how those methods are intended to be used in
    >> Python.

    >
    > Right. That fact that *Python* interpreters implement syntax with
    > special methods is an implementation detail of the *language*. The
    > importance is that it allow *writers* of new classes to rather easily
    > imitate built-in classes so that their classes seamlessly plug into the
    > syntax.


    If I've understood this paragraph correctly, you're trying to say that
    since *other languages* that aren't Python are free to implement syntax
    features using some other mechanism, *Python* developers shouldn't use
    special methods because they are implementation details.

    If we're prohibited from using anything which is an implementation detail
    of "the *language*" (your emphasis), then we can't use *anything*. Yes,
    special methods are an implementation detail of Python, but only in the
    same sense that it is an implementation detail of Python that we write
    this:

    def f(a, b):
    x = a + b
    return math.sqrt(x)


    rather than this:

    function f(a, b: integer):float:
    var
    x: integer;
    begin
    x := a + b;
    f := sqrt(x)
    end;



    --
    Steven
     
    Steven D'Aprano, Sep 30, 2010
    #5
  6. On Wed, 29 Sep 2010 14:34:33 +0200, Hrvoje Niksic wrote:

    > Steven D'Aprano <> writes:
    >> (This may change in the future. Given type(), and isinstance(), I'm not
    >> sure what value __class__ adds.)

    >
    > None whatsoever. __class__ used to be necessary to tell the appart
    > instances of different old-style classes:
    >
    >>>> class X: pass # old-style

    > ...
    >>>> X().__class__

    > <class __main__.X at 0xb772f2fc>
    >>>> type(X())

    > <type 'instance'>
    >
    > Now that classes produce real types, they are equivalent.



    I've been thinking about this, and I think that there may be a use-case
    for changing __class__ manually. I'm not entirely sure if this is a good
    idea or not, I'd need to spend some time experimenting, but imagine a
    class that wraps another object and uses delegation instead of
    inheritance.

    If you also set __class__ (on the class itself, naturally, not the
    instance) appropriately, then type(instance) and instance.__class__ will
    be different. type() will return the "real" type of the delegation class,
    while instance.__class__ returns the class that it is trying to be.

    And of course, presumably metaclasses can do anything they like with
    __class__, for good or ill.

    I'm not sure if and when this would be useful, but it's a hint that
    perhaps the distinction is not entirely meaningless.



    --
    Steven
     
    Steven D'Aprano, Sep 30, 2010
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Schnoffos
    Replies:
    2
    Views:
    1,251
    Martien Verbruggen
    Jun 27, 2003
  2. Hal Styli
    Replies:
    14
    Views:
    1,709
    Old Wolf
    Jan 20, 2004
  3. arun
    Replies:
    8
    Views:
    481
    Dave Thompson
    Jul 31, 2006
  4. aling
    Replies:
    8
    Views:
    1,030
    Jim Langston
    Oct 20, 2005
  5. Anonieko Ramos

    What's wrong with rpc-literal? Why use doc-literal?

    Anonieko Ramos, Sep 27, 2004, in forum: ASP .Net Web Services
    Replies:
    0
    Views:
    407
    Anonieko Ramos
    Sep 27, 2004
Loading...

Share This Page