Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does setattr work differently for attributes and methods?

Tags:

python

When I set an attribute, getattr result's id changes to value id. When I set a method, getattr result id doesn't change. Why?

class A (object):
    a = 1
a = 42
print id(getattr(A, 'a'))
print id(a)
setattr(A, 'a', a)
print id(getattr(A, 'a'))
# Got:
#   36159832
#   36160840
#   36160840

class B (object):
    def b(self):
        return 1
b = lambda self: 42
print id(getattr(B, 'b'))
print id(b)
setattr(B, 'b', b)
print id(getattr(B, 'b'))
# Got:
#   140512684858496
#   140512684127608
#   140512684858496
like image 316
Timur Avatar asked Feb 10 '16 15:02

Timur


1 Answers

The difference is based on how methods work in python

note that

>>> B.b
<unbound method B.<lambda>>

Methods are actually built using descriptors

Updating the "method", the descriptor isn't changing

Looking inside the descriptor we find the underlying function does

class B (object):
    def b(self):
        return 1
b = lambda self: 42
print id(getattr(B, 'b'))
print id(b)
setattr(B, 'b', b)
print id(getattr(B, 'b'))
print id(getattr(B, 'b').im_func)  # grab function from the descriptor


4424060752
4440057568
4424060752
4440057568   # here's our new lambda

You can also have a look at

B.__dict__['b']

before and after

like image 56
second Avatar answered Nov 14 '22 22:11

second