Re: Perl vs. Python question...
On Tue, 2009-07-14 at 15:32 -0400, Joshua Judson Rosen wrote: > > The simplistic self.foo = self.compute_foo() will trigger a call to > > __getattr__, so you can't use that within __getattr__. > > That's not true; it *will*, however, trigger a call to __settattr__, > if it exists; that's what you're thinking of :) > > cf. http://docs.python.org/reference/datamodel.html#object.__setattr__ > > __getattr__, however, is free to just do `self.foo = ...'. Thanks for the correction. -- Lloyd Kvam Venix Corp DLSLUG/GNHLUG library http://dlslug.org/library.html http://www.librarything.com/catalog/dlslug http://www.librarything.com/rsshtml/recent/dlslug http://www.librarything.com/rss/recent/dlslug ___ gnhlug-discuss mailing list gnhlug-discuss@mail.gnhlug.org http://mail.gnhlug.org/mailman/listinfo/gnhlug-discuss/
Re: Perl vs. Python question...
Lloyd Kvam writes: > > On Mon, 2009-07-13 at 22:59 -0400, Paul Lussier wrote: > > Lloyd Kvam writes: > > > > > You've already gotten two useful responses. I'd just like to add that > > > typically, the object attributes are referenced directly: > > > rect.length * rect.width > > > > Lloyd, thanks. But what if the attribute isn't set yet? If I have > > self.foo, and self.foo hasn't yet been set, I want it to go and get set, > > then return the correct value. > > If the initial set value is a simple constant, make it a class attribute > with the default value. The object can override the attribute with a > different value when that value is determined. > > > > I get the impression the __getattr__() method helps here, > > If the value will be computed on demand, __getattr__ is one way to go. > def __getattr__(self, attr): > if attr == 'foo': > return self.compute_foo() > elif > else: > raise AttributeError( attr + ' is invalid name') > > This is the 'traditional' approach. __getattr__ is *only* called when > an attribute is not found. If you wanted to save the computed value, so > that __getattr__ was no longer used: > self.__dict__['foo'] = self.compute_foo() > return self.foo > > The simplistic self.foo = self.compute_foo() will trigger a call to > __getattr__, so you can't use that within __getattr__. That's not true; it *will*, however, trigger a call to __settattr__, if it exists; that's what you're thinking of :) cf. http://docs.python.org/reference/datamodel.html#object.__setattr__ __getattr__, however, is free to just do `self.foo = ...'. -- Don't be afraid to ask (Lf.((Lx.xx) (Lr.f(rr. ___ gnhlug-discuss mailing list gnhlug-discuss@mail.gnhlug.org http://mail.gnhlug.org/mailman/listinfo/gnhlug-discuss/
Re: Perl vs. Python question...
Lloyd Kvam writes: > If the value will be computed on demand, __getattr__ is one way to go. > def __getattr__(self, attr): > if attr == 'foo': > return self.compute_foo() > elif > else: > raise AttributeError( attr + ' is invalid name') > > This is the 'traditional' approach. __getattr__ is *only* called when > an attribute is not found. If you wanted to save the computed value, so > that __getattr__ was no longer used: > self.__dict__['foo'] = self.compute_foo() > return self.foo > > HTH Very much so! -- Thanks, Paul ___ gnhlug-discuss mailing list gnhlug-discuss@mail.gnhlug.org http://mail.gnhlug.org/mailman/listinfo/gnhlug-discuss/
Re: Perl vs. Python question...
On Mon, 2009-07-13 at 22:59 -0400, Paul Lussier wrote: > Lloyd Kvam writes: > > > You've already gotten two useful responses. I'd just like to add that > > typically, the object attributes are referenced directly: > > rect.length * rect.width > > Lloyd, thanks. But what if the attribute isn't set yet? If I have > self.foo, and self.foo hasn't yet been set, I want it to go and get set, > then return the correct value. If the initial set value is a simple constant, make it a class attribute with the default value. The object can override the attribute with a different value when that value is determined. > > I get the impression the __getattr__() method helps here, If the value will be computed on demand, __getattr__ is one way to go. def __getattr__(self, attr): if attr == 'foo': return self.compute_foo() elif else: raise AttributeError( attr + ' is invalid name') This is the 'traditional' approach. __getattr__ is *only* called when an attribute is not found. If you wanted to save the computed value, so that __getattr__ was no longer used: self.__dict__['foo'] = self.compute_foo() return self.foo The simplistic self.foo = self.compute_foo() will trigger a call to __getattr__, so you can't use that within __getattr__. The new-style python classes allow for cleaner dispatching of your attribute computations using properties, but for a small number of names, __getattr__ will do just fine. If there is no setter method and foo is always computed, your class could be coded: foo = property( compute_foo) > I just don't > quite get it yet. HTH > > -- > Thanks, > Paul -- Lloyd Kvam Venix Corp DLSLUG/GNHLUG library http://dlslug.org/library.html http://www.librarything.com/catalog/dlslug http://www.librarything.com/rsshtml/recent/dlslug http://www.librarything.com/rss/recent/dlslug ___ gnhlug-discuss mailing list gnhlug-discuss@mail.gnhlug.org http://mail.gnhlug.org/mailman/listinfo/gnhlug-discuss/
Re: Perl vs. Python question...
Lloyd Kvam writes: > You've already gotten two useful responses. I'd just like to add that > typically, the object attributes are referenced directly: > rect.length * rect.width Lloyd, thanks. But what if the attribute isn't set yet? If I have self.foo, and self.foo hasn't yet been set, I want it to go and get set, then return the correct value. I get the impression the __getattr__() method helps here, I just don't quite get it yet. -- Thanks, Paul ___ gnhlug-discuss mailing list gnhlug-discuss@mail.gnhlug.org http://mail.gnhlug.org/mailman/listinfo/gnhlug-discuss/
Re: Perl vs. Python question...
On 07/11/2009 11:44 PM, Paul Lussier wrote: > In perl, I can use the AUTOLOAD feature to dynamically create methods, > something like this: It looks like in perl6 you get this for free. I'm just getting started with it though. -Bill -- Bill McGonigle, Owner Work: 603.448.4440 BFC Computing, LLC Home: 603.448.1668 http://www.bfccomputing.com/Cell: 603.252.2606 Twitter, etc.: bill_mcgonigle Page: 603.442.1833 Email, IM, VOIP: b...@bfccomputing.com Blog: http://blog.bfccomputing.com/ VCard: http://bfccomputing.com/vcard/bill.vcf ___ gnhlug-discuss mailing list gnhlug-discuss@mail.gnhlug.org http://mail.gnhlug.org/mailman/listinfo/gnhlug-discuss/
Re: Perl vs. Python question...
On Sat, 2009-07-11 at 23:44 -0400, Paul Lussier wrote: > How do I create dynamically created methods in python classes? > > For example, if I have a number of member variables which I want to > get > or set, I don't want to have to create getters and setters for each > attribute, since the code would largely be the same, just the variable > I'm dealing with would be different. You've already gotten two useful responses. I'd just like to add that typically, the object attributes are referenced directly: rect.length * rect.width to compute area. Do not use: rect.get_length() * rect.get_width(). getter/setter methods get created when you some code is needed to control access: room.celsius room.fahrenheit computes the proper value from a single stored temperature (in Kelvin?). The code still looks like a direct reference to the attribute. You have a choice of using __getattr__/__getattribute__/__setattr__ or properties as suggested in the other email responses. -- Lloyd Kvam Venix Corp DLSLUG/GNHLUG library http://dlslug.org/library.html http://www.librarything.com/catalog/dlslug http://www.librarything.com/rsshtml/recent/dlslug http://www.librarything.com/rss/recent/dlslug ___ gnhlug-discuss mailing list gnhlug-discuss@mail.gnhlug.org http://mail.gnhlug.org/mailman/listinfo/gnhlug-discuss/
Re: Perl vs. Python question...
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 07/11/09 23:44, quoth Paul Lussier: > Hi Folks, > > How do I create dynamically created methods in python classes? > > For example, if I have a number of member variables which I want to get > or set, I don't want to have to create getters and setters for each > attribute, since the code would largely be the same, just the variable > I'm dealing with would be different. > > In perl, I can use the AUTOLOAD feature to dynamically create methods, > something like this: > > sub AUTOLOAD { > my ($self, @args) = @_; > my $method = $AUTOLOAD; > $method =~ s/.*:://; > if ($method ne 'DESTROY') { > # Return the structure/value pointed to by $self->{KEY}, or, set it > # if it's not a ref to something else. > if (exists $self->{"_$method"} && !ref($self->{"_$method"})) { > eval("*$AUTOLOAD = " > . "sub {" >. " my (\$self, \$value) = assertMinMaxArgs(1, 2, \...@_);" > . " if (\$value) {" > . "\$self->{\"_\$method\"} = \$value;" > . " }" > . " return \$self->{\"_\$method\"}" > . "}"); > } > goto &$AUTOLOAD; > } > } > > What this AUTOLOAD sub does is this: > > - First, it strips everything before the :: leaving just the methodname >(in perl, method names look like: CLASS::method() ) > - Then, it looks to see if there exists a member variable >$self->{_}, and that it's not a reference to something > - Then, it creates an anonymous sub (== a lambda in python I think) >Each anonymous sub looks like this: > > sub { > my ($self, $value) = assertMinMaxArgs(1, 2, @_); > if ($value) { > $self->{_$method} = $value; > } > return $self->{_$method} > > Essentially, it works like this. If I have a member variable _foo, and > I want to either set or get _foo, I call a method $self->foo(). If I > call it as $self->foo(bar), the _foo gets set to bar, otherwise, I get > back the current value of _foo. So, the anonymous sub above, gets > re-written as: > > sub foo { > my ($self, $value) = assertMinMaxArgs(1, 2, @_); > if ($value) { > $self->{_foo} = $value; > } > return $self->{_foo} > > I can basically create 1 method which will automagically create for me, > getter and setter methods for any member variable I create in my class. > (this is extremely similar, if not identical, to lisp macros!) > > For some reason I didn't think python had this capability, but someone > mentioned to me it did, but I'm not quite sure how I'd write it. > > Does anyone have any ideas? In the Python Coookbook, on (my) page 252 is a section called Section 6.8: "Avoiding Boilerplate Accessors for Properties". http://www.ubookcase.com/book/Oreilly/Python.Cookbook.2nd.edition/0596007973/pythoncook2-chp-6-sect-8.html The code they provide is this: def xproperty(fget, fset, fdel=None, doc=None): if isinstance(fget, str): attr_name = fget def fget(obj): return getattr(obj, attr_name) elif isinstance(fset, str): attr_name = fset def fset(obj, val): setattr(obj, attr_name, val) else: raise TypeError, 'either fget or fset must be a str' return property(fget, fset, fdel, doc) but the discussion is important to read and fully understand before you think you can just plug it in. - -- Time flies like the wind. Fruit flies like a banana. Stranger things have .0. happened but none stranger than this. Does your driver's license say Organ ..0 Donor?Black holes are where God divided by zero. Listen to me! We are all- 000 individuals! What if this weren't a hypothetical question? steveo at syslang.net -BEGIN PGP SIGNATURE- Version: GnuPG v2.0.10 (GNU/Linux) Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org iEYEARECAAYFAkpaP+kACgkQRIVy4fC+NyRqtQCeLV5oscJqOGQ0zME7KXjvM8n2 HZsAn1OcpB0aif6K1rTbchwdV7GDzn7k =gJni -END PGP SIGNATURE- ___ gnhlug-discuss mailing list gnhlug-discuss@mail.gnhlug.org http://mail.gnhlug.org/mailman/listinfo/gnhlug-discuss/
Re: Perl vs. Python question...
Paul Lussier writes: > > Hi Folks, > > How do I create dynamically created methods in python classes? > > For example, if I have a number of member variables which I want to get > or set, I don't want to have to create getters and setters for each > attribute, since the code would largely be the same, just the variable > I'm dealing with would be different. Rather than implementing a whole bunch of similar `get_*()' and `set_*()' methods in Python, you can just define __getattr__() and __setattr__(): http://docs.python.org/reference/datamodel.html#object.__getattr__ How's that? Perfect fit? :) Alternately (e.g.: something other than `getters and setters'): can't you just create a single method that takes an `extra' parameter? Even if you really do really want to `lots of methods' interface, I'd still start with unified dispatcher-method--then the other methods would just be simple wrappers, e.g.: class C: def do_stuff(self, key, *args): print 'doing %s stuff...' % key do_x = lambda self, *args: self.do_stuff('x', *args) do_y = lambda self, *args: self.do_stuff('y', *args) do_z = lambda self, *args: self.do_stuff('z', *args) You could even set all of those `C.do_*' attributes (which become methods) automatically, e.g.: for key in ('xray', 'yankee', 'zulu'): def do_predispatched_stuff_stuff(self, *args): return self.do_stuff(key, *rags) setattr(C, key, do_predispatched_stuff) -- Don't be afraid to ask (Lf.((Lx.xx) (Lr.f(rr. ___ gnhlug-discuss mailing list gnhlug-discuss@mail.gnhlug.org http://mail.gnhlug.org/mailman/listinfo/gnhlug-discuss/