473,395 Members | 1,869 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

idiom for constructor?

Mac
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.

Jul 19 '05 #1
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."
Jul 19 '05 #2
Mac
> 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.

Jul 19 '05 #3
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.

Jul 19 '05 #4
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...
Jul 19 '05 #5
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
Jul 19 '05 #6
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

Jul 19 '05 #7

"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


Jul 19 '05 #8
Mac
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).

Jul 19 '05 #9
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
Jul 19 '05 #10
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-

Jul 19 '05 #11
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
Jul 19 '05 #12
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'?
Jul 19 '05 #13
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

Jul 19 '05 #14
And you probably should add:

...
def __init__(self, *args):
assert len(args) == len(self.__slots__)
...

--T

Jul 19 '05 #15

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
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) :...
7
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...
10
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...
14
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...
6
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...
0
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...
0
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...
0
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
0
BarryA
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...
0
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...
0
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...
0
Oralloy
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,...
0
jinu1996
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...
0
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...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.