[Tutor] attribute of built-in type

spir denis.spir at free.fr
Mon Dec 1 13:35:27 CET 2008


Kent Johnson a écrit :

[...big snip...]

 > Do you know that you can probably just assign a __name__ attribute to
 > the objects? Or name, or whatever you like?
 >
 > In [13]: class Foo(object): pass
 >    ....:
 >
 > In [14]: f=Foo()
 >
 > In [15]: f.name
 > ---------------------------------------------------------------------------
 > AttributeError                            Traceback (most recent call last)
 >
 > /Users/kent/<ipython console> in <module>()
 >
 > AttributeError: 'Foo' object has no attribute 'name'
 >
 > In [16]: f.name = 'f'
 >
 > In [17]: f.name
 > Out[17]: 'f'
 >
 > This will work for custom objects that do not have a __slots__
 > attribute. Perhaps you could wrap the creation of the objects in a
 > function that gives them a name?

Exactly. I presently use a tool func (actually, a Classmethod) that executes 
this (pseudocode):
def set_names(scope):
	for name,obj in scope.__dict__.items():
		# exclude not_to_be_named objects of the scope
		if name_has_the_proper_form:
			# 'name' attr already used for other purpose
			obj.id = name

Which works. I will use this method if I cannot find a way to let the objects 
natively have __name__ attributes. Conceptually , it is not the same thing -- 
at least for me. That a class of objects has such an attribute may be seen as 
an interface characteristics (comparable to 'iterable' or 'ordered') that could 
be inherited. If I want a class to define/construct ordered containers, I will 
simply let it inherit list's interface. The facts that python sets __name__ 
attributes at a low level (as you explain below) and that workarounds are not 
satisfying, both confirm that this is a fondamental interface charasteristics, 
not a superficial one.

Also, I need a name format rule to distinguish to_be_named from not_to_be_named 
objects. This is not a big issue, as this rule has only to be followed inside a 
specific scope. But maybe you understand that I do not find this conceptually 
/satisfying/. A logical feature that should not depend on such a random detail, 
rather it should be a basic property. Imagine a case where you would need to 
give objects characteristics such as iterable or ordered (or mutable / 
immutable!), by implementing the proper __xxx__ methods, based on the fact that 
their name has this or that format. Which may happen if such characteristics 
could not be inherited in python.

[...smaller snip...]

 >> It is an illustration of what i'm trying to do: let a class inherit from
 >> 'function' so that its instances get a __name__. This wouldn't be a harmful
 >> overload I guess, as these objects have a __call__ method anyway (the reason
 >> why I chose 'function').
 >
 > I doubt this would do what you want. AFAICT the function name is
 > assigned by the compiler, not by the function constructor. (That is a
 > bit of oversimplification but close enough. I think the compiler
 > creates a code object, passing its name to the constructor; when a
 > function object is wrapped around the code object, it pulls its name
 > from the code object.)

This let me play a bit further with functions. The following confirms both that 
  __name__ is a very low-level attribute, and that it lies in the code itself:
=============================
import types ; Function = types.FunctionType

def typ(obj): return obj.__class__.__name__
def f():pass
g = f
print id(f)
print "%s: %s at %s \n" % ( g.__name__,typ(g),id(g) )

print dir(f)
cod = g.func_code
print "cod is a '%s' object\n" % typ(cod)

h = Function(cod,{})
print "%s: %s at %s \n" % ( h.__name__,typ(h),id(h) )

==>

10464752
f: function at 10464752

['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__get__', 
'__getattribute__', '__hash__', '__init__', '__module__', '__name__', 
'__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 
'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 
'func_globals', 'func_name']
cod is a 'code' object

f: function at 10464816
==========================

g points to the same, unique, function as f. So that we can understand that g's 
__name__ actually is 'f'. But this shows that an object's "birthname" is 
somehwhat different from further name to which the object may be bound.
Now, h points to brand new object (as confirmed by its id); still, its __name__ 
is 'f'. This attr is well carried by the code and retrieved there, but it is 
not an attribute of code objects (cod.__name__ does not exist).
As I see it, the __name__ is somehow a third kind of name/id for objects. In 
fact, if 'id()' was called 'address()' instead, then __name__ could well be 
called __id__.
I also find highly meaningful that, among built_in types, the bool, int, float, 
str,... series do not have a __name__. (But this is probably an off-topic 
subject for the python_tutor list.)

 >>> Kent

Salutation,
denis




More information about the Tutor mailing list