Re: [Python-Dev] Instance variable access and descriptors

2007-06-11 Thread Gustavo Carneiro

 While you're at it, it would be nice to fix this ugly asymmetry I found in
descriptors.  It seems that descriptor's __get__ is called even when
accessed from a class rather than instance, but __set__ is only invoked from
instances, never from classes:

class Descr(object):
   def __get__(self, obj, objtype):
   print __get__ from instance %s, type %s % (obj, type)
   return foo

   def __set__(self, obj, value):
   print __set__ on instance %s, value %s % (obj, value)

class Foo(object):
   foo = Descr()

print Foo.foo # works

## doesn't work, goes directly to the class dict, not calling __set__
Foo.foo = 123

 Because of this problem, I may have to install properties into a class's
metaclass achieve the same effect that I expected to achieve with a simple
descriptor :-(


On 10/06/07, Aahz [EMAIL PROTECTED] wrote:


On Sun, Jun 10, 2007, Eyal Lotem wrote:

 Python, probably through the valid assumption that most attribute
 lookups go to the class, tries to look for the attribute in the class
 first, and in the instance, second.

 What Python currently does is quite peculiar!
 Here's a short description o PyObject_GenericGetAttr:

 A. Python looks for a descriptor in the _entire_ mro hierarchy
 (len(mro) class/type check and dict lookups).
 B. If Python found a descriptor and it has both get and set functions
 - it uses it to get the value and returns, skipping the next stage.
 C. If Python either did not find a descriptor, or found one that has
 no setter, it will try a lookup in the instance dict.
 D. If Python failed to find it in the instance, it will use the
 descriptor's getter, and if it has no getter it will use the
 descriptor itself.

Guido, Ping, and I tried working on this at the sprint for PyCon 2003.
We were unable to find any solution that did not affect critical-path
timing.  As other people have noted, the current semantics cannot be
changed.  I'll also echo other people and suggest that this discusion be
moved to python-ideas if you want to continue pushing for a change in
semantics.

I just did a Google for my notes from PyCon 2003 and it appears that I
never sent them out (probably because they aren't particularly
comprehensible).  Here they are for the record (from 3/25/2003):

'''
CACHE_ATTR is the name used to describe a speedup (for new-style classes
only) in attribute lookup by caching the location of attributes in the
MRO.  Some of the non-obvious bits of code:

* If a new-style class has any classic classes in its bases, we
can't do attribute caching (we need to weakrefs to the derived
classes).

* If searching the MRO for an attribute discovers a data descriptor (has
tp_descr_set), that overrides any attribute that might be in the instance;
however, the existence of tp_descr_get still permits the instance to
override its bases (but tp_descr_get is called if there is no instance
attribute).

* We need to invalidate the cache for the updated attribute in all derived
classes in the following cases:

* an attribute is added or deleted to the class or its base classes

* an attribute has its status changed to or from being a data
descriptor

This file uses Python pseudocode to describe changes necessary to
implement CACHE_ATTR at the C level.  Except for class Meta, these are
all exact descriptions of the work being done.  Except for class Meta the
changes go into object.c (Meta goes into typeobject.c).  The pseudocode
looks somewhat C-like to ease the transformation.
'''

NULL = object()

def getattr(inst, name):
isdata, where = lookup(inst.__class__, name)
if isdata:
descr = where[name]
if hasattr(descr, __get__):
return descr.__get__(inst)
else:
return descr
value = inst.__dict__.get(name, NULL)
if value != NULL:
return value
if where == NULL:
raise AttributError
descr = where[name]
if hasattr(descr, __get__):
value = descr.__get__(inst)
else:
value = descr
return value

def setattr(inst, name, value):
isdata, where = lookup(inst.__class__, name)
if isdata:
descr = where[name]
descr.__set__(inst, value)
return
inst.__dict__[name] = value

def lookup(cls, name):
if cls.__cache__ != NULL:
pair = cls.__cache__.get(name)
else:
pair = NULL
if pair:
return pair
else:
for c in cls.__mro__:
where = c.__dict__
if name in where:
descr = where[name]
isdata = hasattr(descr, __set__)
pair = isdata, where
break
else:
pair = False, NULL
if cls.__cache__ != NULL:
cls.__cache__[name] = pair
return pair


'''
These changes go into typeobject.c; they are not a complete
description of what happens during creation/updates, only the
changes necessary to implement CACHE_ATTRO.
'''

from types import ClassType

class Meta(type):
def _invalidate(cls, 

Re: [Python-Dev] Instance variable access and descriptors

2007-06-11 Thread Armin Rigo
Hi Eyal,

On Sun, Jun 10, 2007 at 04:13:38AM +0300, Eyal Lotem wrote:
 I must be missing something, as I really see no reason to keep the
 existing semantics other than backwards compatibility (which can be
 achieved by introducing a __fastattr__ or such).
 
 Can you explain under which situations or find any example situation
 where the existing semantics are desirable?

The existing semantics are essential when dealing with metaclasses.
Many of the descriptors of the 'type' class would stop working without
it.  For example, the fact that 'x.__class__' normally gives the type of
'x' for any object x relies on this.  Reading the '__dict__' attribute
of types is also based on this.  Before proposing changes, be sure you
understand exactly how the following works:

 object.__class__
type 'type'
 object.__dict__['__class__']
attribute '__class__' of 'object' objects

 class A(object):
... pass
 A.__dict__
dictproxy object at 0xb7c98e6c
 A.__dict__['__dict__']
attribute '__dict__' of 'A' objects


A bientot,

Armin.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Santa Fe Python Day report

2007-06-11 Thread Facundo Batista
It was very succesful, around +300 people assisted, and there were a lot of 
interesting talks (two introductory talks, Turbogears, PyWeek, Zope 3, 
security, creating 3D games, Plone, automatic security testings, concurrency, 
and programming the OLPC).

I want to thanks the PSF for the received support. Python is developing 
interestingly in Argentina, and this Python Days are both a prove of that, and 
a way to get more Python developers.

Some links:

  Santa Fe Python Day: http://www.python-santafe.com.ar/
  Python Argentina: http://www.python.com.ar/moin

Regards,

-- 
.   Facundo
.
Blog: http://www.taniquetil.com.ar/plog/
PyAr: http://www.python.org/ar/


___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Question about dictobject.c:lookdict_string

2007-06-11 Thread Carl Friedrich Bolz
Eyal Lotem wrote:
 My question is specifically regarding the transition back from
 lookdict_string (the initial value) to the general lookdict.
 
 Currently, when a string-only dict is trying to look up any
 non-string, it reverts back to a general lookdict.
 
 Wouldn't it be better (especially in the more important case of a
 string-key-only dict), to revert to the generic lookdict when a
 non-string is inserted to the dict, rather than when one is being
 searched?
[...]
 This does not seem like a significant issue, but as I know a lot of
 effort went into optimizing dicts, I was wondering if I am missing
 something here.

Yes, you are: when doing a lookup with a non-string-key, that key could 
be an instance of a class that has __hash__ and __eq__ implementations 
that make the key compare equal to some string that is in the 
dictionary. So you need to change to lookdict, otherwise that lookup 
might fail.

Cheers,

Carl Friedrich Bolz

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com