From: Alan Harris-Reid on
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
From: Chris Rebert on
On Tue, Apr 20, 2010 at 2:59 PM, Alan Harris-Reid
<aharrisreid(a)googlemail.com> wrote:
> Stefan Behnel wrote:
>> 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)?

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
From: Ethan Furman on
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~
From: Alan Harris-Reid on
Ethan Furman wrote:
> 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~
>
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

From: Jean-Michel Pichavant on
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?
>>>
>>> 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
>>
> Hi Jean-Michel,
>
> Interesting solutions, but I think for the effort involved (and
> readability) I'll stick to repeating the class.
>
> Regards,
> Alan
that's the way to go :)

JM