OO in Python? ^^

B

bonono

Magnus said:
Assume that you didn't use Python, but rather something with
static typing. How could you make a module such as my_module.py,
which is capable of working with any type that supports some
standard copy functionality and the +-operator?

The following is a very short Haskell function I defined which I hope
can give you some idea.

What it does is just take a generic list of things(I want to use it on
string) and break it up into a tuple using any object in token as
seperator (sort of C's strtok).

breakKeyword token xs =
case break (flip elem token) xs of
(_,[]) -> (xs,[])
(ys,z:zs) -> (ys, zs)

This is the function declaration derived by Haskell(I haven't specify
anything above about types)

*MyList> :type breakKeyword
breakKeyword :: (Eq a) => [a] -> [a] -> ([a], [a])

What it means is that breakKeyword can take any list of object type "a"
so long it belongs to the class Eq. It can be char, number or whatever
so long it is an instance of Eq.

All that is needed for my custom data type(whatever it is) is that it
must implment the compare function that "elem" would use to compare if
a given object is in the list of token.

*MyList> :type elem
elem :: (Eq a) => a -> [a] -> Bool
 
A

Antoon Pardon

Op 2005-12-14 said:
I don't know. I am learning Haskell(and Python too), long way to go
before I would get into the the usage you mentioned, if ever, be it
Haskell or Python.

Huh? I must have expressed my thoughts badly. This is trivial to
use in Python. You could for instance write a module like this:

### my_module.py ###
import copy

def sum(*args):
result = copy.copy(args[0])
for arg in args[1:]:
result += arg
return result

### end my_module.py ###

Then you can do:
from my_module import sum
sum(1,2,3) 6
sum('a','b','c') 'abc'
sum([1,2,3],[4,4,4]) [1, 2, 3, 4, 4, 4]

Assume that you didn't use Python, but rather something with
static typing.

That depends on what you would call static typing.

Suppose we would add type declarations in python.
So we could do things like

int: a
object: b

Some people seem to think that this would introduce static
typing, but the only effect those staments need to have
is that each time a variable is rebound an assert statement
would implicitly be executed, checking whether the variable is
still an instance of the declared type.

(Assuming for simplicity that all classes are subclasses
of object so that all objects are instances of object.)
How could you make a module such as my_module.py,

In the above scenario in just the same way as in python.
 
C

Christopher Subich

Antoon said:
Suppose we would add type declarations in python.
So we could do things like

int: a
object: b

Some people seem to think that this would introduce static
typing, but the only effect those staments need to have
is that each time a variable is rebound an assert statement
would implicitly be executed, checking whether the variable is
still an instance of the declared type.

Doesn't work; duck typing is emphatically not subclass-typing. For this
system to still work and be as general as Python is now (without having
to make all variables 'object's), we'd need true interface checking.
That is, we'd have to be able to say:

implements + like int: a

or somesuch. This is a Hard problem, and not worth solving for the
simple benefit of checking type errors in code.

It might be worth solving for dynamic code optimization, but that's
still a ways off.
 
M

Magnus Lycka

Christopher said:
Doesn't work; duck typing is emphatically not subclass-typing. For this
system to still work and be as general as Python is now (without having
to make all variables 'object's), we'd need true interface checking.
That is, we'd have to be able to say:

implements + like int: a

or somesuch. This is a Hard problem, and not worth solving for the
simple benefit of checking type errors in code.

It might be worth solving for dynamic code optimization, but that's
still a ways off.

Correct, but he's just trolling you know. What he suggests isn't
static typing, and he knows it. It gives all the rigidity of static
typing with only a tiny fraction of the claimed benefits, but it would
give a hefty performance penalty.
 
M

Mike Meyer

Magnus Lycka said:
Huh? I must have expressed my thoughts badly. This is trivial to
use in Python. You could for instance write a module like this:

### my_module.py ###
import copy

def sum(*args):
result = copy.copy(args[0])
for arg in args[1:]:
result += arg
return result

### end my_module.py ###

Then you can do:
from my_module import sum
sum(1,2,3) 6
sum('a','b','c') 'abc'
sum([1,2,3],[4,4,4]) [1, 2, 3, 4, 4, 4]

Assume that you didn't use Python, but rather something with
static typing. How could you make a module such as my_module.py,
which is capable of working with any type that supports some
standard copy functionality and the +-operator?

CLU had this decades ago. You'd right something like:

def sum(*args) args has +=:
...

Basically, it did duck typing, checked at compile time instead of
dynamically.

<mike
 
D

Donn Cave

Magnus said:
Assume that you didn't use Python, but rather something with
static typing. How could you make a module such as my_module.py,
which is capable of working with any type that supports some
standard copy functionality and the +-operator?

The following is a very short Haskell function I defined which I hope
can give you some idea. ....

*MyList> :type breakKeyword
breakKeyword :: (Eq a) => [a] -> [a] -> ([a], [a])

What it means is that breakKeyword can take any list of object type "a"
so long it belongs to the class Eq. It can be char, number or whatever
so long it is an instance of Eq.

All that is needed for my custom data type(whatever it is) is that it
must implment the compare function that "elem" would use to compare if
a given object is in the list of token.

*MyList> :type elem
elem :: (Eq a) => a -> [a] -> Bool

Moreover, 1) this compare implementation is (as I understand it)
made available via runtime information, so a typeclass instance
may be implemented after the function that encounters it was compiled,
and 2) implementation often requires no more than "deriving Eq"
after the data type declaration -- assuming the data type is
composed of other types of data, you can infer the functional
composition of a typeclass instance.

The sum function in my_module.py was, in a very approximate sense,
like the standard "foldr" function. Of course foldr doesn't need to
copy, nor does it use any += operator. foldr is generic to any
function of type (a -> a -> b) (i.e., takes two parameters of one
type and returns a value of another type.) Lists don't support
a (+) operation (numeric only), but they support (++) concatenation
and :)) composition. foldr also takes an initial parameter of type b.

so,
foldr :)) "" ['a', 'b', 'c']
foldr (++) [] [[1, 2, 3], [4, 4, 4]]

Really, this kind of abstraction of data types is not only well
supported in Haskell, it can be almost a curse, at least for
someone like myself who has fairly superficial experience with
this kind of programming. After all the functions have been
zealously scrubbed clean of any trace of concrete data types and
rendered maximally abstract, they can be a little hard to understand.

Donn Cave, (e-mail address removed)
 
B

bonono

Donn said:
Really, this kind of abstraction of data types is not only well
supported in Haskell, it can be almost a curse, at least for
someone like myself who has fairly superficial experience with
this kind of programming. After all the functions have been
zealously scrubbed clean of any trace of concrete data types and
rendered maximally abstract, they can be a little hard to understand.
My experience too. An interesting thing I experienced with Haskell is
that even though it is strongly and statically typed, I seldom think
about data types when writing programs, kind of typeless to me.
 
B

bonono

Alex said:
Well, historically templates HAVE been added to Haskell "as an
afterthought" (well after the rest of the language was done), and
judging mostly from
<http://research.microsoft.com/~simonpj/papers/meta-haskell/meta-haskell
.ps> it doesn't seem unfair to call them "convoluted"...
I think I was talking about the need to add templates in order for
writing generic functions that was mentioned(see the example given
about sum), not in the context you are talking about. You seem to have
skipped the other half of the text I quoted.
 
A

Alex Martelli

I think I was talking about the need to add templates in order for
writing generic functions that was mentioned(see the example given
about sum), not in the context you are talking about. You seem to have
skipped the other half of the text I quoted.

Right, you can get good genericity with Haskell's typeclasses (I've
posted about that often in the past, and desperately and so far
unsuccessfully tried to convince Guido to use something close to
typeclasses rather than "interfaces" for such purposes as PEP 246
[protocol adaptation]); it's the state of _templates_ in Haskell,
specifically, which I was rather dubious about (it may be that I just
haven't dug into them deep enough yet, but they do seem not a little
"convoluted" to me, so far).


Alex
 
B

bonono

Alex said:
I think I was talking about the need to add templates in order for
writing generic functions that was mentioned(see the example given
about sum), not in the context you are talking about. You seem to have
skipped the other half of the text I quoted.

Right, you can get good genericity with Haskell's typeclasses (I've
posted about that often in the past, and desperately and so far
unsuccessfully tried to convince Guido to use something close to
typeclasses rather than "interfaces" for such purposes as PEP 246
[protocol adaptation]); it's the state of _templates_ in Haskell,
specifically, which I was rather dubious about (it may be that I just
haven't dug into them deep enough yet, but they do seem not a little
"convoluted" to me, so far).
Yup, the templates is an afterthought and the point of discussion by
Lispers(?) too. I have no idea what it is intended for, there must be
some need for it but definitely beyond what I can handle.
 
A

Antoon Pardon

Op 2005-12-14 said:
Doesn't work; duck typing is emphatically not subclass-typing.

I don't see how that is relevant.
For this
system to still work and be as general as Python is now (without having
to make all variables 'object's),

But the way Guido wants python to evolve would make all variables
objects. This is what PEP 3000 states.

Support only new-style classes; classic classes will be gone.

As far as I understand this would imply that all classes are subclasses
of object and thus that isinstance(var, object) would be true for all variables.
 
A

Antoon Pardon

Op 2005-12-14 said:
Correct, but he's just trolling you know. What he suggests isn't
static typing, and he knows it.

What I know or not isn't the point. My impression is that different
people have different ideas on what is static typing and what is not.
I can't read minds about what each individual person thinks. So
I don't know whether you (or someone else) considered this static
typing or not.
It gives all the rigidity of static
typing with only a tiny fraction of the claimed benefits, but it would
give a hefty performance penalty.

Yes it would give a performance penalty. That is irrelavant to the
question asked. Nothing stops the language designers from using
this type information, to produce more efficient code where possible.
But whether or not the designers would do this, would make no difference
on what would be possible to do.
 
B

Ben Sizer

Antoon said:
Op 2005-12-14, Christopher Subich schreef

I don't see how that is relevant.


But the way Guido wants python to evolve would make all variables
objects. This is what PEP 3000 states.

Support only new-style classes; classic classes will be gone.

As far as I understand this would imply that all classes are subclasses
of object and thus that isinstance(var, object) would be true for all variables.

But that's still useless for your purposes. Everything will be derived
from object but it doesn't mean everything file-like will be derived
from file or everything dictionary-like will be derived from
dictionary. Duck-typing means that code told to 'expect' certain types
will break unnecessarily when a different-yet-equivalent type is later
passed to it.
 
A

Antoon Pardon

Op 2005-12-15 said:
But that's still useless for your purposes.

What purpose would that be? Maybe you can tell me, so I can
know too.
Everything will be derived from object but it doesn't mean
everything file-like will be derived from file or everything
dictionary-like will be derived from dictionary.

So? I answered a question. That my answer is not usefull for
a specific purpose is very well prosible but is AFAIC irrelevant.
I didn't notice a specific purpose behind the question
and didn't answer the question with a specific purpose in mind.
Duck-typing means that code told to 'expect' certain types
will break unnecessarily when a different-yet-equivalent type is later
passed to it.

I think you mixed things up.
 
B

Ben Sizer

Antoon said:
Op 2005-12-15, Ben Sizer schreef <[email protected]>:
So? I answered a question. That my answer is not usefull for
a specific purpose is very well prosible but is AFAIC irrelevant.

The point being made was that your declarations such as these:

int: a
object: b

would break the original idea (a module containing a sum() function
that can take any object that has an addition operator). Inheritance
isn't good enough in this situation. I apologise if that isn't what you
were answering, but that seems to have been the thread context.
 
A

Antoon Pardon

Op 2005-12-15 said:
The point being made was that your declarations such as these:

int: a
object: b

would break the original idea (a module containing a sum() function
that can take any object that has an addition operator).

1) a declaration as

object: b

Wouldn't break the original idea, since b would be basically a python
object as it is now.

2) Sure a declaration as

int: a

would break the original idea, but that was just given as an example
of what kind of declarations one might possibly use. You are not obligated
to use declarations that limits you so much.
Inheritance
isn't good enough in this situation. I apologise if that isn't what you
were answering, but that seems to have been the thread context.

No I wasn't answering that. I was just trying to give an idea from
a different angle. People seem to think that one uses static typing
or inheritance typing or duck typing. IMO the possibility of inheritance
typing doesn't have to prevent duck typing.
 
A

Aahz

Right, you can get good genericity with Haskell's typeclasses (I've
posted about that often in the past, and desperately and so far
unsuccessfully tried to convince Guido to use something close to
typeclasses rather than "interfaces" for such purposes as PEP 246
[protocol adaptation]); it's the state of _templates_ in Haskell,
specifically, which I was rather dubious about (it may be that I just
haven't dug into them deep enough yet, but they do seem not a little
"convoluted" to me, so far).

Hrm. I don't recall anything about typeclasses, so my suspicion is that
you were writing something lengthy and above my head. Can you write
something reasonably short about it? (I'm asking partly for your
benefit, because if it makes sense to me, that will likely go a long way
toward making sense to Guido -- we seem to think similarly in certain
ways.)
 
A

Alex Martelli

[protocol adaptation]); it's the state of _templates_ in Haskell,
specifically, which I was rather dubious about (it may be that I just
haven't dug into them deep enough yet, but they do seem not a little
"convoluted" to me, so far).
Yup, the templates is an afterthought and the point of discussion by
Lispers(?) too. I have no idea what it is intended for, there must be
some need for it but definitely beyond what I can handle.

I believe that the basic idea is to make available a powerful "compile
time language" in parallel to the "runtime language" -- so in a sense
the motivation is related to that for macros in Lisp, at least if I grok
it correctly... but with more anchoring in the typesystem rather than in
syntactic aspects of the base language. As it turns out that C++'s
templates also make up a Turing-complete compile-time language anchored
in the (admittedly weaker/less elegant) typesystem of the base language,
it's not all that different "philosophically" (if my understanding is
correct). I gather that the next C++ standard will have "concepts" (in
the generic programming sense of the word) as a first-class construct,
rather than just as an abstraction to help you think of templates, so it
may be that the current distinctions will blur even further...


Alex
 
A

Alex Martelli

Aahz said:
Hrm. I don't recall anything about typeclasses, so my suspicion is that
you were writing something lengthy and above my head. Can you write
something reasonably short about it? (I'm asking partly for your
benefit, because if it makes sense to me, that will likely go a long way
toward making sense to Guido -- we seem to think similarly in certain
ways.)

Think of a typeclass as something "like an interface, more than an
interface" to which a type can easily be "adapted" by a third programmer
even if the two programmers who wrote the type and typeclass were
working separately and with no knowledge of each other -- not too far
from the vaguer idea of "protocol" I support in PEP 246 (which focuses
on the adaptation), except that in Haskell things happen at compile time
while in Python we prefer to avoid the strong distinction between
compile time and runtime.

You may think of a typeclass as akin to an abstract baseclass, because
it's not constrained to only giving the signatures of methods, it can
also supply some default implementations of some methods in terms of
others. Guido blogged in August about interfaces versus ABCs, not
remembering why he had once Pronounced about preferring ABCs, and in his
critique of ABCs he mentions that one weakness of their ability to
provide default implementations is that you have to decide about what is
the most fundamental subset, in whose terms the rest is implemented.
But *typeclasses do away with that need*. Consider (arbitrary
pythonesquoid syntax):

typeclass mapping:
def __getitem__(self, key):
_notthere=[]
result = self.get(key, _notthere)
if result is notthere: raise KeyError
return result
def get(self, key, default):
try: return self[key]
except KeyError: return default
# etc etc

this LOOKS like mutual recursion, but since it's a typeclass it doesn't
mean that: it means __getitem__ may be defined (and then get uses the
provided default implementation unless overridden) OR get may be defined
(and then it's __getitem__ that may use the default implementation
supplied by the the typeclass, or else override it).

When you compile a typeclass you build a directed graph of dependencies
of methods on each other, which may include cycles; when you show how a
type adapts to a typeclass, you build a copy of that graph removing the
dependencies of those methods which do get explicitly implemented (in
the type or in the adapter) -- if the copy at the end of these
compilations still has cycles, or leaves (methods that the typeclass
requires and neither the type nor the adapter supply), then this raises
an exception (incomplete adaptation).

Thus, a typeclass clearly shows the semantics intended for methods that
depend on each other, and conveniently lets you, the adapter's author,
choose what to implement -- the typeclass's author has not been forced
to pick the "most fundamental" methods. ABCs, or extremely handy mixins
such as UserDict.DictMixin, do force a programmer who knows nothing
about the internals of your class (the author of the ABC or mixin) to
pick "most fundamental" methods. Thus, typeclasses are more useful than
ABCs by as much as ABC are more useful than (simply "syntactical")
interfaces -- coupled with adaptation mechanisms, the overall result can
be extremely handy (as any Haskell programmer might confirm).


Alex
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,001
Messages
2,570,254
Members
46,849
Latest member
Fira

Latest Threads

Top