About instance.name look up order

P

Prim

First, sorry about my poor english.
Put these in IPython under ubuntu.
-------------------------------------------------------------------------------------
class C:
def __init__(self):
self.x = 1
def print(self):
print self.x
c = C()
c.x --> 1, so c.x mean a attr of c named 'x'
c.print() --> pirnt 1, so c.print mean a method of c named 'print'
-------------------------------------------------------------------------------------
class C:
def __init__(self):
self.x = 1
def x(self):
print 'x method'
def y(self):
print 'y method'
c = C()
c.x --> 1
c.x() --> TypeError: 'int' object is not callable
c.y --> bound method C.y
#Q1: instance.name will get the attr first, than method?
-------------------------------------------------------------------------------------
class C:
def x(self):
print 'x method'
def __getattr__(self, attr):
print 'in __getattr__ method'
return attr
c = C()
c.x --> print in __getattr__ method, then throw TypeError: 'str'
object is not callable
c.x() --> print in __getattr__ method, x method 2 lines
#Q2: why c.x would get a exception?

t = c.x
t --> print in __getattr__ method, then throw TypeError: 'str' object
is not callable
t() --> print x method
t = c.x() --> print x method, t == None
#Q3 why t=c.x() and c.x() output different?

#Q4, if when I define the class use property too, then instance.name
look up order would be?

Thanks for your reply.
 
K

Kev Dwyer

Prim said:
First, sorry about my poor english.
Put these in IPython under ubuntu.
-------------------------------------------------------------------------------------
class C:
def __init__(self):
self.x = 1
def print(self):
print self.x
c = C()
c.x --> 1, so c.x mean a attr of c named 'x'
c.print() --> pirnt 1, so c.print mean a method of c named 'print'
-------------------------------------------------------------------------------------
class C:
def __init__(self):
self.x = 1
def x(self):
print 'x method'
def y(self):
print 'y method'
c = C()
c.x --> 1
c.x() --> TypeError: 'int' object is not callable
c.y --> bound method C.y
#Q1: instance.name will get the attr first, than method?
-------------------------------------------------------------------------------------
class C:
def x(self):
print 'x method'
def __getattr__(self, attr):
print 'in __getattr__ method'
return attr
c = C()
c.x --> print in __getattr__ method, then throw TypeError: 'str'
object is not callable
c.x() --> print in __getattr__ method, x method 2 lines
#Q2: why c.x would get a exception?

t = c.x
t --> print in __getattr__ method, then throw TypeError: 'str' object
is not callable
t() --> print x method
t = c.x() --> print x method, t == None
#Q3 why t=c.x() and c.x() output different?

#Q4, if when I define the class use property too, then instance.name
look up order would be?

Thanks for your reply.

Hello,

Python always looks for attributes in the instance first, then in the class,
and then in the class's superclasses. In your first example, by defining
"x" in C.__init__ you are creating an instance attribute named "x". When
the attribute c.x is requested, Python finds an attribute "x" in the
instance and returns it; the method "x" is found in the class, but the
attribute lookup does not proceed this far.

Try looking at C.__dict__ and c.__dict__ in the interpreter to see how the
attributes are stored.

See also
http://docs.python.org/reference/datamodel.html#customizing-attribute-access

Cheers

Kev
 
I

Ian Kelly

class C:
   def x(self):
       print 'x method'
   def __getattr__(self, attr):
       print 'in __getattr__ method'
       return attr
c = C()
c.x --> print in __getattr__ method, then throw TypeError: 'str'
object is not callable
c.x() --> print in __getattr__ method, x method 2 lines
#Q2: why c.x would get a exception?

I'm not sure exactly what's going on there, but as a general rule you
should use new-style classes, not classic classes, which are
deprecated and have been removed in Python 3. In Python 2 if you
define a class without any base classes, you get a classic class. To
define C as a new-style class in Python 2, derive it from object (or
another new-style class):
.... def x(self):
.... print 'x method'
.... def __getattr__(self, attr):
.... print 'in __getattr__ method'
.... return attr
....x method

Note that in this case __getattr__ never gets called because the name
was found using the normal lookup mechanism. You would need to use
__getattribute__ if you want it to be called unconditionally.
#Q4, if when I define the class use property too, then instance.name
look up order would be?

You can't use properties in classic classes. In a new-style class, if
you access a property, then any instance attribute with the same name
is ignored and can't be set in the first place.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top