duck typing assertþ

Discussion in 'Python' started by Andriy Kornatskyy, Nov 8, 2012.

  1. People who come from strongly typed languages that offer interfaces often are confused by lack of one in Python. Python, being dynamic typing programming language, follows duck typing principal. It can as simple as this:
     
    assert looks(Foo).like(IFoo)
     
    The post below shows how programmer can assert duck typing between two Python classes:
     
    http://mindref.blogspot.com/2012/11/python-duck-typing-assert.html
     
    Comments or suggestions are welcome.
     
    Thanks.
     
    Andriy Kornatskyy
    Andriy Kornatskyy, Nov 8, 2012
    #1
    1. Advertising

  2. Re: duck typing assertâ€

    On Thu, 08 Nov 2012 20:34:58 +0300, Andriy Kornatskyy wrote:

    > People who come from strongly typed languages that offer interfaces
    > often are confused by lack of one in Python. Python, being dynamic
    > typing programming language, follows duck typing principal. It can as
    > simple as this:
    >  
    > assert looks(Foo).like(IFoo)


    How very cute. And I don't mean that in a good way.

    Why is this a class with a method, instead of a function that takes two
    class arguments (plus any optional arguments needed)?

    looks_like(Foo, IFoo)

    is less "cute", reads better to English speakers, and much more Pythonic.
    This isn't Java, not everything needs to be a class.


    > The post below shows how programmer can assert duck typing between two
    > Python classes:
    >  
    > http://mindref.blogspot.com/2012/11/python-duck-typing-assert.html


    I don't understand the emphasis on assert for this code. It is enough
    that looks() return a flag. The caller can then use that as an assertion:

    assert looks(Spam).like(Ham)

    or as a conditional:

    if looks(food).like(Meat):
    ...
    else:
    ...


    Assertions are only one use for this check, and in my opinion, the least
    useful one.

    And why the warnings? In my opinion, using the warning mechanism as a way
    to communicate the differences between the classes is an abuse of
    warnings: they're not *warnings*, they are *diagnostic information*.

    It is also fragile: the caller may have filtered warnings, and will not
    see the messages you generate.

    Lastly, I do not understand the purpose of this "wheezy.core" package.
    Does it have something to do with Ubuntu Wheezy? The documentation is
    unclear -- it refers to it as a "Python package" that "provides core
    features", but doesn't say what the purpose of the package is: core
    features of *what*? And the examples.rst file doesn't show any examples.

    https://bitbucket.org/akorn/wheezy.core/src/ca5b902e9605/doc/examples.rst


    --
    Steven
    Steven D'Aprano, Nov 8, 2012
    #2
    1. Advertising

  3. Andriy Kornatskyy

    Ian Kelly Guest

    Re: duck typing assert

    On Thu, Nov 8, 2012 at 4:33 PM, Steven D'Aprano
    <> wrote:
    > On Thu, 08 Nov 2012 20:34:58 +0300, Andriy Kornatskyy wrote:
    >
    >> People who come from strongly typed languages that offer interfaces
    >> often are confused by lack of one in Python. Python, being dynamic
    >> typing programming language, follows duck typing principal. It can as
    >> simple as this:
    >>
    >> assert looks(Foo).like(IFoo)

    >
    > How very cute. And I don't mean that in a good way.
    >
    > Why is this a class with a method, instead of a function that takes two
    > class arguments (plus any optional arguments needed)?
    >
    > looks_like(Foo, IFoo)
    >
    > is less "cute", reads better to English speakers, and much more Pythonic.
    > This isn't Java, not everything needs to be a class.


    I disagree. Does that test whether Foo looks like IFoo, or IFoo looks
    like Foo? Of course, given the naming convention and the example,
    it's easy to work out, but when you're trying to *write* that from
    memory, it could be a nuisance to remember the proper order. This is
    already a wart of isinstance and issubclass.

    looks(Foo).like(IFoo), on the other hand, is crystal clear about which
    argument is which.
    Ian Kelly, Nov 9, 2012
    #3
  4. Re: duck typing assert

    On Fri, Nov 9, 2012 at 12:00 PM, Ian Kelly <> wrote:
    > looks(Foo).like(IFoo), on the other hand, is crystal clear about which
    > argument is which.


    I'm not so sure that it is, tbh. If you read it like an English
    sentence, it's clearly testing whether Foo matches the template in
    IFoo, but which are you more likely to do: test one class to see if it
    satisfies lots of templates, or test one template against every class
    you meet? I think probably the latter is, if not more likely than the
    former, at least sufficiently plausible as to create confusion. It
    makes very good sense to say:

    duckmatch(IFoo).compare(Foo)

    ie with the arguments the other way.

    ChrisA
    Chris Angelico, Nov 9, 2012
    #4
  5. RE: duck typing assert

    Thank you for all comments.

    > It makes very good sense to say:
    >
    > duckmatch(IFoo).compare(Foo)


    Since we do duck match of IFoo... but there is no `duck match`, there is `duck test`. I believe instead of `compare` is more readable with `equals`. Than it is more from mathematics - precise answer... that you can not guarantee at all in dynamic programming language. So it false to use suchwording to reflect this check. We can only make an assumption that one looks like the other (similar)... with some limitation of cause... understanding what is `duck test`.

    http://en.wikipedia.org/wiki/Duck_test

    The intent is to make such language `construct` so it reads as English sentence that make sense, and not mandatory `pythonic` way (readability counts, java smokes aside).

    is_similar(Foo).to(IFoo) # <= but we lost `duck test` sense here?

    Words `looks` and `like` are coming from duck test and point also direction:

    # 1
    looks(Foo).like(IFoo, notice=['__len__'], ignore_funcs=['foo'], ignore_argspec['bar'])

    English sentence equivalent: if functions in Foo looks like one in IFoo than, probably, IFoo can be replaced with Foo; notice to check __len__, it is safe to ignore function `foo` and arguments passed to `bar`.

    # 2
    looks(Foo, notice=['__len__'], ignore_funcs=['foo'], ignore_argspec['bar']).like(IFoo)

    English sentence equivalent: while looking at Foo notice to check `__len__`, it is safe to ignore function `foo` and arguments passed to `bar`, than probably it like IFoo.

    I think #1 is easier to understand once it is written. Thoughts?

    Also construction looks(Foo).like(IFoo) points direction of check. It youneed the two be replaceable you need two asserts:

    assert looks(Foo).like(IFoo)
    assert looks(IFoo).like(Foo)

    Thanks.

    Andriy Kornatskyy


    ----------------------------------------
    > Date: Fri, 9 Nov 2012 17:14:49 +1100
    > Subject: Re: duck typing assert
    > From:
    > To:
    >
    > On Fri, Nov 9, 2012 at 12:00 PM, Ian Kelly <> wrote:
    > > looks(Foo).like(IFoo), on the other hand, is crystal clear about which
    > > argument is which.

    >
    > I'm not so sure that it is, tbh. If you read it like an English
    > sentence, it's clearly testing whether Foo matches the template in
    > IFoo, but which are you more likely to do: test one class to see if it
    > satisfies lots of templates, or test one template against every class
    > you meet? I think probably the latter is, if not more likely than the
    > former, at least sufficiently plausible as to create confusion. It
    > makes very good sense to say:
    >
    > duckmatch(IFoo).compare(Foo)
    >
    > ie with the arguments the other way.
    >
    > ChrisA
    > --
    > http://mail.python.org/mailman/listinfo/python-list
    Andriy Kornatskyy, Nov 9, 2012
    #5
  6. Re: duck typing assert

    On Thu, 08 Nov 2012 18:00:58 -0700, Ian Kelly wrote:

    > On Thu, Nov 8, 2012 at 4:33 PM, Steven D'Aprano
    > <> wrote:
    >> On Thu, 08 Nov 2012 20:34:58 +0300, Andriy Kornatskyy wrote:
    >>
    >>> People who come from strongly typed languages that offer interfaces
    >>> often are confused by lack of one in Python. Python, being dynamic
    >>> typing programming language, follows duck typing principal. It can as
    >>> simple as this:
    >>>
    >>> assert looks(Foo).like(IFoo)

    >>
    >> How very cute. And I don't mean that in a good way.
    >>
    >> Why is this a class with a method, instead of a function that takes two
    >> class arguments (plus any optional arguments needed)?
    >>
    >> looks_like(Foo, IFoo)
    >>
    >> is less "cute", reads better to English speakers, and much more
    >> Pythonic. This isn't Java, not everything needs to be a class.

    >
    > I disagree. Does that test whether Foo looks like IFoo, or IFoo looks
    > like Foo?


    What's the difference? "Looks like" is a symmetric comparison, like
    "equal" and "almost equal", but not "subset", "less than" etc. If x looks
    like y, then necessarily y must look like x. If Katy Perry looks like
    Zooey Deschanel, then it stands to reason that Zooey Deschanel looks like
    Katy Perry. James Woods looks like Erwin Schroedinger, and Erwin
    Schroedinger looks like James Woods.

    http://tvrefill.com/wp-content/uploads/2010/12/zooey-deschanel.jpg

    http://cheezburger.com/6704400128


    So in that sense, looks(Spam).like(Ham) must always be the same as
    looks(Ham).like(Spam), and the order of operators doesn't matter.

    But that's not what we want! And to his credit, that's not what Andriy
    Kornatskyy's code actually implements. The problem is with the name,
    which is actively misleading by suggesting a symmetrical comparison for
    one which is not symmetrical.

    Suppose we want to make a movie with Zooey Deschanel, but she's not
    available, so we want a replacement who is duck-type compatible with her.
    The replacement doesn't need to be a Deschanel sister, but she does need
    to do *at least* everything Zooey can do. If she can do more, that's
    fine, but she can't do less.

    Since Katy Perry can do everything Zooey can do, PLUS she sings, we can
    replace Zooey with Katy: Katy is duck-type compatible with Zooey. But we
    can't replace Katy with Zooey, because Zooey can't sing.[1]

    (I think... I really don't actually know if Zooey Deschanel can sing or
    not. Just go along with the example.)

    The point I am making is that "looks like" is not a good description for
    this function. "Looks like" must be symmetrical, but the function we
    actually want is not symmetrical. It is actually a "subset" type
    relationship: given "looks(Zooey).like(Katy)", it checks that the public
    methods etc. of Zooey are a subset of the methods of Katy. That is, that
    instances of Katy can be used instead of instances of Zooey.

    Or is it the other way? Damned if I know. Let's find out:

    class Zooey:
    def act(self): pass

    class Katy:
    def act(self): pass
    def sing(self): pass


    py> looks(Zooey).like(Katy)
    __main__:2: UserWarning: 'sing': is missing.
    False

    I guessed wrong. The looks.like method as implemented tests that the
    right-hand size operand is a subset of the right-hand-side:

    py> looks(Katy).like(Zooey)
    True


    I argue that this is the wrong way around. (Even if it isn't the wrong
    way around, it certainly isn't clear or obvious which way you have to
    write the operands!)

    Consider this use-case:

    candidates = [Hilary, Jennifer, Katy]
    expected = looks(Zooey) # instantiate the looks class once only
    for actor in candidates:
    if expected.like(actor):
    make_movie_with(actor())


    That's much nicer and more efficient than the way you have to write it
    now:

    candidates = [Hilary, Jennifer, Katy]
    for actor in candidates:
    # instantiate the looks class every time we want to test another class
    if looks(actor).like(Zooey):
    make_movie_with(actor())


    So... it's a cute name, that sounds English-like. But it doesn't actually
    describe what the function does, it is wasteful for at least one useful
    use-case, and it's not clear which order you have to supply the two
    arguments.


    > looks(Foo).like(IFoo), on the other hand, is crystal clear about which
    > argument is which.


    I hope that by now you can see why I say that it is as clear as mud.





    [1] Some people might argue that neither can Katy Perry.


    --
    Steven
    Steven D'Aprano, Nov 9, 2012
    #6
  7. RE: duck typing assert

    1. In looks-like we check features of Foo (that may be superset) of what IFoo offers.

    assert looks(Foo).like(IFoo)

    2. We can check if Foo is limited to IFoo only:

    assert looks(IFoo).like(Foo)

    So it valid to have both asserts.

    Thanks.

    Andriy Kornatskyy


    ----------------------------------------
    > From:
    > Subject: Re: duck typing assert
    > Date: Fri, 9 Nov 2012 13:36:39 +0000
    > To:
    >
    > On Thu, 08 Nov 2012 18:00:58 -0700, Ian Kelly wrote:
    >
    > > On Thu, Nov 8, 2012 at 4:33 PM, Steven D'Aprano
    > > <> wrote:
    > >> On Thu, 08 Nov 2012 20:34:58 +0300, Andriy Kornatskyy wrote:
    > >>
    > >>> People who come from strongly typed languages that offer interfaces
    > >>> often are confused by lack of one in Python. Python, being dynamic
    > >>> typing programming language, follows duck typing principal. It can as
    > >>> simple as this:
    > >>>
    > >>> assert looks(Foo).like(IFoo)
    > >>
    > >> How very cute. And I don't mean that in a good way.
    > >>
    > >> Why is this a class with a method, instead of a function that takes two
    > >> class arguments (plus any optional arguments needed)?
    > >>
    > >> looks_like(Foo, IFoo)
    > >>
    > >> is less "cute", reads better to English speakers, and much more
    > >> Pythonic. This isn't Java, not everything needs to be a class.

    > >
    > > I disagree. Does that test whether Foo looks like IFoo, or IFoo looks
    > > like Foo?

    >
    > What's the difference? "Looks like" is a symmetric comparison, like
    > "equal" and "almost equal", but not "subset", "less than" etc. If x looks
    > like y, then necessarily y must look like x. If Katy Perry looks like
    > Zooey Deschanel, then it stands to reason that Zooey Deschanel looks like
    > Katy Perry. James Woods looks like Erwin Schroedinger, and Erwin
    > Schroedinger looks like James Woods.
    >
    > http://tvrefill.com/wp-content/uploads/2010/12/zooey-deschanel.jpg
    >
    > http://cheezburger.com/6704400128
    >
    >
    > So in that sense, looks(Spam).like(Ham) must always be the same as
    > looks(Ham).like(Spam), and the order of operators doesn't matter.
    >
    > But that's not what we want! And to his credit, that's not what Andriy
    > Kornatskyy's code actually implements. The problem is with the name,
    > which is actively misleading by suggesting a symmetrical comparison for
    > one which is not symmetrical.
    >
    > Suppose we want to make a movie with Zooey Deschanel, but she's not
    > available, so we want a replacement who is duck-type compatible with her.
    > The replacement doesn't need to be a Deschanel sister, but she does need
    > to do *at least* everything Zooey can do. If she can do more, that's
    > fine, but she can't do less.
    >
    > Since Katy Perry can do everything Zooey can do, PLUS she sings, we can
    > replace Zooey with Katy: Katy is duck-type compatible with Zooey. But we
    > can't replace Katy with Zooey, because Zooey can't sing.[1]
    >
    > (I think... I really don't actually know if Zooey Deschanel can sing or
    > not. Just go along with the example.)
    >
    > The point I am making is that "looks like" is not a good description for
    > this function. "Looks like" must be symmetrical, but the function we
    > actually want is not symmetrical. It is actually a "subset" type
    > relationship: given "looks(Zooey).like(Katy)", it checks that the public
    > methods etc. of Zooey are a subset of the methods of Katy. That is, that
    > instances of Katy can be used instead of instances of Zooey.
    >
    > Or is it the other way? Damned if I know. Let's find out:
    >
    > class Zooey:
    > def act(self): pass
    >
    > class Katy:
    > def act(self): pass
    > def sing(self): pass
    >
    >
    > py> looks(Zooey).like(Katy)
    > __main__:2: UserWarning: 'sing': is missing.
    > False
    >
    > I guessed wrong. The looks.like method as implemented tests that the
    > right-hand size operand is a subset of the right-hand-side:
    >
    > py> looks(Katy).like(Zooey)
    > True
    >
    >
    > I argue that this is the wrong way around. (Even if it isn't the wrong
    > way around, it certainly isn't clear or obvious which way you have to
    > write the operands!)
    >
    > Consider this use-case:
    >
    > candidates = [Hilary, Jennifer, Katy]
    > expected = looks(Zooey) # instantiate the looks class once only
    > for actor in candidates:
    > if expected.like(actor):
    > make_movie_with(actor())
    >
    >
    > That's much nicer and more efficient than the way you have to write it
    > now:
    >
    > candidates = [Hilary, Jennifer, Katy]
    > for actor in candidates:
    > # instantiate the looks class every time we want to test another class
    > if looks(actor).like(Zooey):
    > make_movie_with(actor())
    >
    >
    > So... it's a cute name, that sounds English-like. But it doesn't actually
    > describe what the function does, it is wasteful for at least one useful
    > use-case, and it's not clear which order you have to supply the two
    > arguments.
    >
    >
    > > looks(Foo).like(IFoo), on the other hand, is crystal clear about which
    > > argument is which.

    >
    > I hope that by now you can see why I say that it is as clear as mud.
    >
    >
    >
    >
    >
    > [1] Some people might argue that neither can Katy Perry.
    >
    >
    > --
    > Steven
    > --
    > http://mail.python.org/mailman/listinfo/python-list
    Andriy Kornatskyy, Nov 9, 2012
    #7
  8. Re: duck typing assert

    On Sat, Nov 10, 2012 at 1:01 AM, Andriy Kornatskyy
    <> wrote:
    >
    > 1. In looks-like we check features of Foo (that may be superset) of what IFoo offers.
    >
    > assert looks(Foo).like(IFoo)
    >
    > 2. We can check if Foo is limited to IFoo only:
    >
    > assert looks(IFoo).like(Foo)
    >
    > So it valid to have both asserts.


    You'll almost never need #2, but since there's no difference between a
    "class" and an "interface", it's perfectly legal to switch them
    around.

    But I would generally expect that unrecognized methods are never a
    problem (assuming they don't collide with anything) - that, as in
    Steven's example, it's fine to have an actor who can sing when you
    don't need her to. When you post job openings, you don't normally ask
    for someone with "5+ years Python experience and unable to program in
    REXX" [1]. You're checking for a minimum set of requirements.

    [1] Though I suppose you might ask for someone who's unable to program
    in Pascal. Might save you some hassle.

    ChrisA
    Chris Angelico, Nov 9, 2012
    #8
  9. RE: duck typing assert

    There is sense for #2. Let me explain. There is basic IFoo implementation and improved Foo. While I switched to Foo, I still want to be as close to IFoo as possible, since there might be sense to switch to Foo2 later, which conform to IFoo.

    Here is the problem: if I will not assert #2 potentially I will use some `features` that are not in IFoo, thus that breaks my code switching to Foo2later.

    That might not apply for 100% usability cases, just wanted to point that out as reasonable thing.

    Thanks.

    Andriy Kornatskyy


    ----------------------------------------
    > Date: Sat, 10 Nov 2012 01:15:36 +1100
    > Subject: Re: duck typing assert
    > From:
    > To:
    >
    > On Sat, Nov 10, 2012 at 1:01 AM, Andriy Kornatskyy
    > <> wrote:
    > >
    > > 1. In looks-like we check features of Foo (that may be superset) of what IFoo offers.
    > >
    > > assert looks(Foo).like(IFoo)
    > >
    > > 2. We can check if Foo is limited to IFoo only:
    > >
    > > assert looks(IFoo).like(Foo)
    > >
    > > So it valid to have both asserts.

    >
    > You'll almost never need #2, but since there's no difference between a
    > "class" and an "interface", it's perfectly legal to switch them
    > around.
    >
    > But I would generally expect that unrecognized methods are never a
    > problem (assuming they don't collide with anything) - that, as in
    > Steven's example, it's fine to have an actor who can sing when you
    > don't need her to. When you post job openings, you don't normally ask
    > for someone with "5+ years Python experience and unable to program in
    > REXX" [1]. You're checking for a minimum set of requirements.
    >
    > [1] Though I suppose you might ask for someone who's unable to program
    > in Pascal. Might save you some hassle.
    >
    > ChrisA
    > --
    > http://mail.python.org/mailman/listinfo/python-list
    Andriy Kornatskyy, Nov 9, 2012
    #9
  10. RE: duck typing assert

    Andriy Kornatskyy wrote:

    >
    > Thank you for all comments.
    >

    > > It makes very good sense to say:
    > >
    > > duckmatch(IFoo).compare(Foo)

    >
    > Since we do duck match of IFoo...but there is no `duck match`, there is `duck test`. I believe instead of
    > `compare` is more readable with `equals`. Than it is more from mathematics - precise answer... that you can not
    > guarantee at all in dynamic programming language. So it false to use such wordingto reflect this check. We can
    > only make an assumption that one looks like the other (similar)... with some limitation of cause...
    > understanding what is `duck test`.
    >
    > http://en.wikipedia.org/wiki/Duck_test
    >
    > The intent is to make such language `construct` so it reads as English sentence that make sense, and not
    > mandatory `pythonic` way (readability counts, java smokes aside).
    >
    > is_similar(Foo).to(IFoo) # <= but we lost `duck test` sense here?
    >
    > Words `looks` and `like` are coming from duck test and point also direction:
    >
    > # 1
    > looks(Foo).like(IFoo, notice=['__len__'], ignore_funcs=['foo'], ignore_argspec['bar'])
    >
    > English sentence equivalent: if functions in Foo looks like one in IFoo than, probably, IFoo can be replaced
    > with Foo; notice to check __len__, it is safe to ignore function `foo` and arguments passed to `bar`.
    >
    > # 2
    > looks(Foo, notice=['__len__'], ignore_funcs=['foo'], ignore_argspec['bar']).like(IFoo)
    >
    > English sentence equivalent: while looking at Foo notice to check `__len__`, it is safe to ignore function `foo`
    > and arguments passed to `bar`, than probably it like IFoo.


    What about?

    duck(Foo).equivalent_to(IFoo, <kwargs>)
    duck(Foo).matches(IFoo, <kwargs>)

    This email is confidential and subject to important disclaimers and
    conditions including on offers for the purchase or sale of
    securities, accuracy and completeness of information, viruses,
    confidentiality, legal privilege, and legal entity disclaimers,
    available at http://www.jpmorgan.com/pages/disclosures/email.
    Prasad, Ramit, Nov 9, 2012
    #10
  11. RE: duck typing assert

    duck(Foo).match(IFoo, <kwargs>)
    duck(Foo).like(IFoo, <kwargs>)

    Hm... function name in most cases is read as verb... this may cause confusion:
    duck => synonyms => immerse, dip

    Thanks.

    Andriy Kornatskyy

    ----------------------------------------
    > From:
    > To: ;
    > Subject: RE: duck typing assert
    > Date: Fri, 9 Nov 2012 17:37:29 +0000
    >
    > Andriy Kornatskyy wrote:
    > >
    > > Thank you for all comments.
    > >
    > > > It makes very good sense to say:
    > > >
    > > > duckmatch(IFoo).compare(Foo)

    > >
    > > Since we do duck match of IFoo... but there is no `duck match`, thereis `duck test`. I believe instead of
    > > `compare` is more readable with `equals`. Than it is more from mathematics - precise answer... that you can not
    > > guarantee at all in dynamic programming language. So it false to use such wording to reflect this check. We can
    > > only make an assumption that one looks like the other (similar)... withsome limitation of cause...
    > > understanding what is `duck test`.
    > >
    > > http://en.wikipedia.org/wiki/Duck_test
    > >
    > > The intent is to make such language `construct` so it reads as English sentence that make sense, and not
    > > mandatory `pythonic` way (readability counts, java smokes aside).
    > >
    > > is_similar(Foo).to(IFoo) # <= but we lost `duck test` sense here?
    > >
    > > Words `looks` and `like` are coming from duck test and point also direction:
    > >
    > > # 1
    > > looks(Foo).like(IFoo, notice=['__len__'], ignore_funcs=['foo'], ignore_argspec['bar'])
    > >
    > > English sentence equivalent: if functions in Foo looks like one in IFoothan, probably, IFoo can be replaced
    > > with Foo; notice to check __len__, it is safe to ignore function `foo` and arguments passed to `bar`.
    > >
    > > # 2
    > > looks(Foo, notice=['__len__'], ignore_funcs=['foo'], ignore_argspec['bar']).like(IFoo)
    > >
    > > English sentence equivalent: while looking at Foo notice to check `__len__`, it is safe to ignore function `foo`
    > > and arguments passed to `bar`, than probably it like IFoo.

    >
    > What about?
    >
    > duck(Foo).equivalent_to(IFoo, <kwargs>)
    > duck(Foo).matches(IFoo, <kwargs>)
    >
    > This email is confidential and subject to important disclaimers and
    > conditions including on offers for the purchase or sale of
    > securities, accuracy and completeness of information, viruses,
    > confidentiality, legal privilege, and legal entity disclaimers,
    > available at http://www.jpmorgan.com/pages/disclosures/email.
    Andriy Kornatskyy, Nov 9, 2012
    #11
    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. Duck Typing

    , Sep 16, 2003, in forum: Python
    Replies:
    10
    Views:
    683
    Steve Holden
    Sep 17, 2003
  2. Replies:
    15
    Views:
    563
    Isaac Gouy
    Sep 1, 2006
  3. Replies:
    2
    Views:
    320
    Terry Reedy
    Jan 28, 2008
  4. Paddy
    Replies:
    1
    Views:
    392
    Paddy
    May 9, 2008
  5. Paddy
    Replies:
    0
    Views:
    241
    Paddy
    Jun 25, 2008
Loading...

Share This Page