Need help with Python scoping rules
Steven D'Aprano
steve at REMOVE-THIS-cybersource.com.au
Thu Aug 27 05:14:41 EDT 2009
On Thu, 27 Aug 2009 08:38:29 +0200, Hendrik van Rooyen wrote:
> On Wednesday 26 August 2009 17:14:27 kj wrote:
>
>> As I described at length in another reply, the function in question is
>> not intended to be "callable outside the class". And yes,
>
> I think this might go to nub of your problem - It might help you to
> think as follows:
>
> A Python class, even after it has been executed, does not really exist
> except as a kind of template or pattern - it is mostly useless until an
> instance of the class is made by calling it with whatever it needs to
> set up the instance. And once you have an instance, you can do stuff
> with that particular instance. Before that time, the class is mostly
> just a promise of things to come.
Oh my! I couldn't disagree more strongly! I think the above is totally
incorrect.
Classes and types are first class objects, you can treat them like
anything else in Python. In fact, classes themselves are instances of
type, so you can say:
>>> class C(object): # must inherit from object
... pass
...
>>> issubclass(C, object)
True
>>> isinstance(C, type)
True
Classes are themselves instances of their metaclass. By default, classes
have a metaclass of type, but you can easily change that. Metaclass
programming is advanced but very powerful.
Because classes are themselves objects, you can (with a bit of metaclass
jiggery-pokery) make them do all sorts of interesting things. For
instance, huge amounts of effort are often put into creating a Singleton
class, a class that has a single instance. Well, okay... but why not just
use the class object itself, instead of an instance? There's already one
of those, and you can't (easily) make a copy of it, and even if you did,
it would be an independent class. Instead of this:
singleton = SingletonClass(args)
do_something_with(singleton)
just do this:
do_something_with(SingletonClass)
Of course SingletonClass needs to be designed to work that way, which
will probably need some metaclass magic. It would be interesting to see
which requires less effort.
When it comes to built-in classes (types), I often use the class object
itself as an object. E.g. I might do something like this:
def convert(seq):
t = type(seq) # remember the original type
result = process(seq) # always produces a list
if t is list:
return result # don't bother making a copy of the result
elif t is str or t is unicode:
empty = t()
return empty.join(result)
else:
return t(result) # return the original type
>> recursive functions in Python *are* restricted in ways that
>> non-recursive functions aren't. The examples I've posted prove this
>> point unambiguously.
>
> Yes and no - mostly no - your examples just illustrate the point I
> tried to make above.
Completely no. You may have missed the examples I've given, but the
problems the Original Poster were having had nothing to do with recursion.
> Pythons object model, and its classes, are different from what you are
> used to. A bare class is mostly useless without an instance, which is
> ultimately why accessing a function in a class from itself like you are
> doing, without reference to an instance, does not work - the function
> does not exist yet to a degree that it can be referenced.
That is incorrect. What's going on is more subtle.
>>> class Demo:
... def function(x):
... print "Calling function with argument %s" % x
... function(None)
... function(1)
... function(function)
...
Calling function with argument None
Calling function with argument 1
Calling function with argument <function function at 0xb7d495dc>
>>> Demo
<class __main__.Demo at 0xb7d4e0ec>
--
Steven
More information about the Python-list
mailing list