Is there a nice Python idiom for constructors which would expedite the
following?
class Foo:
def __init__(self, a,b,c,d,...):
self.a = a
self.b = b
self.c = c
self.d = d
...
I would like to keep the __init__ parameter list explicit, as is,
rather than passing in a dictionary, as I want the code to be explicit
about what arguments it expects... in effect enforcing the right number
of arguments. 14 1395
"Mac" <id******************@yahoo.com> writes: Is there a nice Python idiom for constructors which would expedite the following?
class Foo: def __init__(self, a,b,c,d,...): self.a = a ...
You could try:
class Foo:
def __init__(self,a,b,c,d):
args = locals()
for arg in args.keys():
if name!='self':
self.__dict__[arg] = args[arg]
I don't think it saves you a whole lot of typing (and gains you a lot
of ugly complexity). I find as soon as I do this, I then want to
manipulate a,b,c,d .
You might look to see if you can customize your editor to use
templates/interaction and then inserts the right text for you.
--
Chris Green <cm*****@uab.edu>
"Yeah, but you're taking the universe out of context."
> You might look to see if you can customize your editor to use templates/interaction and then inserts the right text for you.
Well, I'm not really concerned with "amount of typing" as much as with
the inherent ugliness, tediousness, and lack of elegance of the
original form. Alas, templates/macros would not fix the latter.
Mac wrote: Is there a nice Python idiom for constructors which would expedite the following?
class Foo: def __init__(self, a,b,c,d,...): self.a = a self.b = b self.c = c self.d = d ...
I would like to keep the __init__ parameter list explicit, as is, rather than passing in a dictionary, as I want the code to be explicit about what arguments it expects... in effect enforcing the right number of arguments.
I could list the parameter names programatically:
class A(object):
def __init__(self,a,b,c,d,e,f,):
varnames = self.__init__.im_func.func_code.co_varnames
for varname in varnames[1:7]:
print varname
a = A(1,2,3,4,5,6)
But I could not get their values. You could try:
class Foo: def __init__(self,a,b,c,d): args = locals() for arg in args.keys(): if name!='self': self.__dict__[arg] = args[arg]
Should be:
if arg!='self'
Also it is not perfect. For example:
class Foo:
def __init__(self,a,b,c,d):
temp = 12
self.foo2 = temp + 4
args = locals()
for arg in args.keys():
if arg!='self':
self.__dict__[arg] = args[arg]
a = Foo(1,2,3,4)
print dir(a)
Results in:
['__doc__', '__init__', '__module__', 'a', 'b', 'c', 'd', 'foo2', 'temp']
E.g. not only the parameters but all local variables are used...
Mac wrote: Is there a nice Python idiom for constructors which would expedite the following?
class Foo: def __init__(self, a,b,c,d,...): self.a = a self.b = b self.c = c self.d = d ...
py> class Foo(object):
.... def __init__(self, a, b, c, d):
.... params = locals()
.... del params['self']
.... self.__dict__.update(params)
....
py> vars(Foo(1, 2, 3, 4))
{'a': 1, 'c': 3, 'b': 2, 'd': 4}
Just make sure that "params = locals()" is the first line in __init__
method. (Otherwise you might have other local variables slip in there.)
I wouldn't actually advise this code to anyone though. I find that if I
have more than 3 or 4 parameters to a function, I should probably
refactor my code. And with 4 or fewer parameters, I don't think you
gain any clarity by using the "self.__dict__.update" trick.
STeVe
On Wednesday 01 June 2005 12:50 pm, Mac wrote: Is there a nice Python idiom for constructors which would expedite the following?
class Foo: def __init__(self, a,b,c,d,...): self.a = a self.b = b self.c = c self.d = d ...
I would like to keep the __init__ parameter list explicit, as is, rather than passing in a dictionary, as I want the code to be explicit about what arguments it expects... in effect enforcing the right number of arguments.
Well, it's hard to automate it and keep the parameter list explicit,
but you could do this, of course:
class Foo:
def __init__(self, *args):
maps = zip(('a','b','c','d'), args[:4])
for map in maps:
setattr(self, map[0], map[1])
Which *will* limit the arguments to the ones specified. As an additional
tweak, you could make this a base class and put the argument list in
the subclass to hide the magic:
class Args:
argspec = ()
def __init__(self, *args):
maps = zip(self.argspec, args[:len(self.argspec)])
for map in maps:
setattr(self, map[0], map[1])
class Foo(Args):
argspec = ('a', 'b', 'c', 'd')
Or even better, use a method, so you can customize:
class Args:
argspec = ()
def _get_args(self, *args):
maps = zip(self.argspec, args[:len(self.argspec)])
for map in maps:
setattr(self, map[0], map[1])
class Foo(Args):
argspec = ('a', 'b', 'c', 'd')
def __init__(self, *args):
self._get_args(*args)
This version silently ignores extra arguments, but you might
want to raise an exception instead:
class Args:
argspec = ()
def _get_args(self, *args):
expected = len(self.argspec)
given = len(args)
if expected != given:
raise TypeError("__init__ takes exactly %d arguments (%d given)" % (expected, given))
maps = zip(self.argspec, args[:expected])
for map in maps:
setattr(self, map[0], map[1])
Using this, I get the following response to too many arguments: g = Foo(1, '3', 4.0, 'spam', 'eggs') Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 4, in __init__
File "<stdin>", line 7, in _get_args
TypeError: __init__ takes exactly 4 arguments (5 given)
HTH
Cheers,
Terry
--
Terry Hancock ( hancock at anansispaceworks.com )
Anansi Spaceworks http://www.anansispaceworks.com
"Mac" <id******************@yahoo.com> wrote in message
news:11*********************@f14g2000cwb.googlegro ups.com... Is there a nice Python idiom for constructors which would expedite the following?
class Foo: def __init__(self, a,b,c,d,...): self.a = a self.b = b self.c = c self.d = d
Do you like this better?
self.a, self.b, self.c, self.d = a,b,c,d
For my own code, I might use 's' instead of 'self' to save typing...
Terry J. Reedy
This was the direction I was aiming for initially, and I have used this
form before, but was hoping there was a way I could go one step
further, and somehow get rid of the repetition of "self."... Heh,
ideally:
self.{a,b,c,d} = a,b,c,d
Alas, not Python syntax... :)
I do like Steven's form of a solution, and I think I'll give it a spin
for the really ugly spots (refactoring is too expensive right now;
prototype-code).
Steven Bethard <st************@gmail.com> writes: Mac wrote: Is there a nice Python idiom for constructors which would expedite the following? class Foo: def __init__(self, a,b,c,d,...): self.a = a self.b = b self.c = c self.d = d ...
py> class Foo(object): ... def __init__(self, a, b, c, d): ... params = locals() ... del params['self'] ... self.__dict__.update(params) ... py> vars(Foo(1, 2, 3, 4)) {'a': 1, 'c': 3, 'b': 2, 'd': 4}
Just make sure that "params = locals()" is the first line in __init__ method. (Otherwise you might have other local variables slip in there.)
Or write it like this, using Python's dynamic code execution:
#v+
class A:
def __init__(self, a, b, c, d):
initial = {'a' : 1, 'b' : 2, 'c' : 3, 'd' : 4}
for param in initial.keys():
exec "self.%s = initial['%s']" % (param, param)
#v-
-- http://www.peter.dembinski.prv.pl
Peter Dembinski <pd***@gazeta.pl> writes:
[snap]
Eh, sorry, it should look like this: #v+
class A: def __init__(self, a, b, c, d): initial = {'a' : 1, 'b' : 2, 'c' : 3, 'd' : 4}
initial = {'a' : a, 'b' : b, 'c' : c, 'd' : d} for param in initial.keys(): exec "self.%s = initial['%s']" % (param, param)
#v-
Peter Dembinski wrote: class A: def __init__(self, a, b, c, d): initial = {'a' : a, 'b' : b, 'c' : c, 'd' : d} for param in initial.keys(): exec "self.%s = initial['%s']" % (param, param)
This is not a good use case for exec. Use setattr:
for param in initial:
setattr(self, param, initial[param])
Or better yet, just update the instance dict:
self.__dict__.update(initial)
But this misses the OP's point. The issues was that the OP didn't want
to write a, b, c and d again. Not only does this proposal make you
write them again, it makes you write them again twice!
STeVe
Steven Bethard <st************@gmail.com> writes: Peter Dembinski wrote:class A: def __init__(self, a, b, c, d): initial = {'a' : a, 'b' : b, 'c' : c, 'd' : d} for param in initial.keys(): exec "self.%s = initial['%s']" % (param, param)
This is not a good use case for exec. Use setattr:
OK, true.
From the other side: what are the usual uses of 'exec'?
How about just doing this:
class Foo(object):
__slots__ = ('a','b','c','d')
def __init__(self, *args):
for (name, arg) in zip(self.__slots__, args):
setattr(self, name, arg)
--T
And you probably should add:
...
def __init__(self, *args):
assert len(args) == len(self.__slots__)
...
--T This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Siemel Naran |
last post by:
What is a good idiom for handling a lazy object? I see 2 good
possibilities. Any more, any comments? Which way do people here use?
(1)
class Thing {
public:
Thing(double x, double y) :...
|
by: Mikhail N. Kupchik |
last post by:
Hi All.
I have a question regarding Herb Sutter's idiom of implementation of
operator= via nonthrowing swap() member function, to guarantee strict
exception safety.
The idea of the idiom is...
|
by: Steve |
last post by:
Hi,
I thought I had invented a pretty neat solution for my problem, but it turns
out I'm using the named constructor idiom. :-)
I've seen examples where empty structs are used to identify the...
|
by: Daniel Lidström |
last post by:
Hello!
I have just discovered a way to use the private implementation idiom
(pimpl), without the overhead of dynamic memory allocation. For those of
you who don't know what this is, Wikipedia...
|
by: PLS |
last post by:
I'm converting a piece of c++ code to C#. There's one part I'm having a
problem with.
There is a class A which can be created only by calling a class factory
method on object B. Things won't...
|
by: ryjfgjl |
last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
|
by: ryjfgjl |
last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
|
by: emmanuelkatto |
last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud.
Please let me know.
Thanks!
Emmanuel
|
by: BarryA |
last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
|
by: Hystou |
last post by:
There are some requirements for setting up RAID:
1. The motherboard and BIOS support RAID configuration.
2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers,...
|
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
|
by: Hystou |
last post by:
Overview:
Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
| |