
It is currently somewhat difficult/awkward to create arbitrary "anonymous" objects in Python. For example, to make some object that simply has a foo() method you have to declare a class that defines foo() and instantiate it: class Foo: def foo(self, x): return x obj = Foo() It would be a bit easier if Python allowed attributes to be set on instances of builtins the way it does for user-defined classes. This would at least allow something like: obj = object() obj.foo = lambda x: x Alas, that is not possible either as the assignment raises an AttributeError when dealing with instances of builtins. I would like to propose a different solution: alter object.__new__() to support keyword arguments and set the attributes named in the keyword arguments to their requested value. This would get us code like: obj = object(foo=1, bar=lambda x: x) obj.foo
Python implementation of __new__ would look something like the following, though I suppose this would need to be done at the C level in reality: def __new__(typ, **kwargs): obj = object.__new__(typ) for attr, value in kwargs.items(): setattr(obj, attr, value) return obj So why do we need this? Primarily, this sort of thing is very common in tests where it is often useful to generate anonymous objects with default values. As a result, a number of libraries have risen to fill this need which is a pretty strong indicator that it is a useful pattern, and everyone using one of a dozen different libraries to accomplish the same basic task does not seem very Pythonic. I could also see this being quite useful in quick prototyping scenarios in order to avoid using dicts when an object is more suitable without requiring the overhead of defining a class. I'm curious if people on this list would be interested in seeing support for this added to the language, or if there are some good reasons I have overlooked for why this sort of change might be undesirable. Cheers, -Herman

On Sun, 24 Jul 2011 23:04:53 +0900 Herman Sheremetyev <herman@swebpage.com> wrote:
[...]
obj = object() obj.foo = lambda x: x
Well, really, you're saving *one* line of code all the while making things more obscure (if "obj" gets printed out for whatever reason, you won't ever know it's a Foo or has a foo method).
If that's all you need, you just have to write a convenience function that you put in some utilities module: class AnonymousObject: pass def make(**kwargs): obj = AnonymousObject() for k, v in kwargs.items(): setattr(obj, k, v) return obj and then:
Or you can also create a namedtuple class, if there's a well-defined set of attributes your instance(s) will have. Regards Antoine.

Herman Sheremetyev wrote:
I'm not sure that "anonymous" is the right word here. Normally when we talk about "anonymous", it is in reference to functions and classes, which have a name given them at creation time. In that sense, early all objects in Python are anonymous: few objects have a __name__ attribute. It seems to me that the name, or lack thereof, of the object is irrelevant to what you propose. Essentially, you want a one-liner for the pattern: class MyObject(object): pass obj = MyObject() obj.spam = "spam spam spam"
It might be more convincing if you could give examples of those libraries.
Against the idea, it's a very simple helper class that you can add to your library or application: class MyObject(object): def __init__(self, **kwargs): self.__dict__.update(kwargs) Three lines, and now you can use it as a one-liner any time you want it: obj = MyObject(flag=True, count=1) In favour of the idea of making it built-in, or at least in the standard library: if this pattern is as common as you say, perhaps there should be a standard solution for it, instead of a plethora of almost, but not quite identical versions. After all, that is one of the main reasons we have bool as a built-in. Also in favour: the implementation given may be slightly *too* simple. It doesn't have a nice repr(). There's no validation of the keyword arguments (although I'm not entirely sure they need validating). The more code needed to make it "professional", the better the argument for doing it once, right, in the standard library. I don't think this needs to be object itself. Doing so probably will cause backwards incompatibility issues -- I'm sure that there will be code out there that expects object(attr="spam") to fail. Better to make a new type. +0.5 on a new type for this, not necessarily a built-in. -1 on changing object to behave this way. -- Steven

On Sun, Jul 24, 2011 at 7:04 AM, Herman Sheremetyev <herman@swebpage.com> wrote:
It is currently somewhat difficult/awkward to create arbitrary "anonymous" objects in Python.
It looks like you are trying to duplicate Java's anonymous classes. Please don't try to emulate Java's work-arounds for Java's deficiencies. -- --Guido van Rossum (python.org/~guido)

On Mon, Jul 25, 2011 at 12:06 AM, Guido van Rossum <guido@python.org> wrote:
Ouch, and I don't even know Java well enough to deserve that ;) I think a more accurate characterization would be that I'm trying to emulate Javascript's object literal notation, but I was trying to avoid parallels with other languages in my proposal. FWIW, I think it would be fine if this was a convenience function in the standard library as suggested above. But it seems so basic that having it supported in in the object() constructor would be the most natural place rather than tucking it away in a library. -Herman

On Sun, Jul 24, 2011 at 8:35 AM, Herman Sheremetyev <herman@swebpage.com> wrote:
Ah, sorry.
Still, IMO Javascript's objects suffer from a fatal confusion between being dicts and objects, so I still "object" to the idea. :-)
Python's object is supposed to have only the minimal functionality. Its instances don't even have a __dict__. Also, every one believes there own favorite feature to be so important that it's worth changing the language, but they don't want to grant that to anybody else's favorite feature... :-) -- --Guido van Rossum (python.org/~guido)

On Mon, Jul 25, 2011 at 2:03 AM, Guido van Rossum <guido@python.org> wrote:
We've actually been down the 'namespace object' road years ago (Steve Bethard even wrote a proto-PEP IIRC) and it suffered the same fate as most enum PEPs: everyone has slightly different ideas on what should be supported, so you end up being faced with one of two options: 1. Ignore some of the use cases (so some users still have to do their own thing) 2. Support all of the use cases by increasing the API complexity (so many users will still do their own thing instead of learning the new API) In this space, collections.namedtuple is a well-executed variant of the first alternative. There are some use cases it doesn't handle, but it covers many of them and does it well. For the OP's use case, I'll simply note that this functionality is already provided by the type builtin: obj = type('Foo', (), dict(foo=(lambda x: x)))() Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

You could use a class decorator to help with this. def instance(cls): return cls() @instance class foo(object): x = 42 -- Greg

On Mon, Jul 25, 2011 at 7:47 AM, Nick Coghlan <ncoghlan@gmail.com> wrote:
This one-liner with type is neat. For the record, it's missing "self" so a working version would be a tad bit longer. Using an empty name and using {} instead of dict() makes it look almost usable: obj = type('', (), {'foo': lambda self, x: x})() I think it would actually *be* usable if the dictionary passed in as the last argument could also be built out of keyword arguments: obj = type('', (), foo=lambda self, x: x)() Giving those first two positional arguments default values (empty string and empty tuple?) would make it even better: obj = type(foo=lambda self, x: x)() That's only one set of parens away from my initial proposal, but I think it's close enough. Would there be any objections to changing the type() API to support this? Cheers, -Herman

On Mon, Jul 25, 2011 at 1:03 AM, Guido van Rossum <guido@python.org> wrote:
What if there was a base "dummy" class that would allow this kind of behavior as Steven suggested? My choice of object was simply because it seems like the logical choice among the builtins and to get a discussion going about the idea of creating objects as an expression rather than statement, without resorting to defining a new class just for that purpose. For a short list of libraries that do this sort of thing (not all of them support expression syntax) take a look at the "Simple fake object" section in: http://garybernhardt.github.com/python-mock-comparison/ Disclaimer: I'm the author of the flexmock library listed there. There are also probably another half dozen libraries no longer being maintained that are not listed there but have similar functionality that can be found here: http://pycheesecake.org/wiki/PythonTestingToolsTaxonomy#MockTestingTools As well as a couple of new ones, like Chai, that aren't listed in the testing taxonomy but solve the same problem. Cheers, -Herman

On Jul 24, 2011, at 09:03 AM, Guido van Rossum wrote:
This reminds me of the poll you conducted at a keynote, many Pycons ago. You first asked "who thinks the language is changing too quickly?" Lots of hands went up. Then you asked (probably paraphrasing) "who has a feature they think needs to go into Python?" Lots of the same hands went up. :) -Barry

On Tue, Jul 26, 2011 at 2:52 AM, Barry Warsaw <barry@python.org> wrote:
Heh, I used the exact same point as my first section heading when blogging about some of the reasons I think python-dev is the way it is: "Python evolves too slowly! You're changing the language too fast!" (http://www.boredomandlaziness.org/2011/04/musings-on-culture-of-python-dev.h...). Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

On Thu, Aug 4, 2011 at 2:17 AM, dag.odenhall@gmail.com <dag.odenhall@gmail.com> wrote:
Good find, who'd have ever thought to look in argparse for something like Namespace.. After some more poking around in the stdlib for __init__ methods that take keyword args I found: plistlib.Dict and plistlib.Plist Both of them do the same thing as well as give access to the values using [] notation. There are probably other examples in third party libraries. -Herman

On Wed, Aug 3, 2011 at 11:49 PM, Herman Sheremetyev <herman@swebpage.com> wrote:
Sure. Another stdlib-ish example is Sphinx, which does it in sphinx.util.attrdict. And you can search google code for 'self.__dict__ = self', which reveals a particular(ly nasty) pattern for it with many instances. Devin On Wed, Aug 3, 2011 at 11:49 PM, Herman Sheremetyev <herman@swebpage.com> wrote:

On Sun, 24 Jul 2011 23:04:53 +0900 Herman Sheremetyev <herman@swebpage.com> wrote:
[...]
obj = object() obj.foo = lambda x: x
Well, really, you're saving *one* line of code all the while making things more obscure (if "obj" gets printed out for whatever reason, you won't ever know it's a Foo or has a foo method).
If that's all you need, you just have to write a convenience function that you put in some utilities module: class AnonymousObject: pass def make(**kwargs): obj = AnonymousObject() for k, v in kwargs.items(): setattr(obj, k, v) return obj and then:
Or you can also create a namedtuple class, if there's a well-defined set of attributes your instance(s) will have. Regards Antoine.

Herman Sheremetyev wrote:
I'm not sure that "anonymous" is the right word here. Normally when we talk about "anonymous", it is in reference to functions and classes, which have a name given them at creation time. In that sense, early all objects in Python are anonymous: few objects have a __name__ attribute. It seems to me that the name, or lack thereof, of the object is irrelevant to what you propose. Essentially, you want a one-liner for the pattern: class MyObject(object): pass obj = MyObject() obj.spam = "spam spam spam"
It might be more convincing if you could give examples of those libraries.
Against the idea, it's a very simple helper class that you can add to your library or application: class MyObject(object): def __init__(self, **kwargs): self.__dict__.update(kwargs) Three lines, and now you can use it as a one-liner any time you want it: obj = MyObject(flag=True, count=1) In favour of the idea of making it built-in, or at least in the standard library: if this pattern is as common as you say, perhaps there should be a standard solution for it, instead of a plethora of almost, but not quite identical versions. After all, that is one of the main reasons we have bool as a built-in. Also in favour: the implementation given may be slightly *too* simple. It doesn't have a nice repr(). There's no validation of the keyword arguments (although I'm not entirely sure they need validating). The more code needed to make it "professional", the better the argument for doing it once, right, in the standard library. I don't think this needs to be object itself. Doing so probably will cause backwards incompatibility issues -- I'm sure that there will be code out there that expects object(attr="spam") to fail. Better to make a new type. +0.5 on a new type for this, not necessarily a built-in. -1 on changing object to behave this way. -- Steven

On Sun, Jul 24, 2011 at 7:04 AM, Herman Sheremetyev <herman@swebpage.com> wrote:
It is currently somewhat difficult/awkward to create arbitrary "anonymous" objects in Python.
It looks like you are trying to duplicate Java's anonymous classes. Please don't try to emulate Java's work-arounds for Java's deficiencies. -- --Guido van Rossum (python.org/~guido)

On Mon, Jul 25, 2011 at 12:06 AM, Guido van Rossum <guido@python.org> wrote:
Ouch, and I don't even know Java well enough to deserve that ;) I think a more accurate characterization would be that I'm trying to emulate Javascript's object literal notation, but I was trying to avoid parallels with other languages in my proposal. FWIW, I think it would be fine if this was a convenience function in the standard library as suggested above. But it seems so basic that having it supported in in the object() constructor would be the most natural place rather than tucking it away in a library. -Herman

On Sun, Jul 24, 2011 at 8:35 AM, Herman Sheremetyev <herman@swebpage.com> wrote:
Ah, sorry.
Still, IMO Javascript's objects suffer from a fatal confusion between being dicts and objects, so I still "object" to the idea. :-)
Python's object is supposed to have only the minimal functionality. Its instances don't even have a __dict__. Also, every one believes there own favorite feature to be so important that it's worth changing the language, but they don't want to grant that to anybody else's favorite feature... :-) -- --Guido van Rossum (python.org/~guido)

On Mon, Jul 25, 2011 at 2:03 AM, Guido van Rossum <guido@python.org> wrote:
We've actually been down the 'namespace object' road years ago (Steve Bethard even wrote a proto-PEP IIRC) and it suffered the same fate as most enum PEPs: everyone has slightly different ideas on what should be supported, so you end up being faced with one of two options: 1. Ignore some of the use cases (so some users still have to do their own thing) 2. Support all of the use cases by increasing the API complexity (so many users will still do their own thing instead of learning the new API) In this space, collections.namedtuple is a well-executed variant of the first alternative. There are some use cases it doesn't handle, but it covers many of them and does it well. For the OP's use case, I'll simply note that this functionality is already provided by the type builtin: obj = type('Foo', (), dict(foo=(lambda x: x)))() Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

You could use a class decorator to help with this. def instance(cls): return cls() @instance class foo(object): x = 42 -- Greg

On Mon, Jul 25, 2011 at 7:47 AM, Nick Coghlan <ncoghlan@gmail.com> wrote:
This one-liner with type is neat. For the record, it's missing "self" so a working version would be a tad bit longer. Using an empty name and using {} instead of dict() makes it look almost usable: obj = type('', (), {'foo': lambda self, x: x})() I think it would actually *be* usable if the dictionary passed in as the last argument could also be built out of keyword arguments: obj = type('', (), foo=lambda self, x: x)() Giving those first two positional arguments default values (empty string and empty tuple?) would make it even better: obj = type(foo=lambda self, x: x)() That's only one set of parens away from my initial proposal, but I think it's close enough. Would there be any objections to changing the type() API to support this? Cheers, -Herman

On Mon, Jul 25, 2011 at 1:03 AM, Guido van Rossum <guido@python.org> wrote:
What if there was a base "dummy" class that would allow this kind of behavior as Steven suggested? My choice of object was simply because it seems like the logical choice among the builtins and to get a discussion going about the idea of creating objects as an expression rather than statement, without resorting to defining a new class just for that purpose. For a short list of libraries that do this sort of thing (not all of them support expression syntax) take a look at the "Simple fake object" section in: http://garybernhardt.github.com/python-mock-comparison/ Disclaimer: I'm the author of the flexmock library listed there. There are also probably another half dozen libraries no longer being maintained that are not listed there but have similar functionality that can be found here: http://pycheesecake.org/wiki/PythonTestingToolsTaxonomy#MockTestingTools As well as a couple of new ones, like Chai, that aren't listed in the testing taxonomy but solve the same problem. Cheers, -Herman

On Jul 24, 2011, at 09:03 AM, Guido van Rossum wrote:
This reminds me of the poll you conducted at a keynote, many Pycons ago. You first asked "who thinks the language is changing too quickly?" Lots of hands went up. Then you asked (probably paraphrasing) "who has a feature they think needs to go into Python?" Lots of the same hands went up. :) -Barry

On Tue, Jul 26, 2011 at 2:52 AM, Barry Warsaw <barry@python.org> wrote:
Heh, I used the exact same point as my first section heading when blogging about some of the reasons I think python-dev is the way it is: "Python evolves too slowly! You're changing the language too fast!" (http://www.boredomandlaziness.org/2011/04/musings-on-culture-of-python-dev.h...). Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

On Thu, Aug 4, 2011 at 2:17 AM, dag.odenhall@gmail.com <dag.odenhall@gmail.com> wrote:
Good find, who'd have ever thought to look in argparse for something like Namespace.. After some more poking around in the stdlib for __init__ methods that take keyword args I found: plistlib.Dict and plistlib.Plist Both of them do the same thing as well as give access to the values using [] notation. There are probably other examples in third party libraries. -Herman

On Wed, Aug 3, 2011 at 11:49 PM, Herman Sheremetyev <herman@swebpage.com> wrote:
Sure. Another stdlib-ish example is Sphinx, which does it in sphinx.util.attrdict. And you can search google code for 'self.__dict__ = self', which reveals a particular(ly nasty) pattern for it with many instances. Devin On Wed, Aug 3, 2011 at 11:49 PM, Herman Sheremetyev <herman@swebpage.com> wrote:
participants (14)
-
Antoine Pitrou
-
Barry Warsaw
-
Chris Rebert
-
dag.odenhall@gmail.com
-
Devin Jeanpierre
-
Eric V. Smith
-
Georg Brandl
-
Greg Ewing
-
Guido van Rossum
-
Herman Sheremetyev
-
Masklinn
-
Nick Coghlan
-
Raymond Hettinger
-
Steven D'Aprano