473,881 Members | 1,708 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Class attributes, instances and metaclass __getattribute_ _


Hi all
I noticed something strange here while explaining decorators to someone.
Not any real use code, but I think it's worth mentioning.

When I access a class attribute, on a class with a custom metaclass with
a __getattribute_ _ method, the method is used when acessing some
attribute directly with the class object, but not when you do it from
the instance.

<code type='prompt'>
>>class M(type):
.... def __getattribute_ _(cls, attr):
.... print cls, attr
.... return type.__getattri bute__(cls, attr)
....
>>class C(object):
.... __metaclass__ = M
....
>>C.x = 'foo'
C.x
<class '__main__.C'x
'foo'
>>o = C()
o.x
'foo'
>>>
</code>
Someone at freenode #python channel involved with python-dev sprint
suggested it might be a bug, worth mentioning... to me it seems like a
decision to avoid some problems with method and descriptors creation,
since someone using metaclasses and custom __getattribute_ _ at the same
time is asking for trouble, but... I googled for it and tried to find
something on the list but, nothing. From the source it seems like a
generic wrapper is used. What's the real case here ?
Regards,

--
Pedro Werneck
Aug 7 '06 #1
4 3329
Pedro Werneck wrote:
When I access a class attribute, on a class with a custom metaclass with
a __getattribute_ _ method, the method is used when acessing some
attribute directly with the class object, but not when you do it from
the instance.

<code type='prompt'>
>class M(type):
... def __getattribute_ _(cls, attr):
... print cls, attr
... return type.__getattri bute__(cls, attr)
...
>class C(object):
... __metaclass__ = M
...
>C.x = 'foo'
C.x
<class '__main__.C'x
'foo'
>o = C()
o.x
'foo'
>>
</code>
Someone at freenode #python channel involved with python-dev sprint
suggested it might be a bug, worth mentioning... to me it seems like a
decision to avoid some problems with method and descriptors creation,
since someone using metaclasses and custom __getattribute_ _ at the same
time is asking for trouble, but... I googled for it and tried to find
something on the list but, nothing. From the source it seems like a
generic wrapper is used. What's the real case here ?
Regards,

--
Pedro Werneck
To me, it seems consistent. As said in
http://www-128.ibm.com/developerwork...ary/l-pymeta2/

"""The availability of metaclass attributes is not transitive; in other
words, the attributes of a metaclass are available to its instances,
but not to the instances of the instances. Just this is the main
difference between metaclasses and superclasses."" "

Since this happens for real attributes, it looks natural that the same
should
happen for 'virtual' attributes implemented via '__getattr__' or
'__getattribute __'.

Michele Simionato

Aug 8 '06 #2

Hi

On 8 Aug 2006 00:10:39 -0700
"Michele Simionato" <mi************ ***@gmail.comwr ote:
To me, it seems consistent. As said in
http://www-128.ibm.com/developerwork...ary/l-pymeta2/

"""The availability of metaclass attributes is not transitive; in
other words, the attributes of a metaclass are available to its
instances, but not to the instances of the instances. Just this is the
main difference between metaclasses and superclasses."" "

Well... I'm not talking about metaclass attributes... that's perfectly
consistent, agreed.

I'm saying that when the class implements a custom __getattribute_ _,
when you try to access the instance attributes from itself, it uses it.
But if the class is a metaclass, instances of its instances have acess
to the attribute anyway, but don't use the custom __getattribute_ _ you
implemented.

Like the example I mentioned on the previous mail, or (I think in this
case it's more obvious):
>>class N(type):
.... def __getattribute_ _(cls, attr):
.... print 'using N.__getattribut e for "%s"'%(attr )
.... return type.__getattri bute__(cls, attr)
....
>>class M(type):
.... __metaclass__ = N
....
>>class C(object):
.... __metaclass__ = M
....
>>M.x = 'foo'
M.x
using N.__getattribut e for "x"
'foo'
>>C.x
'foo'
So, in both cases I have access to the class attribute; but in one case
it's using the bound M.__getattribut e__ implemented at the base
metaclass, but not in the other. It was supposed to use it after the
bound 'C.__getattribu te__' raises AttributeError as expected, but it
doesn't...

It's inconsistent, but seems a reasonable decision to me since someone
can easily mess with descriptors doing with this... but, someone else
involved with Python dev I talked about thinks it may be a bug.

And, I'm curious anyway... is it possible to customize attribute access
in this case in any other way ? What really happens here ?
>From the typeobject.c source code, seems like when the metaclass
implements __getattribute_ _, it uses type.__getattri bute__ in this case,
but I'm not sure.

Since this happens for real attributes, it looks natural that the same
should happen for 'virtual' attributes implemented via '__getattr__'
or '__getattribute __'.
Well... as I think it's clear now, the case you mentioned is not exactly
what I'm talking about, but it's good you mentioned about 'virtual'
attributes, because in this case we have another problem, it's
inconsistent too and there's no reason for it...
>>class M(type):
.... def __getattr__(cls , attr):
.... if attr == 'x':
.... return 'foo'
....
>>class C(object):
.... __metaclass__ = M
....
>>C.y = 'bar'
C.x
'foo'
>>C.y
'bar'
>>o = C()
>>o.x
....
AttributeError: 'C' object has no attribute 'x'
>>o.y
'bar'
>>>
So... both 'x' and 'y' are class attributes, but 'x' is a virtual
attribute implemented with M.__getattr__. From the instance I have
access to 'y' but not to 'x'.

Regards,

--
Pedro Werneck
Aug 8 '06 #3
Pedro Werneck wrote:
Hi
[snip]
Well... I'm not talking about metaclass attributes... that's perfectly
consistent, agreed.

I'm saying that when the class implements a custom __getattribute_ _,
when you try to access the instance attributes from itself, it uses it.
But if the class is a metaclass, instances of its instances have acess
to the attribute anyway, but don't use the custom __getattribute_ _ you
implemented.
Attribute lookup for instances of a class never calls metaclass'
__getattribute_ _() method. This method is called only when you
access attributes directly on the class.

[snip]
And, I'm curious anyway... is it possible to customize attribute access
in this case in any other way ? What really happens here ?
There are two distinct methods involved in your example; attribute
lookup for classes is controled by metaclass' __getattribute_ _()
method, while instance attribute lookup is controled by class'
__getattribute_ _() method.

They are basicaly the same, but they never use ``type(obj).att r`` to
access the class' attributes. The code for these methods would look
something like this in Python:

class Object(object):
"""
Emulates object's and type's behaviour in attribute lookup.
"""

def __getattribute_ _(self, name):
cls = type(self)

# you normally access this as self.__dict__
try:
dict_descriptor = cls.__dict__['__dict__']
except KeyError:
# uses __slots__ without dict
mydict = {}
else:
mydict = dict_descriptor .__get__(self, cls)

# Can't use cls.name because we would get descriptors
# (methods and similar) that are provided by class'
# metaclass and are not meant to be accessible from
# instances.
classdicts = [c.__dict__ for c in cls.__mro__]

# We have to look in class attributes first, since it can
# be a data descriptor, in which case we have to ignore
# the value in the instance's dict.
for d in classdicts:
if name in d:
classattr = d[name]
break
else:
# None of the classes provides this attribute; perform
# the normal lookup in instance's dict.
try:
return mydict[name]
except KeyError:
# Finally if everything else failed, look for the
# __getattr__ hook.
for d in classdicts:
if '__getattr__' in d:
return d['__getattr__'](self, name)
msg = "%r object has no attribute %r"
raise AttributeError( msg % (cls.__name__, name))

# Check if class' attribute is a descriptor.
if hasattr(classat tr, '__get__'):
# If it is a non-data descriptor, then the value in
# instance's dict takes precedence
if not hasattr(classat tr, '__set__') and name in mydict:
return mydict[name]
return classattr.__get __(self, cls)

# Finally, look into instance's dict.
return mydict.get(name , classattr)

As you can see, it completely avoids calling metaclass'
__getattribute_ _()
method. If it wouldn't do that, then the metaclass' attributes would
'leak' to instances of its classes. For example, __name__, __mro__
and mro() are some of the descriptors provided by type to every class,
but they are not accesible through instances of these classes,
and shouldn't be, otherwise they could mask some errors in user's code.

Ziga

Aug 8 '06 #4
On 8 Aug 2006 07:24:54 -0700
"Ziga Seilnacht" <zi************ @gmail.comwrote :
[snip]
Well... I'm not talking about metaclass attributes... that's
perfectly consistent, agreed.

I'm saying that when the class implements a custom __getattribute_ _,
when you try to access the instance attributes from itself, it uses
it. But if the class is a metaclass, instances of its instances have
acess to the attribute anyway, but don't use the custom
__getattribute_ _ you implemented.

Attribute lookup for instances of a class never calls metaclass'
__getattribute_ _() method. This method is called only when you
access attributes directly on the class.
Well... thanks for the answer.

As I said on the first mail, I noticed this when I was explaining
descriptors and methods to someone else... I implemented a pure-python
Method class to show him exactly how it works.

But, since their __get__ call is available at the class too, my first
thought was that it was implemented at the metaclass __getattribute_ _,
and when an instance tries to get a class attribute it would fail on its
own __getattribute_ _, use the bound method at its class and make the
call.

After implementing a test metaclass I noticed it doesn't work this way,
and even if it's a bit inconsistent (especially in the case of 'virtual'
attributes), it seemed to me the reasonable thing to do, exactly for
what you mentioned on your code... someone could easily break a lot of
stuff doing it the wrong way, instead if not using __dict__.

I mailed the list because someone else thought it might be a bug and I
was in doubt... now it's clear it was the right thing to do.
Regards,

--
Pedro Werneck
Aug 8 '06 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
3647
by: Ruud de Jong | last post by:
I have the situation where I need to construct the name of a static method, and then retrieve the corresponding function from a class object. I thought I could just use __getattribute__ for this purpose. This works fine if I already have an instantiation of the class, but not when I try this on the class object directly. A bare bones example:
50
6402
by: Dan Perl | last post by:
There is something with initializing mutable class attributes that I am struggling with. I'll use an example to explain: class Father: attr1=None # this is OK attr2= # this is wrong def foo(self, data): self.attr1=data self.attr2.append(data) The initialization of attr1 is obviously OK, all instances of Father redefine it in the method foo. But the initialization of attr2 is wrong
7
1719
by: Carlos Ribeiro | last post by:
I'm looking for ways to load new class definitions at runtime (I'm not talking about object instances here, so a persistent object database isn't what I am looking for ). I'm aware of a few options, but I would like to discuss the possible side effects for a potentially big, long running application server. I am developing a business application based on workflow concepts. The model is quite simple: a business process is modelled as a...
3
2583
by: Sylvain Ferriol | last post by:
hello when i define __getattribute__ in a class, it is for the class instances but if i want to have a __getattribute__ for class attributes how can i do that ? sylvain
5
2077
by: Laszlo Zsolt Nagy | last post by:
Hughes, Chad O wrote: > Is there any way to create a class method? I can create a class > variable like this: > Hmm, seeing this post, I have decided to implement a 'classproperty' descriptor. But I could not. This is what I imagined: class A(object):
9
1868
by: sashang | last post by:
Hi I'd like to use metaclasses to dynamically generate a class based on a parameter to the objects init function. For example: class MetaThing(type): def __init__(cls, name, bases, dict, extra_information): super(MetaThing, cls).__init__(name, bases, dict)
14
2812
by: Harlin Seritt | last post by:
Hi, How does one get the name of a class from within the class code? I tried something like this as a guess: self.__name__ Obviously it didn't work. Anyone know how to do that?
5
3182
by: JH | last post by:
Hi I found that a type/class are both a subclass and a instance of base type "object". It conflicts to my understanding that: 1.) a type/class object is created from class statement 2.) a instance is created by "calling" a class object.
5
4994
by: Neal Becker | last post by:
After spending the morning debugging where I had misspelled the name of an attribute (thus adding a new attr instead of updating an existing one), I would like a way to decorate a class so that attributes cannot be (easily) added. I guess class decorators are not available yet (pep 3129), but probably inheritance can be used. Can anyone suggest an implementation?
0
9928
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
11100
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10718
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10816
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10401
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
9554
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7953
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
7110
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5977
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.