Getting the name of an assignment

Discussion in 'Python' started by Adam Atlas, Dec 23, 2006.

  1. Adam Atlas

    Adam Atlas Guest

    Is it possible for an object, in its __init__ method, to find out if it
    is being assigned to a variable, and if so, what that variable's name
    is? I can think of some potentially ugly ways of finding out using
    sys._getframe, but if possible I'd prefer something less exotic.
    (Basically I have a class whose instances, upon being created, need a
    'name' property, and if it's being assigned to a variable immediately,
    that variable's name would be the best value of 'name'; to make the
    code cleaner and less redundant, it would be best if it knew its own
    name upon creation, just like functions and classes do, without the
    code having to pass it its own name as a string.)
     
    Adam Atlas, Dec 23, 2006
    #1
    1. Advertising

  2. On 23 Dec 2006 14:38:19 -0800, Adam Atlas <> wrote:
    > Is it possible for an object, in its __init__ method, to find out if it
    > is being assigned to a variable, and if so, what that variable's name
    > is? I can think of some potentially ugly ways of finding out using
    > sys._getframe, but if possible I'd prefer something less exotic.
    > (Basically I have a class whose instances, upon being created, need a
    > 'name' property, and if it's being assigned to a variable immediately,
    > that variable's name would be the best value of 'name'; to make the
    > code cleaner and less redundant, it would be best if it knew its own
    > name upon creation, just like functions and classes do, without the
    > code having to pass it its own name as a string.)


    I guess you mean something like this:

    >>> olle = Person()
    >>> olle.name

    "olle"

    Instead of:

    >>> olle = Person("olle")
    >>> olle.name

    "olle"

    It is not possible without ugly hacks. What you could use instead is
    some kind of registry approach:

    reg = {}
    class Person:
    def __init__(self, name):
    self.name = name
    reg[name] = self

    >>> Person("olle")
    >>> reg["olle"].name

    "olle"

    I think there are thousand different ways you could solve it.

    --
    mvh Björn
     
    =?ISO-8859-1?Q?BJ=F6rn_Lindqvist?=, Dec 23, 2006
    #2
    1. Advertising

  3. Adam Atlas

    Adam Atlas Guest

    On Dec 23, 5:58 pm, "BJörn Lindqvist" <> wrote:
    > On 23 Dec 2006 14:38:19 -0800, Adam Atlas <> wrote:
    >
    > > Is it possible for an object, in its __init__ method, to find out if it
    > > is being assigned to a variable, and if so, what that variable's name
    > > is? I can think of some potentially ugly ways of finding out using
    > > sys._getframe, but if possible I'd prefer something less exotic.
    > > (Basically I have a class whose instances, upon being created, need a
    > > 'name' property, and if it's being assigned to a variable immediately,
    > > that variable's name would be the best value of 'name'; to make the
    > > code cleaner and less redundant, it would be best if it knew its own
    > > name upon creation, just like functions and classes do, without the
    > > code having to pass it its own name as a string.)I guess you mean something like this:

    >
    > >>> olle = Person()
    > >>> olle.name"olle"

    >
    > Instead of:
    >
    > >>> olle = Person("olle")
    > >>> olle.name"olle"

    >
    > It is not possible without ugly hacks. What you could use instead is
    > some kind of registry approach:
    >
    > reg = {}
    > class Person:
    > def __init__(self, name):
    > self.name = name
    > reg[name] = self
    >
    > >>> Person("olle")
    > >>> reg["olle"].name"olle"

    >
    > I think there are thousand different ways you could solve it.


    Yeah, I've thought of ways like that. I was just hoping to make the
    syntax as minimal and Pythonic as possible.

    I have the following working:

    > import sys
    >
    > class c:
    > def __init__(self):
    > f = sys._getframe(1)
    > names = [n for n in f.f_code.co_names if n not in f.f_locals]
    > if len(names) > 0:
    > name = names[0]
    > print name
    >
    > a = c() # prints 'a'
    > b = 'blah'
    > b = c() # prints nothing


    Question: too evil?
     
    Adam Atlas, Dec 24, 2006
    #3
  4. On Sat, 23 Dec 2006 14:38:19 -0800, Adam Atlas wrote:

    > Is it possible for an object, in its __init__ method, to find out if it
    > is being assigned to a variable, and if so, what that variable's name
    > is?


    What should the variable name be set to if you do one of the following?


    john = eric = graham = terry = Named_Instance()

    some_list = [None, 1, "string", Named_Instance()]

    fred = Named_Instance(); barney = fred; del fred


    Name assignment is not a one-to-one operation. An object can have no name,
    one name or many names. If your code assumes such a one-to-one
    relationship between names and objects, it is wrong.


    > I can think of some potentially ugly ways of finding out using
    > sys._getframe, but if possible I'd prefer something less exotic.
    > (Basically I have a class whose instances, upon being created, need a
    > 'name' property, and if it's being assigned to a variable immediately,
    > that variable's name would be the best value of 'name'; to make the code
    > cleaner and less redundant, it would be best if it knew its own name
    > upon creation, just like functions and classes do, without the code
    > having to pass it its own name as a string.)


    I suggest rethinking your data model, and accept that the name
    attribute of an object is not necessarily the same as the name it is
    bound to.

    If you still want a convenience function that names the object and binds
    it to a name at the same time, try something like this:

    def Make_A_Named_Instance(name, *args, **kwargs):
    globals()[name] = Named_Instance(*args, **kwargs)
    globals()[name].name = name


    You might be tempted to replace globals() with locals() in the above.
    Don't -- it doesn't generally work:

    http://docs.python.org/lib/built-in-funcs.html


    --
    Steven.
     
    Steven D'Aprano, Dec 24, 2006
    #4
  5. Adam Atlas wrote:
    > Is it possible for an object, in its __init__ method, to find out if it
    > is being assigned to a variable, and if so, what that variable's name
    > is? I can think of some potentially ugly ways of finding out using
    > sys._getframe, but if possible I'd prefer something less exotic.
    > (Basically I have a class whose instances, upon being created, need a
    > 'name' property, and if it's being assigned to a variable immediately,
    > that variable's name would be the best value of 'name'; to make the
    > code cleaner and less redundant, it would be best if it knew its own
    > name upon creation, just like functions and classes do, without the
    > code having to pass it its own name as a string.)


    As others have mentioned, in general the answer is no. However, class
    statements do have access to the name they're assigned, so you could
    abuse a class statement like this::

    >>> # your class whose instances need a name property
    >>> class C(object):

    ... def __init__(self, name):
    ... self.name = name
    ... @classmethod
    ... def from_class_block(cls, name, bases, blockdict):
    ... return cls(name)
    ...
    >>> # instances of your class with the appropriate names
    >>> class instance:

    ... __metaclass__ = C.from_class_block
    ...
    >>> instance.name

    'instance'

    Though it doesn't rely on private functions like sys._getframe, it's
    still sure to confuse the hell out of your users. ;-)

    STeVe
     
    Steven Bethard, Dec 24, 2006
    #5
  6. Adam Atlas

    Adam Atlas Guest

    Thanks, Steven and Steven.

    @Bethard:
    Isn't it a bit convoluted to use metaclasses?
    someinstance.__class__.__name__ does the same thing.

    @D'Aprano:
    Thanks for the advice to rethink my data model. I'm doing so right now,
    and I've already come up with a way that makes more sense. :)
     
    Adam Atlas, Dec 24, 2006
    #6
  7. Adam Atlas wrote:
    > Isn't it a bit convoluted to use metaclasses?


    Yep. It's a well known fact that putting "convoluted" and "metaclasses"
    in the same sentence is repetitively redundant. ;-)

    > someinstance.__class__.__name__ does the same thing.


    No, not really::

    >>> class C(object):

    ... def __init__(self, name):
    ... self.name = name
    ... @classmethod
    ... def from_class_block(cls, name, bases, blockdict):
    ... return cls(name)
    ...
    >>> c = C('foo')
    >>> c.name

    'foo'
    >>> type(c)

    <class '__main__.C'>
    >>> c.__class__.__name__

    'C'
    >>> class foo:

    ... __metaclass__ = C.from_class_block
    ...
    >>> foo.name

    'foo'
    >>> type(foo)

    <class '__main__.C'>
    >>> foo.__class__.__name__

    'C'

    Note that the ``class foo`` statement is not creating a class. It's
    creating an instance of ``C``. So it really is doing something pretty
    different.

    STeVe
     
    Steven Bethard, Dec 24, 2006
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?iso-8859-1?B?bW9vcJk=?=
    Replies:
    7
    Views:
    829
    Roedy Green
    Jan 2, 2006
  2. ding feng
    Replies:
    2
    Views:
    2,821
    ding feng
    Jun 25, 2003
  3. nagy
    Replies:
    36
    Views:
    1,011
    Terry Reedy
    Jul 20, 2006
  4. Chris
    Replies:
    34
    Views:
    1,526
  5. Bobby Chamness
    Replies:
    2
    Views:
    2,400
    Joe Smith
    Apr 22, 2007
Loading...

Share This Page