How to learn OO of python?

C

could ildg

I have learned python for over a month.
I heard that it was very easy to learn, but when I tried to know OO of python,
I found it really weird, some expressions seem very hard to understand,
and I can't find enough doc to know any more about it.
So, I wonder how did you master python? And where to find some cool docs?

Thanks.
 
?

=?iso-8859-1?q?Asbj=F8rn_S=E6b=F8?=

could ildg said:
I have learned python for over a month.
I heard that it was very easy to learn, but when I tried to know OO of python,
I found it really weird, some expressions seem very hard to understand,
and I can't find enough doc to know any more about it.

Have you seen the python docs? Maybe this link is of some help.
http://www.python.org/doc/2.4.1/tut/node11.html

Asbjørn
 
P

Peter Dembinski

could ildg said:
I have learned python for over a month.
I heard that it was very easy to learn, but when I tried to know OO
of python,
I found it really weird, some expressions seem very hard to understand,
and I can't find enough doc to know any more about it.

These may be hard to understand because you haven't understood OOP.
Python syntax is very similar to p-code used in computer science
books. Try to think like a computer scientist :>
So, I wonder how did you master python? And where to find some cool
docs?

Go to the nearest library and get some OO design book.
 
H

Harlin Seritt

I think I know what you mean. When I first started trying to learn the
OOP aspect of Python I thought it was strange since I had started with
OOP on Java and C++. Nonetheless, once you get the hang of it, OOP will
make way more sense than all of the complications of Java and C++ class
implementations. Let me give you a quick example of what I'm talking
about:

class Animal:
def eats(self):
print 'The animal eats.'
def walks(self):
print 'The animal walks.'

"""Here the class Dog instantiates the class Animal. 'Dog' will 'do'
whatever 'Animal' does plus some other things which we will describe in
this class code."""
class Dog(Animal):
"""#the self keyword means that this function will be a class
function"""
def communicate(self):
print 'The dog barks.'

"""# __init__ function defines what # #will happen as soon as this
class is instantiated. Also, the overloaded variable designators (color
= None, fur = None) allow the instantiator to optionally define these
variables when called from elsewhere."""

def __init__(self, color=None, fur=None):
"""# this time self will designate the variable 'color' # as a
class variable."""
self.color = color
self.fur = fur

if __name__ == '__main__':
sparky = Dog(color="White", fur="Short")
sparky.communicate()
print sparky.color
print sparky.fur
print sparky.eats() # Here sparky will access 'Animal' methods
that 'Dog' inherited.
print sparky.walks() # Another method originating from the 'Animal'
class.

What happens if you don't use 'self' inside your class code? You won't
be able to access it within the class outside of the method where you
initialized it. For instance, if you don't designate color with self
then you can only use the 'color' variable within the __init__()
method. This is useful whenever you want to use 'color' as a private
variable.

The same also goes for methods. Hopefully, you see how useful this can
be down the road. This way you won't have to use variable/method access
modifiers like Public, Private, Protected and so forth. If this doesn't
make sense or you want more clarity, please let me know.

Good luck,

Harlin Seritt
 
P

Philippe C. Martin

PS: if you're under linux, try umbrello: you design your classes with a
graphical tool and umbrello will generate the code (Python too) for you.
 
C

could ildg

Thanks very much to Harlin Seritt.
Your example is really helpful to me.

I read some more docs on python oop and I am more clear
now. But when I try to understand Decorators for Functions and Methods
in PEP 318, I got puzzled. How do Decorators work?

I think decorator is a function which return a function, is this right?
e.g. The decorator below if from http://www.python.org/peps/pep-0318.html#id1.

def accepts(*types):
def check_accepts(f):
assert len(types) == f.func_code.co_argcount
def new_f(*args, **kwds):
for (a, t) in zip(args, types):
assert isinstance(a, t), \
"arg %r does not match %s" % (a,t)
return f(*args, **kwds)
new_f.func_name = f.func_name
return new_f
return check_accepts

After I saw all the examples, I concluded that every decorator must
define an inner function which takes only one argument, the
function to decorate. Is this right?
 
S

Steven Bethard

could said:
I think decorator is a function which return a function, is this right?
e.g. The decorator below if from http://www.python.org/peps/pep-0318.html#id1.

def accepts(*types):
def check_accepts(f):
assert len(types) == f.func_code.co_argcount
def new_f(*args, **kwds):
for (a, t) in zip(args, types):
assert isinstance(a, t), \
"arg %r does not match %s" % (a,t)
return f(*args, **kwds)
new_f.func_name = f.func_name
return new_f
return check_accepts

After I saw all the examples, I concluded that every decorator must
define an inner function which takes only one argument, the
function to decorate. Is this right?

It's close, but not quite right. (I will use the word "function" for
the moment, but see below for why this is inaccurate.) Every
*decorator* must take only one argument, the function to decorate. It is
not at all necessary that a decorator define an inner function.
Consider (from [1]):

def onexit(f):
import atexit
atexit.register(f)
return f

onexit is a decorator because it takes a function and returns a
function. In this case, it happens to be that the same function is
accepted and returned.

Note that in the 'accepts' example above, *check_accepts* is the
decorator, not accepts. The accepts function is actually a function
that *returns* decorators.

Now about that word "function". Decorators are actually *callables*
that accept a single *callable* and return a *callable*. Why does the
terminology matter? Because I can construct decorators from classes too
(from [2]):

class memoized(object):
def __init__(self, func):
self.func = func
self.cache = {}
def __call__(self, *args):
try:
return self.cache[args]
except KeyError:
self.cache[args] = value = self.func(*args)
return value
except TypeError:
return self.func(*args)

Now the memoized decorator can be used just like any other decorator, e.g.:

@memoized
def fibonacci(n):
if n in (0, 1):
return n
return fibonacci(n-1) + fibonacci(n-2)

Note however that memoized is a *callable*, not a *function*.

STeVe

[1] http://www.python.org/peps/pep-0318.html
[2] http://wiki.python.org/moin/PythonDecoratorLibrary
 
C

could ildg

Steven Bethard:
Thank you so much!
Your answer is very very helpful~

could said:
I think decorator is a function which return a function, is this right?
e.g. The decorator below if from http://www.python.org/peps/pep-0318.html#id1.

def accepts(*types):
def check_accepts(f):
assert len(types) == f.func_code.co_argcount
def new_f(*args, **kwds):
for (a, t) in zip(args, types):
assert isinstance(a, t), \
"arg %r does not match %s" % (a,t)
return f(*args, **kwds)
new_f.func_name = f.func_name
return new_f
return check_accepts

After I saw all the examples, I concluded that every decorator must
define an inner function which takes only one argument, the
function to decorate. Is this right?

It's close, but not quite right. (I will use the word "function" for
the moment, but see below for why this is inaccurate.) Every
*decorator* must take only one argument, the function to decorate. It is
not at all necessary that a decorator define an inner function.
Consider (from [1]):

def onexit(f):
import atexit
atexit.register(f)
return f

onexit is a decorator because it takes a function and returns a
function. In this case, it happens to be that the same function is
accepted and returned.

Note that in the 'accepts' example above, *check_accepts* is the
decorator, not accepts. The accepts function is actually a function
that *returns* decorators.

Now about that word "function". Decorators are actually *callables*
that accept a single *callable* and return a *callable*. Why does the
terminology matter? Because I can construct decorators from classes too
(from [2]):

class memoized(object):
def __init__(self, func):
self.func = func
self.cache = {}
def __call__(self, *args):
try:
return self.cache[args]
except KeyError:
self.cache[args] = value = self.func(*args)
return value
except TypeError:
return self.func(*args)

Now the memoized decorator can be used just like any other decorator, e.g..:

@memoized
def fibonacci(n):
if n in (0, 1):
return n
return fibonacci(n-1) + fibonacci(n-2)

Note however that memoized is a *callable*, not a *function*.

STeVe

[1] http://www.python.org/peps/pep-0318.html
[2] http://wiki.python.org/moin/PythonDecoratorLibrary
 
M

Mike Meyer

Harlin Seritt said:
I think I know what you mean. When I first started trying to learn the
OOP aspect of Python I thought it was strange since I had started with
OOP on Java and C++. Nonetheless, once you get the hang of it, OOP will
make way more sense than all of the complications of Java and C++ class
implementations. Let me give you a quick example of what I'm talking
about:

Um, there are some problems with your commentary.
class Animal:
def eats(self):
print 'The animal eats.'
def walks(self):
print 'The animal walks.'

"""Here the class Dog instantiates the class Animal. 'Dog' will 'do'
whatever 'Animal' does plus some other things which we will describe in
this class code."""
class Dog(Animal):
"""#the self keyword means that this function will be a class
function"""
def communicate(self):
print 'The dog barks.'

First, the correct terminology is class *method*. Yes, it looks like a
function definition, but it's a class method. Second, "self" isn't a
keyword. It's just a name. You can name any variable self. The first
argument to all class methods is a reference to the instance of the
class that is invoking the method. It can have any name you want, but
by convention in Python is called "self". Consider the following:

py> class C:
.... def say(my, message):
.... print message
....
py> self = C()
py> self.say("hello")
hello
py>

Finally, *every* def inside a class statement creates a class
method. You don't really need to worry about this, but will see it on
the group. The method can be wrapped, and the defined name rebound to
the wrapper, either via the decorator syntax or directly, using the
classmethod and staticmethod functions.
"""# __init__ function defines what # #will happen as soon as this
class is instantiated. Also, the overloaded variable designators (color
= None, fur = None) allow the instantiator to optionally define these
variables when called from elsewhere."""

def __init__(self, color=None, fur=None):
"""# this time self will designate the variable 'color' # as a
class variable."""
self.color = color
self.fur = fur

These aren't variable designators, and they aern't overloaded. They
are parementers, and they are given default values. This means they
can be omitted from an invocation of the method, in which case the
default values will be used.
if __name__ == '__main__':
sparky = Dog(color="White", fur="Short")
sparky.communicate()
print sparky.color
print sparky.fur
print sparky.eats() # Here sparky will access 'Animal' methods
that 'Dog' inherited.
print sparky.walks() # Another method originating from the 'Animal'
class.

What happens if you don't use 'self' inside your class code? You won't
be able to access it within the class outside of the method where you
initialized it. For instance, if you don't designate color with self
then you can only use the 'color' variable within the __init__()
method. This is useful whenever you want to use 'color' as a private
variable.

I'm not sure where to start here.

"self" is a variable name. By convention, it's use is reserved for the
first argument of methods, in which case it is passed the instance
that is invoking the method.

By assigning something to "self.feature", you are assigning a value to
an attribute - "feature" of this instance. This means it'll persist
beyond the function existing.

Assuming you have access to another object - let's call it foo - you
can assign values to it's attributes in the same way, by assigning to
"foo.feature". Once made, such an assignment will persist until it's
either changed, or the object foo ceases to exist.

If you assign to a bare variable name - i.e., one with no dot - it
will by default be local to that function. This means the variable
will cease to exist when the function exits. Some details you should
keep in mind, but can genarlly ignore: When the variable ceases to
exist, the object it reference will lose a reference, which may or may
not cause that object to cease to exist. You can cause an assignment
to refer to a variable in the enclosing modules global name space with
the "global" statement. Finally, if you referene a varaible rather
than assigning to it, it's searched for in the enclosing scopes, out
to the module global namespace.
The same also goes for methods. Hopefully, you see how useful this can
be down the road. This way you won't have to use variable/method access
modifiers like Public, Private, Protected and so forth. If this doesn't
make sense or you want more clarity, please let me know.

Generally, methods are referred to by referring to a feature of an
instance of an object. The first argument to the method is left off
such an invocation, as the instance the method reference is attached
to will be passed as that parameter. This is the way "self.method"
works - it's a reference to a method of the instance that was used to
invoke the currently executing method. Sometimes, you'll see
invocations of methods from the class, in which case an instance has
to be passed as the first parameter. The only time you're liable to
have to worry about this as you get started is in calling a precursor
to a method, like so:

class A:
def meth(self):
...

class B(A):
def meth(self):
A.meth(self)
...

This is depreciated. You should be using new-style classes and the
super function instead:

class A(object):
def meth(self):
...

class B(A):
def meth(self):
super(B, self).meth()

All features of classes/objects are public. The philosphy is that
"we're all adults here". If you want to indicate that some feature is
an internal implementation detail, and shouldn't be used by client
classes, start it's name with an "_". If you're really desperate, use
a double underscore. Python will mangle "__name" to
"_<classname>__name", making it slightly more painfull to use. This
just makes them hard to use, though, doesn't really hide them. But it
does this for classes that inherit from the class as well as clients
of the class.

<mike
 
B

Benji York

Harlin Seritt said:
>class Animal:
> def eats(self):
> print 'The animal eats.'
> def walks(self):
> print 'The animal walks.'
> """#the self keyword means that this function will be a class
>function"""

Mike said:
> First, the correct terminology is class *method*. Yes, it looks like
> a function definition, but it's a class method.

Perhaps you meant "instance method" instead of "class method".

From http://docs.python.org/lib/built-in-funcs.html:

A class method receives the class as implicit first argument, just
like an instance method receives the instance.
 

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,240
Messages
2,571,211
Members
47,845
Latest member
vojosay

Latest Threads

Top