self.__dict__ tricks

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Sat Oct 31 03:37:10 CET 2009


On Fri, 30 Oct 2009 11:16:29 -0500, Tim Johnson wrote:

> On 2009-10-30, Steven D'Aprano <steve at REMOVE-THIS-cybersource.com.au>
> wrote:
>>
>> Could you explain what problem you are trying to solve?
>>
>>
>>> class formLoader():
>  
>   Hi Steve
>   In a nutshell:
>   The 'problem' is to parse a form in such a way that tags which are to
>   be modified are represented as dictionaries. The 'grunt' work is done.
>    This class will probably grow with time.

The standard way of doing this is to list the arguments as parameters, 
together with their defaults:

def __init__(self, filename=None, record=None, string=None):
    ...


Then Python will do the error checking for your, and raise an exception 
if the caller passes an unexpected argument. Can you explain why this 
isn't enough for your needs, and you need to do something else?


>> Idiomatic Python is to use CamelCase for classes.
>   Can you point me to a discussion on Idiomatic Python, CamelCase and
>   other matters?

See PEP 8:

http://www.python.org/dev/peps/pep-0008/



>> In my opinion, AttributeError is not appropriate here. Passing an
>> invalid parameter shouldn't raise the same error as failing an
>> attribute look-up. That's misleading and confusing.
>
> What error class or other approach do you recommend?

Unless you have a good reason for doing something different, do what 
Python built-ins do:

>>> int('123', parrot=16)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'parrot' is an invalid keyword argument for this function


>> I also should point out that your trick will fail if you are using
>> __slots__.
>   ??. Will research that. Elaborate if you wish.

__slots__ are an optimization for making objects smaller than normal if 
you have many millions of them:

http://docs.python.org/reference/datamodel.html#slots


>   If the class grows - and I expect it will - I'd prefer to stick with
>   the keywords approach. That approach also allows me to use a
>   dictionary to initialize the object.

You can still do that with named parameters.


>>> class Parrot:
...     def __init__(self, name='Polly', colour='blue',
...     breed='Norwegian'):
...         self.name = name
...         self.colour = colour
...         self.breed = breed
...     def speak(self):
...         print "%s the %s %s says 'Give us a kiss!'" % (
...         self.name, self.colour, self.breed)
...
>>> p = Parrot("Sparky", 'white', "Cockatoo")
>>> p.speak()
Sparky the white Cockatoo says 'Give us a kiss!'
>>>
>>> data = dict(colour='red', name='Fred', foo=1)
>>> p = Parrot(**data)  # raise an error with bad input
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __init__() got an unexpected keyword argument 'foo'
>>> 
>>> del data['foo']  # fix the bad input
>>> p = Parrot(**data)
>>> p.speak()
Fred the red Norwegian says 'Give us a kiss!'


-- 
Steven



More information about the Python-list mailing list