Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Code redundancy

1 view
Skip to first unread message

Alan Harris-Reid

unread,
Apr 20, 2010, 9:43:53 AM4/20/10
to Python List
Hi,

During my Python (3.1) programming I often find myself having to repeat
code such as...

class1.attr1 = 1
class1.attr2 = 2
class1.attr3 = 3
class1.attr4 = 4
etc.

Is there any way to achieve the same result without having to repeat the
class1 prefix? Before Python my previous main language was Visual
Foxpro, which had the syntax...

with class1
.attr1 = 1
.attr2 = 2
.attr3 = 3
.attr4 = 4
etc.
endwith

Is there any equivalent to this in Python?

Any help would be appreciated.

Alan Harris-Reid

Stefan Behnel

unread,
Apr 20, 2010, 10:25:07 AM4/20/10
to pytho...@python.org
Alan Harris-Reid, 20.04.2010 15:43:

> During my Python (3.1) programming I often find myself having to repeat
> code such as...
>
> class1.attr1 = 1
> class1.attr2 = 2
> class1.attr3 = 3
> class1.attr4 = 4
> etc.
>
> Is there any way to achieve the same result without having to repeat the
> class1 prefix? Before Python my previous main language was Visual
> Foxpro, which had the syntax...
>
> with class1
> .attr1 = 1
> .attr2 = 2
> .attr3 = 3
> .attr4 = 4
> etc.
> endwith
>
> Is there any equivalent to this in Python?

There's more than one way to do this, depending on your actual needs and
the source of the attributes. I assume this is done in __init__?

This might work for you:

self.__dict__.update(attr1=1, attr2=2, attr3=3, attr4=4)

You should also think once more about the use of the code you presented
above, having to set all those attributes may have a little smell. Maybe
that's totally ok, but since you mention that you "often" find yourself
doing the above, you may also have a mental design problem somewhere. We
can't tell unless you provide a more concrete example than what you show above.

Stefan

Iain King

unread,
Apr 20, 2010, 10:54:29 AM4/20/10
to
On Apr 20, 2:43 pm, Alan Harris-Reid <aharrisr...@googlemail.com>
wrote:

The pythonic equivalent of VB 'with' is to assign to a short variable
name, for example '_':

_ = class1
_.attr1 = 1
_.attr2 = 2
_.attr3 = 3
_.attr4 = 4

alternatively, you could use the __setattr__ method:

for attr, value in (
('attr1', 1),
('attr2', 2),
('attr3', 3),
('attr4', 4)):
class1.__setattr__(attr, value)

and to get a bit crunchy, with this your specific example can be
written:

for i in xrange(1, 5):
class1.__setattr__('attr%d' % i, i)

Iain

Peter Otten

unread,
Apr 20, 2010, 12:05:17 PM4/20/10
to
Alan Harris-Reid wrote:

No. You could write a helper function

>>> def update(obj, **kw):
... for k, v in kw.items():
... setattr(obj, k, v)
...

and then use keyword arguments:

>>> class A: pass
...
>>> a = A()
>>> update(a, foo=42, bar="yadda")
>>> a.foo, a.bar
(42, 'yadda')
>>>

But if you are doing that a lot and if the attributes are as uniform as
their names suggest you should rather use a Python dict than a custom class.

>>> d = {}
>>> d.update(foo=42, bar="whatever")
>>> d
{'foo': 42, 'bar': 'whatever'}
>>> d["bar"]
'whatever'

Peter

Jean-Michel Pichavant

unread,
Apr 20, 2010, 1:57:27 PM4/20/10
to Alan Harris-Reid, Python List
Alan Harris-Reid wrote:
> Hi,
>
> During my Python (3.1) programming I often find myself having to
> repeat code such as...
>
> class1.attr1 = 1
> class1.attr2 = 2
> class1.attr3 = 3
> class1.attr4 = 4
> etc.
>
> Is there any way to achieve the same result without having to repeat
> the class1 prefix? Before Python my previous main language was Visual
> Foxpro, which had the syntax...
>
> with class1
> .attr1 = 1
> .attr2 = 2
> .attr3 = 3
> .attr4 = 4
> etc.
> endwith
>
> Is there any equivalent to this in Python?
>
> Any help would be appreciated.
>
> Alan Harris-Reid
Hello,

Use an effective text editor, repeating stuff should not be a problem.
In a more general manner, avoid trying to speed your writing while you
should care speeding the reading.
Most of the tricks you could use will confuse the reader (unless the
reader is familiar with Visual foxpro).

Anyway,

for attrName, value in [


('attr1', 1),
('attr2', 2),
('attr3', 3),

]:
setattr(class1, attrName, value)

or

class Foo:
def __init__(self):
self.attr1=None
self.attr2=None
self.attr3=None

def set(self, *args, **kwargs):
for k in kwargs:
if hasattr(self, k):
setattr(self, k, kwargs[k])
else:
raise AttributeError('%s instance has no attribute "%s"' %
(self.__class__.__name__, k))

f = Foo()
f.set(attr1=25)
print f.__dict__
f.set(attr3=4, attr2=89)
print f.__dict__
f.set(bar= 8)

output:
{'attr2': None, 'attr3': None, 'attr1': 25}
{'attr2': 89, 'attr3': 4, 'attr1': 25}
AttributeError: Foo instance has no attribute "bar"


JM

Alan Harris-Reid

unread,
Apr 20, 2010, 5:26:59 PM4/20/10
to Jean-Michel Pichavant, Python List
Hi Jean-Michel,

Interesting solutions, but I think for the effort involved (and
readability) I'll stick to repeating the class.

Regards,
Alan

Alan Harris-Reid

unread,
Apr 20, 2010, 5:59:11 PM4/20/10
to Stefan Behnel, pytho...@python.org
Stefan Behnel wrote:
> <div class="moz-text-flowed">Alan Harris-Reid, 20.04.2010 15:43:

>> During my Python (3.1) programming I often find myself having to repeat
>> code such as...
>>
>> class1.attr1 = 1
>> class1.attr2 = 2
>> class1.attr3 = 3
>> class1.attr4 = 4
>> etc.
>>
>> Is there any way to achieve the same result without having to repeat the
>> class1 prefix? Before Python my previous main language was Visual
>> Foxpro, which had the syntax...
>>
>> with class1
>> .attr1 = 1
>> .attr2 = 2
>> .attr3 = 3
>> .attr4 = 4
>> etc.
>> endwith
>>
>> Is there any equivalent to this in Python?
>
> There's more than one way to do this, depending on your actual needs
> and the source of the attributes. I assume this is done in __init__?
>
> This might work for you:
>
> self.__dict__.update(attr1=1, attr2=2, attr3=3, attr4=4)
>
> You should also think once more about the use of the code you
> presented above, having to set all those attributes may have a little
> smell. Maybe that's totally ok, but since you mention that you "often"
> find yourself doing the above, you may also have a mental design
> problem somewhere. We can't tell unless you provide a more concrete
> example than what you show above.
>
> Stefan
Hi Stefan, thanks for the reply.

The code is not usually in class.__init__ (otherwise I would have used
the self. prefix), but I like your self.__dict__.update(...) solution
and I'll try and remember it.

The code I was thinking of goes something like as follows (don't have a
specific example to hand, but the principal is the same)...

NewClass = BaseClass()
NewClass.attr1 = value1
NewClass.attr2 = value2
NewClass.attr3 = value3
etc.

So if there are more than a couple of attributes to set for a class
instance, how would you approach it (short of passing the values as
parameters to BaseClass)?

Regards,
Alan

Chris Rebert

unread,
Apr 20, 2010, 6:29:50 PM4/20/10
to Alan Harris-Reid, pytho...@python.org, Stefan Behnel
On Tue, Apr 20, 2010 at 2:59 PM, Alan Harris-Reid
<aharr...@googlemail.com> wrote:

Why are you against passing them as parameters?
If your constructor would have a lot of parameters, it may be a sign that:
(A) you have some Data Clumps
(http://martinfowler.com/bliki/DataClump.html) among the parameters
that ought to be made into full objects
(B) your class is doing too many things and needs to be split into
multiple classes
(http://www.refactoring.com/catalog/extractClass.html)

Cheers,
Chris
--
Yay Refactoring!
http://blog.rebertia.com

Ethan Furman

unread,
Apr 20, 2010, 6:48:57 PM4/20/10
to Alan Harris-Reid, pytho...@python.org
Alan Harris-Reid wrote:
> The code is not usually in class.__init__ (otherwise I would have used
> the self. prefix), but I like your self.__dict__.update(...) solution
> and I'll try and remember it.
>
> The code I was thinking of goes something like as follows (don't have a
> specific example to hand, but the principal is the same)...
>
> NewClass = BaseClass()
> NewClass.attr1 = value1
> NewClass.attr2 = value2
> NewClass.attr3 = value3
> etc.
>
> So if there are more than a couple of attributes to set for a class
> instance, how would you approach it (short of passing the values as
> parameters to BaseClass)?

Unless I'm missing something (your use-case, perhaps? ;) in this example
NewClass is *not* a class -- it's an instance of BaseClass, and you are
dynamically adding attributes to it.

It's definitely a switch coming from FoxPro (me, too!), but it is well
worth it once your brain starts working pythonically.

~Ethan~

Alan Harris-Reid

unread,
Apr 20, 2010, 7:56:53 PM4/20/10
to Ethan Furman, pytho...@python.org
Hi Ethan,
You are correct - NewClass is an instance of BaseClass and I chose a
very bad class-name as an example.

Good to see ex-Fox people on this list. I have recently got stuck-into
learning Python after my last VFP contract finished last December - wish
I had started years ago. Really glad I went for Python, which I thought
would be the easiest transition from Foxpro (I looked at other
languages, but none came near to Python in terms of popularity and
developer-friendly syntax). What's your story?

Regards,
Alan

Jean-Michel Pichavant

unread,
Apr 21, 2010, 5:38:35 AM4/21/10
to Alan Harris-Reid, Python List
Alan Harris-Reid wrote:
> Jean-Michel Pichavant wrote:
>> Alan Harris-Reid wrote:
>>> Hi,
>>>
>>> During my Python (3.1) programming I often find myself having to
>>> repeat code such as...
>>>
>>> class1.attr1 = 1
>>> class1.attr2 = 2
>>> class1.attr3 = 3
>>> class1.attr4 = 4
>>> etc.
>>>
>>> Is there any way to achieve the same result without having to repeat
>>> the class1 prefix? Before Python my previous main language was
>>> Visual Foxpro, which had the syntax...
>>>
>>> with class1
>>> .attr1 = 1
>>> .attr2 = 2
>>> .attr3 = 3
>>> .attr4 = 4
>>> etc.
>>> endwith
>>>
>>> Is there any equivalent to this in Python?
>>>
that's the way to go :)

JM

Andreas Löscher

unread,
Apr 21, 2010, 6:03:57 AM4/21/10
to
You can do something like this:

>>> class A(): pass
>>> inst=A()
>>> exec("""
... a=1
... b=2
... c=3
... d=4
... """) in inst.__dict__
>>> inst.a
1
>>>

This executes the Statement in the exec function and uses inst.__dict__
as namespace. But be aware, that this is not recommended. If you mess
with __dict__, you won't be able to replace it with some logic
(parameter) if you need to do something more than setting a variable.

Best

Ryan Kelly

unread,
Apr 21, 2010, 6:33:10 PM4/21/10
to Alan Harris-Reid, Python List
On Tue, 2010-04-20 at 14:43 +0100, Alan Harris-Reid wrote:
> Hi,
>
> During my Python (3.1) programming I often find myself having to repeat
> code such as...
>
> class1.attr1 = 1
> class1.attr2 = 2
> class1.attr3 = 3
> class1.attr4 = 4
> etc.
>
> Is there any way to achieve the same result without having to repeat the
> class1 prefix? Before Python my previous main language was Visual
> Foxpro, which had the syntax...
>
> with class1
> .attr1 = 1
> .attr2 = 2
> .attr3 = 3
> .attr4 = 4
> etc.
> endwith
>
> Is there any equivalent to this in Python?


Please don't take this as in invitation to disregard the excellent
advice already received in this thread - I just want to point out that
python can usually be bent to your will. Observe:


from withhacks import namespace

with namespace(class1):
attr1 = 1
attr2 = 2


This will do pretty much what you get from the "with" statement in
javascript (I assume it's similar to Visual Foxpro).


But don't use this in any real code. Seriously, don't even think about
it. You don't want to know the kind of abuses that go on under the
covers to make this kind of syntax hacking work...

Cheers,

Ryan

--
Ryan Kelly
http://www.rfk.id.au | This message is digitally signed. Please visit
ry...@rfk.id.au | http://www.rfk.id.au/ramblings/gpg/ for details


pyt...@bdurham.com

unread,
Apr 21, 2010, 7:43:10 PM4/21/10
to Ryan Kelly, Alan Harris-Reid, Python List
Ryan,

Your withhacks module looks very interesting.
http://pypi.python.org/pypi/withhacks

What are your specific concerns about its use? Are there portability
concerns?

Malcolm


Ryan Kelly

unread,
Apr 21, 2010, 7:55:09 PM4/21/10
to pyt...@bdurham.com, Python List, Alan Harris-Reid


It combines two things you just don't see in respectable python programs
- bytecode hacking and trace-function hacking. And I'm sure its
performance is less than stellar, although much of that could be fixed
with some careful bytecode caching.

I'd be surprised if it runs under alternative python implementations,
and not surprised if it doesn't even work on Python 3 - although I
haven't tried it to confirm either way.

Having said that, it should work as advertised on Python 2.X with
minimal fuss. So if you don't care about portability or about that dirty
feeling you get from messing with the Python internals, then have at
it :-)

pyt...@bdurham.com

unread,
Apr 21, 2010, 9:09:50 PM4/21/10
to Ryan Kelly, Python List, Alan Harris-Reid
Ryan,

> So if you don't care about portability or about that dirty feeling you get from messing with the Python internals, then have at it :-)

Warnings aside, its very clever code. Thanks for sharing!

Malcolm

0 new messages