A lot to address here.
On Thu, May 22, 2008 at 9:43 AM, Calvin Spealman firstname.lastname@example.org wrote:
Start using those and suddenly you are going to have lots of little anonymous objects around and you'll start to want to add functionality to them and otherwise enforce things about them. Now you have a higher barrier than when you would have been creating it from scratch.
That wasn't my intended use case, though. I wouldn't be using an anonymous object in more than one place to create the same type of object. In that case, actually defining a class or using NamedTuple (or some equivalent) clearly wins out. This would be a similar situation to that of lambda. You would not use lambda in several different places to define the same function; as soon as you start to write it a second time, you'd be much better to def the function and use it in both places.
My main use case is in packing related information together for convenience and readability when passing it around to several different functions. In other words, the exact case where someone might be tempted to use a tuple (in spite of poor readability later) or a dict (in spite of a cumbersome access pattern). If you're using it for a case like this and you later decide that you should expand the anonymous object to a full-blown class, you would only have to change it in one place. Moreover, it would be much easier than changing a tuple or dict to a class. In the anonymous object situation, you only have to change the one instantiation; as long as you create a class with the same field names, your other accesses are still valid. In the tuple or dict cases, however, you have to change the code everywhere that you are using the object. Thus, I feel that having an anonymous object available actually lowers the barrier to making smart changes to the code.
and remember, object is not a function. It is a type. It is the base type of all types and so this has implications beyond what you suggest it for. If object(a=10).a == 10, then when custom classes' __init__ methods upcall, they'll start to fall back on letting kwargs fall up to object.__init__ to set initialization attributes. Now we gain this rule of thumb that keyword arguments are probably going to end up as attributes, because if we don't 'catch' them and they reach object.__init__, they will be. This isn't a behavior the language should encourage, because it should be left up to the developer. Currently, object.__init__ specifically takes any arguments and does nothing with any of them. This is to allow upcall in your __init__ gracefully, because if the upclass is one of your bases or the final base, object, you can still pass your parameters along safely. Implying some behavior when it reaches object.__init__, especially (in most cases) after you've initialized your object, would probably just trounce all over your object and piss you off.
This is a very good argument for why object() should not be used for this purpose; you have completely changed my mind. I still think there would be value in having a built-in function for declaring such objects. Perhaps a function (constructor) named struct(**kwargs) would be appropriate?
On Thu, May 22, 2008 at 8:22 AM, Aahz email@example.com wrote:
Enh. It's easy enough to write
class Obj: def __init__(self, **kwargs): self.__dict__.update(kwargs)
Yes, it is easy enough, once you have worked with Python a lot. Personally, I didn't know much at all about __dict__ or **kwargs when I first started, and looking back at my old code now, there are several places where I have used tuples or dicts and the code is hard to manage. Having a struct type to hold related information which does not justify a full class would have been very nice.
It's not clear to me that your functionality is desired frequently enough *in that specific form* to warrant changing object(). Note particularly the emphasis; over the years, I've seen various small variations in how people want kwargs processed and it's not at all clear to me that codifying one specific form into the language would be helpful. No thanks.
This is another good argument for why object() should not be used for this purpose. I still think that adding a new type "struct" would have several benefits.
NamedList, NamedDict, NamedTuple...
I agree that these are very useful functions to have when what you really want to do is just subclass the indicated type. For the use case I have in mind, however, they have much more functionality (and take up more space?) than necessary, and specifically having to decide on and declare a name that will never be used constitutes wasted effort.
I will be sending out a new reply with my updated proposal, using the name "struct" instead of multi-purposing object, as that is clearly a bad idea.
Thanks for all the constructive criticism and feedback, Brandon