def foo(self) :
(a,b,c,d) = self.state()
... big code with a,b,c,d ...
This is probably not the best Python way to code, is it ?
Is there a simple way to get the *ordered* list of instance
variables as given in the parameter list of __init__ ? __dict__ gives it but not in order...
Thanks a lot,
On Sun, Oct 7, 2012 at 1:50 AM, Franck Ditter <fra...@ditter.org> wrote:
> Hi !
> Another question. When writing a class, I have often to
> destructure the state of an object as in :
> def foo(self) :
> (a,b,c,d) = (self.a,self.b,self.c,self.d)
> ... big code with a,b,c,d ...
I would generally strongly frown on doing that (at least if the
destructuring is actually that trivial). The "self."s are only 5
characters; that's hardly burdensome or verbose. Just write it out
each time, i.e.:
def foo(self):
… code with self.a, self.b, self.c, self.d ...
Or in the extreme case, use "s" instead of "self" (using the name
"self" is just a convention; it's not a language keyword or anything).
> def foo(self) :
> (a,b,c,d) = self.state()
> ... big code with a,b,c,d ...
> This is probably not the best Python way to code, is it ?
Indeed it isn't. Don't bother with the pointless destructuring.
And/or refactor your method so it's less big.
> Is there a simple way to get the *ordered* list of instance
> variables as given in the parameter list of __init__ ?
There is no guaranteed correspondence whatsoever between __init__()'s
parameters and the resulting object's instance variables. At a
minimum, such a hack would fail to account for instance variables that
are merely derived from the parameters (e.g. self.length =
len(some_list_param) ) or are initialized to constant values (e.g.
self.cache = {} ). And then there's private instance variables (e.g.
self._foo = foo_param ); if the parameter is named "_foo", you're
doing it wrong.
That said, you can obtain the names of the parameters using the
`inspect` module in the std lib.
On Sun, Oct 7, 2012 at 7:50 PM, Franck Ditter <fra...@ditter.org> wrote:
> def foo(self) :
> (a,b,c,d) = (self.a,self.b,self.c,self.d)
> ... big code with a,b,c,d ...
This strikes me as ripe for bug introduction. There's no problem if
you're just reading those values, and mutating them is equally fine,
but suddenly you need a different syntax for modifying instance
members.
def foo(self) :
(a,b,c,d) = (self.a,self.b,self.c,self.d)
e = a+b
c.append(1234)
d=self.d = 57 # Oops, mustn't forget to assign both!
Since Python lacks the extensive scoping rules of (say) C++, it's much
simpler and safer to be explicit about scope by adorning your instance
variable references with their "self." tags. There's a guarantee that
you can use "self.a" in any situation where you want to manipulate
that member, a guarantee that's not upheld by the local "a".
In theory, I suppose you could use a C-style preprocessor to help you.
class Foo(object):
#define asdf self.asdf
#define qwer self.qwer
This is not, however, Pythonic code. But if you made some kind of
better declaration than #define, and used a preprocessor that
understood Python indentation rules and flushed its token list at the
end of the class definition, you could perhaps make this look
not-ugly. I still wouldn't recommend it, though.
On Sun, 07 Oct 2012 10:50:38 +0200, Franck Ditter wrote:
> Hi !
> Another question. When writing a class, I have often to destructure the
> state of an object as in :
> def foo(self) :
> (a,b,c,d) = (self.a,self.b,self.c,self.d) > ... big code with a,b,c,d ...
There's your problem right there: "big code". Methods should be small, ideally no more than a dozen lines or so. In my experience, small methods that have a very tight focus on doing one thing make it much easier to write, debug and maintain the method, and as a bonus having to write "self.a" is less of a burden.
I've just looked at one of my classes, picked randomly, and the largest method is twelve lines, the second largest is eight, and the average is three lines.
> def foo(self) :
> (a,b,c,d) = self.state()
> ... big code with a,b,c,d ...
> This is probably not the best Python way to code, is it ?
Not really the best. But I've seen worse.
If you *have* to write "big code with a,b,c,d" then this is probably acceptable. But better to refactor your big method into smaller methods that don't need to use self.a, self.b, self.c, self.d so many times that writing them explicitly is a nuisance.
> Is there a
> simple way to get the *ordered* list of instance variables as given in
> the parameter list of __init__ ?
What you have written in method "state" is the simple way.
By the way, we prefer "instance attribute" or even "instance member" over "instance variable" here.
In article <507170e9$0$29978$c3e8da3$54964...@news.astraweb.com>,
Steven D'Aprano <steve+comp.lang.pyt...@pearwood.info> wrote:
> I've just looked at one of my classes, picked randomly, and the largest > method is twelve lines, the second largest is eight, and the average is > three lines.
I took a look at a subtree of the project I'm working on now. 116 python files, 20 kloc, 330 functions (mostly class methods). I did a quick-and-dirty "grep -n" job on them to find the line numbers of the def statements, then another quick-and-dirty python script to find the differences, and summarize. Results below (second column is length of 'def' block in lines, first column is number of blocks of that length).
This is just dumb line counting; no attempt to exclude block comments, white space, docstrings, etc.
There's three different authors represented here, but I'd guess 70% of the code is mine. Of the three, I'm probably the one who writes the most refactored code (i.e. smallest functions).
I just went and found the longest of these (193 lines). It starts with a 95 line block comment. Of the 100-or so lines of real code, I suppose with some effort it could have been refactored some, but not hugely.