By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
439,957 Members | 1,936 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 439,957 IT Pros & Developers. It's quick & easy.

class vs function ???

P: n/a
Hi !

I am a poor mortal who has become terrified of Python. It seems to
have thrown all the OO concepts out of the window. Penniless, I ask a
basic question :
What is the difference between a class and a function in Python ???
Consider the following code fragments :
# Fragment 1 begins

a = 1
print a
def fun1():
global b
b = "inside fun1"
print b
fun1()
def c1():
print a
print b
c = 12
def fun2():
global d
d = "We are dead !!!"
print d
fun2()
c1()
class c2:
pass
print d
print c

# Fragment 1 ends
# Fragment 2 begins
a = 1
print a
def fun1():
global b
b = "inside fun1"
print b
fun1()
class c1:
print a
print b
c = 12
def fun2():
global d
d = "We are dead !!!"
print d
fun2()
class c2:
pass

print d
print c

# Fragment 2 ends

The output of both these codes are precisely the same ! (including the
error because of 'print c')

The sample output is :
1
inside fun1
1
inside fun1
We are dead !!!
We are dead !!!
Traceback (most recent call last):
File "XYZ.py", line 21, in ?
print c
NameError: name 'c' is not defined

Waiting for some 'logical' explanation !!!

Gaurav
Jul 18 '05 #1
Share this Question
Share on Google+
12 Replies


P: n/a
Python allows you to do basically whatever you want, that doesn't mean
that what you do makes sense.

There are cases where embedding functions is useful (you don't want that
function available to everything else in the module), but it doesn't
help with data abstraction, which is the fundamental use of classes:
class blah: .... def __init__(self, embed):
.... self.embedded = embed
.... def print_embedded(self):
.... print self.embedded
.... a = blah(5)
a.print_embedded() 5

To do this with embedded functions, you'd need to add an attribute to
some returned object explicitly.
def blah2(embed): .... def print_embedded():
.... print embed
.... print_embedded.print_embedded = print_embedded
.... return print_embedded
.... b = blah2(6)
b.print_embedded()
6
Now, the above works, but in my opinion, is ugly. I suggest you try to
do the following with embedded functions (it can be done, but is ugly):

class blah3:
pass
c = blah3()
c.hello = 1
c.goodbye = 2
del c.hello
print c.goodbye

What is the difference between a class and a function in Python ???


Functionally, you can do the same with both. Pragmatically, classes are
easier to use for all non-trivial data abstraction. I know my
explanation hasn't been very good, but you really haven't looked at much
Python code if you don't understand the difference between functions and
classes.

- Josiah
Jul 18 '05 #2

P: n/a
"Gaurav Veda" <gv***@iitk.ac.in> wrote in message
news:1c**************************@posting.google.c om...
[snip]
a = 1
print a
def fun1():
global b
b = "inside fun1"
print b
fun1()
def c1():
print a
print b
c = 12
def fun2():
global d
d = "We are dead !!!"
print d
fun2()
c1()
class c2:
pass
print d
print c [snip] Traceback (most recent call last):
File "XYZ.py", line 21, in ?
print c
NameError: name 'c' is not defined

Waiting for some 'logical' explanation !!!


The error message _is_ the logical explanation:

The name 'c' has not been defined in the scope where
'print c' is called.

You have a variable 'c' earlier in the code, yes, but that
c is a local variable of function c1(), i.e., the name 'c' _is_
defined in the scope of that function (but _only_ in that
scope). It is _not_ defined at the program scope, which
is where you've tried to use it.

I'll avoid going over Python's scoping rules here, they can
be found elsewhere. Good luck,

Sean
Jul 18 '05 #3

P: n/a

"Gaurav Veda" <gv***@iitk.ac.in> wrote in message
news:1c**************************@posting.google.c om...
Hi !

I am a poor mortal who has become terrified of Python. It seems to
have thrown all the OO concepts out of the window. Penniless, I ask a
basic question :
What is the difference between a class and a function in Python ???
Consider the following code fragments :
# Fragment 1 begins

a = 1
print a
def fun1():
global b
b = "inside fun1"
print b
fun1()
def c1():
print a
print b
c = 12
def fun2():
global d
d = "We are dead !!!"
print d
fun2()
c1()
class c2:
pass
print d
print c

# Fragment 1 ends
# Fragment 2 begins
a = 1
print a
def fun1():
global b
b = "inside fun1"
print b
fun1()
class c1:
print a
print b
c = 12
def fun2():
global d
d = "We are dead !!!"
print d
fun2()
class c2:
pass

print d
print c

# Fragment 2 ends

The output of both these codes are precisely the same ! (including the
error because of 'print c')
Why shouldn't they be the same?

The sample output is :
1
inside fun1
1
inside fun1
We are dead !!!
We are dead !!!
Traceback (most recent call last):
File "XYZ.py", line 21, in ?
print c
NameError: name 'c' is not defined

Waiting for some 'logical' explanation !!!

What has probably gotten you confused is that
the text of the class executes when the class is
defined, while the text of a function doesn't.
So in both cases the same statements executed,
but because of a different execution order.
a = 1
print a <------ "1"
def fun1():
global b
b = "inside fun1"
print b
fun1() <--- "inside fun1"
def c1():
print a
print b
c = 12
def fun2():
global d
d = "We are dead !!!"
print d
fun2()
c1() <---- "1", "inside fun1", "We are dead!!!"
class c2:
pass
print d <----- "we are dead !!!" a = 1
print a <------ "1"
def fun1():
global b
b = "inside fun1"
print b
fun1() <--- "inside fun1"
class c1():
print a <--- "1"
print b <--- "inside fun1"
c = 12
def fun2():
global d
d = "We are dead !!!"
print d <---- "we are dead !!!"
fun2()
class c2:
pass
print d <----- "we are dead !!!"
John Roth

Gaurav

Jul 18 '05 #4

P: n/a
Gaurav Veda wrote:
What is the difference between a class and a function in Python ???
Functions and classes are both callable objects. Calling a function
executes the body of the function; calling a class creates and returns an
instance of the class.
Waiting for some 'logical' explanation !!!


I'm not sure to explain. How does the output differ from what you expected?
--
Rainer Deyke - ra*****@eldwood.com - http://eldwood.com
Jul 18 '05 #5

P: n/a
Gaurav Veda wrote:
I am a poor mortal who has become terrified of Python. It's a nice snake, but don't let it wrap itself around you.
What is the difference between a class and a function in Python ??? Substantial. However, your code is not testing that.
The thing to remember is that definitions are executed
to create the defined thing.

A function definition creates code and then stores the code as
the name in the def part.

A class definition creates a new "context,", then interprets the
rest of the class definition in that context. At the end of the
class definition, the class name, superclass list, and all names
defined in context are handed to a metaclass in order to build
a class from that definition, and the class returned by the
metaclass is then stored under the class name. One of the jobs
of the metaclass is to convert functions defined in the context
into "unbound methods".

Your code, if typed in to an interactive interpreter, would
clue you in that this was happening.
# Fragment 1 begins

a = 1 a is defined print a 1 is printed here def fun1():
global b
b = "inside fun1"
print b nothing is printed here, but fun1 is defined.
now you have a and fun1 fun1() 'inside fun1' is printed here, and b is defined def c1():
print a
print b
c = 12
def fun2():
global d
d = "We are dead !!!"
print d
fun2() Again, nothing is printed here, c1 is defined. c1() Now you get the output 'We are dead!!!', and d is defined. class c2:
pass c2 the class is defined. print d the d produced by c1 above is printed. print c I cannot imagine where c came from (it was local to c1, so
goes away when c2 is exited (and is only available inside c1
and fun2 (because fun2 was defined inside c1).
# Fragment 1 ends
# Fragment 2 begins
a = 1
print a
def fun1():
global b
b = "inside fun1"
print b
fun1() up to here is all works the same. class c1:
print a here 1 is printed print b here 'inside fun' is printed c = 12 Here a variable named c is created in the context which will become c1 def fun2():
global d
d = "We are dead !!!"
print d Here a function named fun2 is created in the ... fun2() Here, within the pending context, the normal function fun2 is called.
'We are dead!!!' is printed and the global d is defined.

At the end of c1's definition (because of the outdent below),
a metaclass is handed 'c1', empty superclasses, and a dictionary
containing entries for 'c' and 'fun2'. Now fun2 is converted from
a function to an unbound method in this process.
you could type 'print c1.c' to see a 12 come out.
class c2:
pass Another class is defined.
print d d was created by the function fun2 when called inside c1's definition. print c c is a class variable on c1. You could type 'print c1.c'
Waiting for some 'logical' explanation !!!

I hope this helps.

--
-Scott David Daniels
Sc***********@Acm.Org
Jul 18 '05 #6

P: n/a
On 21 Feb 2004 08:57:44 -0800, gv***@iitk.ac.in (Gaurav Veda)
wrote:
What is the difference between a class and a function in Python ???
Pretty much the same as in every other OOP programming language.
Your question is not really about Python but about OO.

To try to answer it I'll start with the big picture answer:

A function is an operation that returns a value. The value may be
None. A function can be used directly by other bits of your
program.

A class is a combination of some data and the functions which
operate on that data all wrapped up as a single item. A class is
a template which is used to create objects. You normally use the
objects in your program not the classes.

You might want to look at the Modular Programming and OOP topics
in my online tutorial for more details.(see the .sig)

Now let's look at your issues:
def fun1():
global b
b = "inside fun1"
print b
fun1()
Here we define a function called fun1 which takes no parameters
and returns None as a value (None is the defauilt in Python).
Inside the function is some code which, incidentally, does not
follow good programming practice.

[It is better to have your functions completely predictable in
effect. Thus values are passed in, those values are not changed
by the function, the function does not print anything, and the
function returns a result. ]

Of course you are simply printing for debug purposes but in
general its bad practice. However this is all aside from your
main issue...

def c1():
print a
print b
c = 12
def fun2():
global d
d = "We are dead !!!"
print d
fun2()
c1()
This defines a second function called c1 which amongst other
things defines yet another function, fun2, and calls it.
You then call c1.
class c2:
pass
Here we define a class called c2 which does nothing.
And we do not create any objects from it.
class c1:
print a
print b
c = 12
def fun2():
global d
d = "We are dead !!!"
print d
fun2()
Here we create a new class called c1 which contains a variable
called c. In the process of defining the class we incidentally
define another function called fun2 and call it. It has nothing
to do with the class as such.
class c2:
pass
And here we define another new class called c2 which does nothing
except replace the reference to the old c2 class which will, in
due time, be garbage collected.

We have not yet created any objects from any of our classes.
We have executed the class definition code which just happens to
do some printing of values and defining and executing of
functions. But the net result is two classes, one of which is
empty and the other contains a single variable and a function
which is effectively unusable.

We can see the variable by typing

print c1.c

The output of both these codes are precisely the same ! (including the
error because of 'print c')


That's correct, but just because the visible output is the same
does not mean that they are doing the same thing. Nor even that
the end result is the same.

Lets look at one feature of your program again in more detail:

def fun1():
c = 12
print "inside fun1"
print c

class c1:
d = 42
print "defining class c1"
print d

fun1()
print c
print c1.d

Now we can print the d that is inside c1 but not the c that is
inside fun1. This is because c only exists while fun1 is
executing. But d persists after the class is created because the
class itself persists.

To make c visible after fun1 completes we must declare it global,
as you did, but that in reality global simply creates a value
outside of fun1. (See the namespaces topic in my tutor for
that...)

A class is a container and anything you create within its
definition persists and can be accessed, whereas a function is
just a bit of executable code and any values created inside it
are lost when the function exits.

However the real power of classes is only seen once you create
instances of them - ie objects. But that's for another time.

HTH,

Alan G.
Author of the Learn to Program website
http://www.freenetpages.co.uk/hp/alan.gauld
Jul 18 '05 #7

P: n/a
Gaurav Veda wrote:
Hi !

I am a poor mortal who has become terrified of Python. It seems to
have thrown all the OO concepts out of the window. Penniless, I ask a
basic question :
What is the difference between a class and a function in Python ???
As seen in your code, you have to call the function to execute the code in
it. And as not seen, you can create instances of classes but not of
functions.

At the risk of telling too much, I'll mention two concepts here:

1. Everything is an object. A class, a function, a list, a string, an int
are all objects. This means you can pass functions and classes around like
other objects.

2. Objects are created as and when specified. See comments below.
Consider the following code fragments :
# Fragment 1 begins

a = 1
Here you create a new int object and bind it to the name 'a'.
print a
def fun1():
global b
b = "inside fun1"
print b
Here you create a new function object and bind it to name 'fun1'. The def
statement creates a new function object. The code is 'stored' inside the
function object and gets executed later, when you call the function like...
fun1()
def c1():
print a
print b
c = 12
def fun2():
global d
d = "We are dead !!!"
print d
fun2()
Another function got created. Note that the 'def fun2()' statement will not
be executed until c1 is called. And everytime it is called, a new fun2 will
be created (just like a new c is created by 'c = 12'). Also, there is no
way you can call fun2 from outside c1.
c1()
Another function call.
class c2:
pass
Here you create a new class and bind it to the name 'c2'. The class
statement creates a class. Code inside the class body is 'executed' to
create the attributes of the class. Here you have no code. If you had for
example:

class c2:
a = 1
b = 2
c = a + b

then you'd have a class with three class attributes (c2.a, c2.b and c2.c).
Everything inside the body is executed *once* and all the names are
collected to make the class.
print d
print c

# Fragment 1 ends
# Fragment 2 begins
a = 1
print a
def fun1():
global b
b = "inside fun1"
print b
fun1()
class c1:
print a
print b
c = 12
def fun2():
global d
d = "We are dead !!!"
print d
fun2()
A class with a body. Note the 'execution' of the 'def fun2()' statement
creates a function object which ends up in the class (c1.fun2). It is
executed only once, fun2 will never be created again. Calling fun2() in the
body isn't really much use (neither are the print statements).

If you call a class (which you never do), you create an instance of a class
(which is yet another object). Then you can call the functions defined in
the class from the instance. The tutorial might help you here - to use
classes like classes in any other language, as a template for creating
instances and holding common methods.
class c2:
pass

print d
print c

# Fragment 2 ends

The output of both these codes are precisely the same ! (including the
error because of 'print c')


Python keeps all OO concepts intact. The implementation may be somewhat
different from some other languages, but a class behaves like a class and a
function behaves like a function.

Python is mostly easy. If some things are confusing, I suggest you initially
'use as directed', i.e. go through the tutorial and follow other examples
of how it is used.

--
Shalabh
Jul 18 '05 #8

P: n/a
On 21 Feb 2004 08:57:44 -0800, gv***@iitk.ac.in (Gaurav Veda) wrote:
Hi !

I am a poor mortal who has become terrified of Python. It seems to
have thrown all the OO concepts out of the window. Penniless, I ask a
basic question :
What is the difference between a class and a function in Python ???


Lots. However, there are shared ideas which are generally very useful.

Clearly you have spotted that the body source code of a class is
normal code, rather than some alternate 'definition block syntax'.
It's execution builds the class. This is a very simple yet powerful
concept, and very appropriate to a scripting language.

But the similarity in your code snippets is a carefully constructed
illusion. You claim the function 'c1' is equivalent to the class 'c1',
but it is not. The body of function 'c1' only executes because you
called it. The body of class 'c1' executes in order to define the
class - you didn't instantiate it at all.

Being able to use print statements in within the class definition is,
BTW, convenient for debugging, but wouldn't normally be done in
deliverable code. As for calling a just-defined member function within
the definition of a class - well, that's pretty strange. But just
because something is rarely done, it doesn't mean it should be
illegal. At the very least, it could be useful for assertions and
other debug checks.

As for the error with 'c' - of course it's an error in both, and the
same error as in both cases there is no identifier 'c' in scope at the
point of the print statement. The fact that neither block of code
created a suitable identifier is not very strange - there are an
infinite number of ways of writing a block of code that doesn't define
a global 'c' ;-)

However, your two cases are still completely different when you look
at the 'c' identifiers that you did define. In the first case, 'c' is
a local variable in the function - it no longer exists after the call
is completed. In the second case, 'c' is a member variable in the
class - it still exists, but as you did not use the dot notation in
the print statement you are not referencing the member field.
Similarly, I could observe that the following three expressions give
the same result...
2+2 4 2*2 4 2**2 4

I can even get essentially the same errors out of those operators...
class a : .... pass
.... a+a Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: unsupported operand type(s) for +: 'classobj' and
'classobj' a*a Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: unsupported operand type(s) for *: 'classobj' and
'classobj' a**a

Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: unsupported operand type(s) for ** or pow(): 'classobj' and
'classobj
'

That does not mean, however, that addition, multiplication and raising
to a power are the same thing. These are just carefully selected
special cases of the use and abuse of those operators. Which is ok, if
you enjoy playing with such things ;-)
--
Steve Horne

steve at ninereeds dot fsnet dot co dot uk
Jul 18 '05 #9

P: n/a

Hmmm...

In my first reply, I assumed you weren't entirely serious. After all,
why include the 'c2' class definitions - completely empty and not used
in any way - if not to add a little camouflage to your calling the
'c1' function in the first snippet but not doing the matching 'call'
to instantiate 'c1' in the second case?

Now I've read the other replys, and I'm suddenly wondering if I got it
all wrong.

Nah - you were definitely having a bit of fun, weren't you! Go on,
admit it!
--
Steve Horne

steve at ninereeds dot fsnet dot co dot uk
Jul 18 '05 #10

P: n/a
Hi !

I have read all the replies and they are all extremely helpful. Thanks
a lot !!!
My basic doubts were :
1) I am allowed to write things in the class body without the need for
encapsulating them in functions. Moreover, they are executed as soon
as I define the class. Infact, I can also call functions in the class
body (the way I called fun2). All this, while I am just defining the
class ! -- I still don't understand why are classes implemented in
this way in pyhton.

2) The reason I had that erroneous 'print c' statement was, because I
just wanted to point out that it seems like the scoping rules for both
classes and functions are the same. -- I now understand the scoping
rules and realize the fallacy. Thanks again !

Being a 3rd year undergraduate student, I have to make a Python
'compiler' (I know it sounds foolish -- but thats what my instructor
wants me to do !). This is the precise reason why I am tinkering with
Python and trying to figure out the exact way in which things work !

Gaurav

PS : No Steve, I am not trying out any tricks here. Believe me, I know
too little to do any of that :)
Jul 18 '05 #11

P: n/a
Gaurav Veda wrote:
Hi !

I have read all the replies and they are all extremely helpful. Thanks
a lot !!!
My basic doubts were :
1) I am allowed to write things in the class body without the need for
encapsulating them in functions. Moreover, they are executed as soon
as I define the class. Infact, I can also call functions in the class
body (the way I called fun2). All this, while I am just defining the
class ! -- I still don't understand why are classes implemented in
this way in pyhton.
In Python, function declarations ("def"s) are statements just like "if"
or "print" or "while". Anywhere you can define a function you can use
"if" or "print" or "while" and anywhere you can use "if" or "print" or
"while", you can use "def". This simplifies the language by removing
special cases. This basic concept is also very powerful sometimes:
class do_somethin_in_a_cross_platform_way:
if sys.platform=="win32":
import some_win32_library
def myfunc():
some_win32_library.dosomething()
else:
import some_unix_library
def myfunc():
some_win32_library.dosomething()

For various reasons you are unlikely to see code that looks exactly like
that but you should get the gist of how you can take advantage of
Python's flexibility. Here's another kind of pattern that may stretch
your mind:

def function_that_makes_functions(arg1):
def inner_function(self, arg2):
... do something with arg1 and arg2 ...

return inner_function

class a:
mymethod1 = function_that_makes_functions("abc")
mymethod2 = function_that_makes_functions("def")
...
Being a 3rd year undergraduate student, I have to make a Python
'compiler' (I know it sounds foolish -- but thats what my instructor
wants me to do !).


There are actually a few Python compilers out there. compiler.py
compiles to Python bytecodes. Pyrex compiles to C. Jython compiles to
Java bytecodes. There are couple of half-implemented compilers to .NET
bytecodes.

You probably need to define a subset as Pyrex does. Compiling all of
Python is quite a challenge and won't teach you much about how people
compile more traditional languages like Java or C.

Paul Prescod

Jul 18 '05 #12

P: n/a
On 21 Feb 2004 22:26:14 -0800, gv***@iitk.ac.in (Gaurav Veda) wrote:
My basic doubts were :
1) I am allowed to write things in the class body without the need for
encapsulating them in functions. Moreover, they are executed as soon
as I define the class. Infact, I can also call functions in the class
body (the way I called fun2). All this, while I am just defining the
class ! -- I still don't understand why are classes implemented in
this way in pyhton.
Well, I think of it this way. Some time back in ancient prehistory,
Python didn't have classes - but it did have simple imperitive code.
At some point, someone needed to add classes in. The options were...

1. Make a minimal change, exploiting the existing functionality to
allow quite sophisticated classes to be defined relatively easily
using normal code and concepts that were already familiar to
Python users and which could potentially benefit from updates to
the core language.

2. Treat class bodies as a completely new thing, and define a new
'sublanguage' for them from the ground up which, once developed,
Python users would have to learn as an extra thing in addition
to the existing non-class aspects of Python, and which could not
benefit from future useful additions to the core language unless
their implementation was explicitly duplicated in the class
definition sublanguage.

The first choice might seem odd if your experience up to now is mostly
of statically typed languages (where it isn't really an option) but
for a scripting language like Python, IMHO it is the most rational
choice.
PS : No Steve, I am not trying out any tricks here. Believe me, I know
too little to do any of that :)


OK, I guess I'll accept that - but I'm still keeping my eye on you <g>

BTW Python itself is already a compiler - a bytecode compiler - so if
you really need to write your own compiler I'd suggest taking a look
at how the PYC files are generated, and seeing if you can just wrap
them (or something similar) in an exe that embeds the Python
interpreter (or a subset of it, including at least the bytecode
interpreter and its dependencies). Keep in mind that converting a
sequence of text statements into a sequence of function calls (doing
little more than parsing and linearising expressions) may be a bit
simplistic, but it works - and doing anything noticably more
sophisticated would probably be pretty hard work.

I assume that's the approach taken by the existing Py2exe
(http://starship.python.net/crew/thel...xe/index.html).

If you need to write something more advanced, using static analysis to
do special case optimisations when possible, there was a project doing
something similar a little while back but I forget the name. I've done
some googling and keep finding references to Viperc, but I don't think
that's the one I'm thinking of.

If you can find it (whatever it's called) I imagine you'll find it
pretty clueful too.

If your aiming for more of a Python-like but not entirely compatible
language, Pyrex (http://www.cosc.canterbury.ac.nz/~greg/python/Pyrex/)
may also provide some useful hints. It supports some static typing
syntax, which allows it to safely use more efficient compiled code in
many special cases (without requiring it to use psychic powers in its
static analysis).
--
Steve Horne

steve at ninereeds dot fsnet dot co dot uk
Jul 18 '05 #13

This discussion thread is closed

Replies have been disabled for this discussion.