Hi Anatoly, Haven't done any python in a loong time now, but I lurk sometimes on the pypy list, and thought ok, I'll play with that, and see if it's nay use to you.
I wrote techtonik.py (included at the end) and used it interactively to show some features, first trying to approximate the interaction you gave as an example (well, except the ns. prefix ;-) I may have gone a little overboard, tracking re-assignments etc ;-) HTH On 07/15/2014 11:05 AM anatoly techtonik wrote:
Hi, Is it possible at all to define a class in Python that can read name of variable it is assigned to on init? >>> MyObject = SomeClass() >>> print(MyObject) 'MyObject' For this to work, SomeClass __init__ needs to know what variable name is currently waiting to be assigned. But at the time __init__ is executed, MyObject is not entered global or local space yet. I know that this is possible to do on AST level, but AST is inaccessible when program is running, so what is the corresponding structure to track that? (links to source are appreciated) 1. Is it possible to do this in CPython and PyPy? 2. Is it possible to do this in generic way? 3. Is there any stack of assignments? 3.1. Is this stack accessible? Thanks.
--- Python 2.7.3 (default, Jul 3 2012, 19:58:39) [GCC 4.7.1] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> from techtonik import NameSetter, SomeClass >>> ns = NameSetter() >>> ns.MyObject = SomeClass() >>> print ns.MyObject 'MyObject' >>> # QED ;-) ... >>> ns.copy1 = ns.MyObject # new name for same object >>> ns.copy1 <SomeClass obj: () {} assigned to: 'MyObject', 'copy1'> >>> print ns.MyObject 'MyObject', aka 'copy1' >>> ns.a = ns.b = ns.c = SomeClass('multi') >>> ns.a <SomeClass obj: ('multi',) {} assigned to: 'a', 'b', 'c'> >>> print ns.b 'a', aka 'b', aka 'c' >>> ns.b = 123 >>> print ns.b 123 >>> print ns.a 'a', aka '\\b', aka 'c' >>> ns.a <SomeClass obj: ('multi',) {} assigned to: 'a', '\\b', 'c'> >>> nd.d = ns.a Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'nd' is not defined >>> ns.d = ns.a >>> ns.d <SomeClass obj: ('multi',) {} assigned to: 'a', '\\b', 'c', 'd'> >>> ns.b = MyObject Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'MyObject' is not defined >>> ns.b = ns.MyObject >>> ns.b <SomeClass obj: () {} assigned to: 'MyObject', 'copy1', 'b'> >>> ns.a <SomeClass obj: ('multi',) {} assigned to: 'a', '\\b', 'c', 'd'> >>> ns.b = ns.a >>> ns.b <SomeClass obj: ('multi',) {} assigned to: 'a', '\\b', 'c', 'd', 'b'> >>> ns.MyObject <SomeClass obj: () {} assigned to: 'MyObject', 'copy1', '\\b'> >>> If you run techtonik.py, it runs a little test, whose output is: ---- [04:37 ~/wk/py]$ techtonik.py 'MyObject' <SomeClass obj: (1, 2) {'three': 3} assigned to: 'MyObject'> 'MyObject', aka 'mycopy' <SomeClass obj: (1, 2) {'three': 3} assigned to: 'MyObject', 'mycopy'> 'myinstance' <SomeClass obj: ('same class new instance',) {} assigned to: 'myinstance'> 'a', aka 'b', aka 'c' <SomeClass obj: ('multi',) {} assigned to: 'a', 'b', 'c'> 10 20 'a', aka '\\b', aka 'c' <SomeClass obj: ('multi',) {} assigned to: 'a', '\\b', 'c'> [04:37 ~/wk/py]$ ---- Here is the techtonik.py source: ============================================ #!/usr/bin/python # debugging ideas for anatoly # 2014-07-16 00:54:06 # # The goal is to make something like this: # # >>> MyObject = SomeClass() # >>> print(MyObject) # 'MyObject' # # we can do it with an attribute name space: # if you can live with prefixing the name space # name to the names you want to track assignments of: class NameSetter(object): def __setattr__(self, name, val): # if our namespace already has the name being assigned ... if hasattr(self, name): # if that is a nametracking object like a SomeClass instance... tgt = getattr(self, name) if hasattr(tgt, '_names') and isinstance(tgt._names, list): # update its name list to reflect clobbering (prefix '\') for i,nm in enumerate(tgt._names): if nm==name: tgt._names[i] = '\\'+ nm # if value being assigned has a _names list attribute like SomeClass if hasattr(val, '_names') and isinstance(val._names, list): val._names.append(name) # add name to assignemt list # now store the value, whatever the type object.__setattr__(self, name, val) # avoid recursive loop class SomeClass(object): def __init__(self, *args, **kw): self.args = args self.kw = kw self._names = [] def __str__(self): return ', aka '.join(repr(s) for s in (self._names or ["(unassigned)"])) def __repr__(self): return '<%s obj: %r %r %s>' %( self.__class__.__name__, self.args, self.kw, 'assigned to: %s'%( ', '.join(repr(s) for s in (self._names or ["(unassigned)"])))) def test(): ns = NameSetter() ns.target = 'value' ns.MyObject = SomeClass(1,2,three=3) print ns.MyObject print repr(ns.MyObject) ns.mycopy = ns.MyObject print ns.MyObject print repr(ns.MyObject) ns.myinstance = SomeClass('same class new instance') print ns.myinstance print repr(ns.myinstance) ns.a = ns.b = ns.c = SomeClass('multi') print ns.a print repr(ns.b) ns.ten = 10 ns.b = 20 print ns.ten, ns.b, ns.a print repr(ns.a) if __name__ == '__main__': test() ====================================================== Have fun. Regards, Bengt Richter _______________________________________________ pypy-dev mailing list pypy-dev@python.org https://mail.python.org/mailman/listinfo/pypy-dev