From: Dave Angel on
Paddy O'Loughlin wrote:
> Hi,
> I was wondering if there was a shorthand way to get a reference to a method
> object from within that method's code.
>
> Take this code snippet as an example:
> import re
>
> class MyClass(object):
> def find_line(self, lines):
> if not hasattr(MyClass.do_work, "matcher"):
> MyClass.do_work.matcher = re.compile("\d - (.+)")
> for line in lines:
> m = MyClass.do_work.matcher.match(line)
> if m:
> return m.groups()
>
> Here, I have a method which uses a regular expression object to find
> matches. I want the regexp object to be tied to the function, but I don't
> want to have to recreate it every time the function is called (I am aware
> that regexp objects are cached, avoiding this problem, but I'm just using
> this as an example for what I want to know), so I've added it to the method
> object as an attribute and create it only if it doesn't exist.
>
> However, typing out <Classname>.<MethodName>.<variablename> everytime is
> pretty long and susceptible to refactoring issues, so I was wondering if
> there was a way in Python that I am missing which allows you to reference
> the method that the code is in (like __module__ gives a reference to the
> parent module).
>
> Paddy
>
>
I suspect that the "inspection" module has your answer, but that it'll
be bulkier, and much slower than just doing what you're doing already.

Why not use the default arguments gimmick? Since this cached item is to
have a module lifetime, it'd be desirable to create it when the method
is being defined, which is exactly what default arguments do.

Something like (untested):

class ...
def find_line(self, lines, _cacheitems = [] )
if not _cacheitems:
_cacheitems.append( re.compile..... )
for ...
m = _cacheitems[0]( line )


DaveA

From: Gerard Flanagan on
Paddy O'Loughlin wrote:
> Hi,
> I was wondering if there was a shorthand way to get a reference to a
> method object from within that method's code.
>
> Take this code snippet as an example:
> import re
>
> class MyClass(object):
> def find_line(self, lines):
> if not hasattr(MyClass.do_work, "matcher"):
> MyClass.do_work.matcher = re.compile("\d - (.+)")
> for line in lines:
> m = MyClass.do_work.matcher.match(line)
> if m:
> return m.groups()
>
> Here, I have a method which uses a regular expression object to find
> matches. I want the regexp object to be tied to the function, but I
> don't want to have to recreate it every time the function is called

Just an idea:

------------------------------
import re

def matches(patt):
def wrapper(fn):
def inner(self, *args, **kw):
return fn(self, *args, **kw)
inner.match = re.compile(patt).match
return inner
return wrapper

class MyClass(object):

@matches('ab(.*)')
def func(self):
print 'hi'
return 5

c = MyClass()

ret = c.func()
print ret
print c.func.match('abc').groups()
------------------------------------


From: Dave Angel on
Paddy O'Loughlin wrote:
>> I suspect that the "inspection" module has your answer, but that it'll be
>> bulkier, and much slower than just doing what you're doing already.
>>
>>
> Hmm.
> Yeah, it does appear to be bulky. I don't think it's really any more use
> than what I'm doing already.
>
>
> Why not use the default arguments gimmick? Since this cached item is to
>
>> have a module lifetime, it'd be desirable to create it when the method is
>> being defined, which is exactly what default arguments do.
>>
>>
>
> I've a few different ways of emulating static function variables from C/Java
> and the function/method attribute one is easily the one that appeals most to
> my sensibilities.
> I find the default arguments gimmick to be a gimmick. It's co-opting a piece
> of functionality for something it doesn't seem like it was originally
> intended for and as a consequence is less readable (to my eyes).
> The only problem with the function/method way is that it gets rather verbose
> when you are dealing with a user-defined method and have to give the class
> name and method name and it's also a bit of a pain for moving code around
> when refactoring.
>
> You ever wish there was more to python scoping than just locals(), globals()
> and __builtins__? Like a method's class's scope too?
> That's where I am at with this.
>
>
>
Back to your original approach - if you don't bind a new value to a
class variable, it's okay to just reference it with self, rather than
needing cls. But if you forget, and bind a new value, then you'll end
up with an instance attribute instead of reusing the class attribute.

How about (untested):

class ...
cacheitems = []
def find_line(self, lines):
if not self.cacheitems:
self.cacheitems.append( re.compile..... )
for ...
m = self.cacheitems[0]( line )


Just don't put self.cacheitems= xyzzy inside a method.

Incidentally, if your cacheitems is an instance of a dummy class (with
pass as a body), you could use named parameters instead of subscript.
But then you're back to the three nodes you already thought was too
verbose. All you've gained is the relative ease of refactoring.

DaveA