[Tutor] Tutor Digest, Vol 104, Issue 60
eryksun
eryksun at gmail.com
Tue Oct 16 12:45:30 CEST 2012
On Tue, Oct 16, 2012 at 3:53 AM, Osemeka Osuagwu <abasiemeka at gmail.com> wrote:
> On Sun, 14 Oct 2012 16:21:38 +0100 Alan Gauld wrote:
>
> Just to clarify, if I went with the top level function; then I guess
> I'll define a 'name' attribute for each individual grid and then pass
> that name in place of the 'grid' argument in your example. Is this
> correct?
No, you'd just pass a grid object, but you probably want an instance
method, anyway. Perhaps some background can clarify.
Here's a function and a class that have no relation:
>>> def f(grid): pass
>>> class Test(object): pass
The __get__ method-wrapper of the function can bind it as a method of
a Test object:
>>> f.__get__(Test(), Test)
<bound method Test.f of <__main__.Test object at 0x96d5d6c>>
If f is accessed as an attribute of Test, it behaves the same as above:
>>> Test.f = f
>>> Test().f
<bound method Test.f of <__main__.Test object at 0x96d5d8c>>
The first argument of a function, when the function is intended to be
a method, is conventionally called "self". The bound method created by
__get__ automatically supplies this argument for you. If you instead
make the function global (module level), it's best to use a name that
suggests the kind of object you expect as the first argument (e.g.
grid). But really, if it expects to work on a particular grid, you
should make it a method of Grid.
Other kinds of methods:
If the instance is None, __get__ returns an unbound method:
>>> f.__get__(None, Test)
<unbound method Test.f>
A classmethod binds to the class instead of an instance:
>>> classmethod(f).__get__(None, Test)
<bound method type.f of <class '__main__.Test'>>
>>> classmethod(f).__get__(Test(), Test)
<bound method type.f of <class '__main__.Test'>>
When a function is intended to be a classmethod, it's common to name
the first argument "cls".
Finally, a staticmethod has no binding at all. Its __get__
method-wrapper simply returns the wrapped function:
>>> staticmethod(f).__get__(None, Test)
<function f at 0x96daae4>
>>> staticmethod(f).__get__(Test(), Test)
<function f at 0x96daae4>
There's not much use for this.
Refer to the Descriptor HowTo Guide for more details:
http://docs.python.org/howto/descriptor.html
> I don't quite get this one; I intended state to be just the value of
> the particular cell in the concerned instance. I don't think it gets
> shared by all the grids. The edit method was meant as a way of seeding
> the initial cell configuration, so it just writes whatever it is
> passed in the 'state' arg over that cell location; then again, I'm
> probably missing something here...
Grid.__array is used throughout the class definition. This is a class
attribute. Instances will not get their own copy. Instead, create the
list of lists in Grid.__init__:
def __init__(self, rows=26, cols=26):
'''Create a rows x cols grid'''
self._array = [[''] * cols for i in range(rows)]
print 'A %d x %d cell World has been Created' % (rows, cols)
Note that this uses a list comprehension to create each row as a
unique list. If instead it multiplied a list literal by a number, each
row would be the *same* list. For example:
>>> rows = [[''] * 2] * 2
>>> rows[0][0] = '##'
>>> rows
[['##', ''], ['##', '']]
Also note that it uses _array with a single leading underscore. This
is the convention for 'private' data or methods. It signals to other
developers that this is not part of the public API. Using a leading
double underscore causes the compiler to use name mangling in order to
prevent a subclass from easily overriding an attribute; it's used
infrequently.
Here's how the edit_cell method changes now that _array is instance data:
def edit_cell(self, cells, state='##'):
'''cells is a list of tuples containing coordinates of
the cells to edit
'''
for row, col in cells:
self._array[row][col] = state
return
More information about the Tutor
mailing list