When a name is bound to an object, the object doesn't hear about it, usually. The exceptions I could think of are class and function definitions, and imports. Also, you can sneak around it using setattr/descriptors if you control the class... However, objects are otherwise (and generally) blind to their names. This is relevant when you want an object to be aware of the contexts in which it exists. It also relates to DRY issues that people bring up sometimes with regards to descriptors and namedtuple (though I'm not sure its that big a deal). Here are three approaches that satisfy this situation: 1. have assignment automatically pass the name to the __init__ when binding a new instance. 2. bind the name to __name__ on the object before calling __init__. 3. call __bound__(self, name, obj) on the object before __init__ is called (or maybe after). The first is the approach import/class/def take. You can't really generalize that, though, since most classes don't have a name parameter. Both the first and second approach only work when the object to be bound is instantiated. The second seems to work better than the first, but __name__ shouldn't be re-bound on an object every time it is involved in an assignment. It might be a good special-case, though. I like the third option because it could be tried for any name binding, from assignment to function arguments. However, that may be its downfall too. I would guess that name binding happens more than just once or twice during the course of execution <wink>. I would also guess that it would kill performance. However, I don't know the ins and outs of the compiler/runtime so I could be pleasantly wrong. In addition to __bound__, an __unbound__ could be leveraged (wait for it) to let an object know when it has been unbound from a name (during del or when another object is bound to the name). Of course you get double the performance hit from just __bound__. Like most things, this can already be done, just not cleanly. Here's an example of more or less equivalent code: class Something: def __init__(self): self._names = set() def __bound__(self, name, obj): if (name, obj) in set: return self._names.add((name, obj)) def __unbound__(self, name, obj): self._names.remove((name, obj)) obj = __import__(__file__.rsplit(".py", 1)[0]) something = Something() something.__bound__("something", obj) something.__unbound__("something", obj) something = Something() something.__bound__("something", obj) something.__unbound__("something", obj) del something So you can do it already, explicitly, but it's a mess. I wouldn't be surprised if there was a way to be smarter about when to call __bound__/__unbound__ to alleviate the performance hit, but I don't see it. I also wouldn't be surprised if there was a trivial way to do this, or if no one's brought it up because it's such an obviously bad idea! :) Maybe I just need to get go some sleep. Regardless, this idea hit me suddenly while I was working on something else. I don't remember what prompted the idea, but I at least wanted to float it out there. Even if it's a terrible idea, I think the concept of letting the bound object know how it's bound is an interesting one. It's an angle I had not considered before. Thanks, -eric
On 6/4/2011 2:11 AM, Eric Snow wrote:
When a name is bound to an object, the object doesn't hear about it,
Objects are created. Then they may *optionally* be bound to names (possibly in a different namespace) and collection slots. Or they may be used in an expression and be discarded without every being bound to anything.
usually.
I believe never.
The exceptions I could think of are class and function definitions, and imports.
Functions, classes, and modules have __name__ attributes (that cannot be deleted, even if they can be replaced). This attribute is set before they are optionally bound, so they also do not hear about the subsequent bindings. This attribute is used for their string representations for humans to read. I cannot think of any other use by the interpreter itself.
Also, you can sneak around it using setattr/descriptors if you control the class... However, objects are otherwise (and generally) blind to their names.
Object (or definition or intrinsic or attribute) names (exactly 1 for certain instances of certain classes) and namespace binding names (0-many for every object) are different concepts. Ojects names live on the object. The binding names live in one of the many namespaces. Object names are not unique among objects. Binding names are unique within each namespace. Objects names do not have to match any of the binding names of the object. A common type of example of this is
import itertools as it it.__name__ 'itertools'
This is relevant when you want an object to be aware of the contexts in which it exists.
Python objects exist within an anonymous object space with no structure. They can be used within any namespace context from which they can be accessed via names and slots. Adding a __name__ attribute to instances of a class will not say anything about use context. Modules carry source information in __filename__ for convenience in error reporting. Classes and functions have the *name* of their creation context in __module__ for the same reason. I do not believe that __filename or __module__ have any operational meaning after the object is created. For functions (but not classes) __globals__ *is* needed to function. Instances have __class__, which is used for both attribute lookup and information display.
It also relates to DRY issues that people bring up sometimes with regards to descriptors and namedtuple (though I'm not sure its that big a deal).
If one wants an object name and initial binding name to be the same, I agree that giving the name once is a convenience. Def, class, and import *statements* allow this for functions, classes, and modules. Each has a syntax peculiar to the class. Lambda expressions, type() calls, __import__ calls (and others in inspect create objects with __name__s but without an automatic binding operation. Ideas about not repeating duplicate object/binding names was discussed here in a thread with several posts within the last year. I believe one idea was a new 'augmented assignment': something like 'x .= y' meaning "y.__name__ = 'x'; x = y". But there was some problem with every proposal. -- Terry Jan Reedy
On Sun, Jun 5, 2011 at 11:54 AM, Terry Reedy <tjreedy@udel.edu> wrote:
Functions, classes, and modules have __name__ attributes (that cannot be deleted, even if they can be replaced). This attribute is set before they are optionally bound, so they also do not hear about the subsequent bindings. This attribute is used for their string representations for humans to read. I cannot think of any other use by the interpreter itself.
__name__ attributes are also relevant for serialisation (esp. pickling). However, due to immutable objects, there's no realistic general purpose solution in this space. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
This is in principle doable with metaclasses (like everything else :-D)... Here's what I whipped up in the console:
class MagicDict(dict): ... def __setitem__(self, key, value): ... print("Binding key: {} to value: {}".format(key, value)) ... if hasattr(value, "__bind__"): ... value.__bind__(key) ... super().__setitem__(key, value) ... class Bindable: ... def __bind__(self, key): ... print("{} was bound to {}".format(self, key)) ... class MetaBinding(type): ... @classmethod ... def __prepare__(metacls, name, bases): ... return MagicDict() ... class BindingReports(metaclass=MetaBinding): ... a = 1 ... b = Bindable() ... c = "blah" ... Binding key: __module__ to value: __main__ Binding key: a to value: 1 Binding key: b to value: <__main__.Bindable object at 0x100603b50> <__main__.Bindable object at 0x100603b50> was bound to b Binding key: c to value: blah
Not sure how useful this is. I don't like using the term "class" for things where you're not really trying to bundle together methods or create a type, just change the way values get bound. -- Carl Johnson
On Sat, Jun 4, 2011 at 11:50 PM, Nick Coghlan <ncoghlan@gmail.com> wrote:
On Sun, Jun 5, 2011 at 11:54 AM, Terry Reedy <tjreedy@udel.edu> wrote:
Functions, classes, and modules have __name__ attributes (that cannot be deleted, even if they can be replaced). This attribute is set before they are optionally bound, so they also do not hear about the subsequent bindings. This attribute is used for their string representations for humans to read. I cannot think of any other use by the interpreter itself.
__name__ attributes are also relevant for serialisation (esp. pickling).
However, due to immutable objects, there's no realistic general purpose solution in this space.
Yeah, I think I was hasty on writing this up. It's interesting, but not a great fit, nor very practical. The immutable objects problem is definitely a show-stopper. Thanks for the feedback though. -eric
Cheers, Nick.
-- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia _______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas
I'm not sure what you're trying to do (ie if there's any practical problem that motivates this), but in Lepl (a parser) I use a little trick that lets me examine variables defined within a "with" scope. That lets me add "debugging" at the application level. There's an example here: http://www.acooke.org/lepl/debugging.html#variable-traces - everything defined inside the "with TraceVariables" is found by inspection of some Python internals doo-hicky, and then modified to produce the debug output (note that the output incldues the variable *names* which is the kind of thing you are trying to do here). Contact me if you want more info. Andrew On Mon, Jun 06, 2011 at 09:48:07AM -0600, Eric Snow wrote:
On Sat, Jun 4, 2011 at 11:50 PM, Nick Coghlan <ncoghlan@gmail.com> wrote:
On Sun, Jun 5, 2011 at 11:54 AM, Terry Reedy <tjreedy@udel.edu> wrote:
Functions, classes, and modules have __name__ attributes (that cannot be deleted, even if they can be replaced). This attribute is set before they are optionally bound, so they also do not hear about the subsequent bindings. This attribute is used for their string representations for humans to read. I cannot think of any other use by the interpreter itself.
__name__ attributes are also relevant for serialisation (esp. pickling).
However, due to immutable objects, there's no realistic general purpose solution in this space.
Yeah, I think I was hasty on writing this up. It's interesting, but not a great fit, nor very practical. The immutable objects problem is definitely a show-stopper. Thanks for the feedback though.
-eric
Cheers, Nick.
-- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia _______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas
_______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas
participants (5)
-
andrew cooke
-
Carl M. Johnson
-
Eric Snow
-
Nick Coghlan
-
Terry Reedy