[Python-Dev] Arbitrary attributes on funcs and methods

bwarsaw@python.org bwarsaw@python.org
Tue, 11 Apr 2000 01:08:49 -0400 (EDT)


>>>>> "GvR" == Guido van Rossum <guido@python.org> writes:

    GvR> Here I have a question.  Should this really change F.a, or
    GvR> should it change the method bound to f only?  You implement
    GvR> the former, but I'm not sure if those semantics are right --
    GvR> if I have two instances, f1 and f2, and you change f2.a.spam,
    GvR> I'd be surprised if f1.a.spam got changed as well (since f1.a
    GvR> and f2.a are *not* the same thing -- they are not shared.
    GvR> f1.a.im_func and f2.a.im_func are the same thing, but f1.a
    GvR> and f2.a are distinct!

As are f1.a and f1.a! :)

    GvR> I would suggest that you only allow setting attributes via
    GvR> the class or via a function.  (This means that you must still
    GvR> implement the pass-through on method objects, but reject it
    GvR> if the method is bound to an instance.)

Given that, Python should probably raise a TypeError if an attempt is
made to set an attribute on a bound method object.  However, it should
definitely succeed to /get/ an attribute on a bound method object.
I'm not 100% sure that setting bound-method-attributes should be
illegal, but we can be strict about it now and see if it makes sense
to loosen the restriction later.

Here's a candidate for Lib/test/test_methattr.py which should print a
bunch of `1's.  I'll post the revised diffs (taking into account GvR's
and GS's suggestions) tomorrow after I've had a night to sleep on it.

-Barry

-------------------- snip snip --------------------
from test_support import verbose

class F:
    def a(self):
        pass

def b():
    pass

# setting attributes on functions
try:
    b.blah
except AttributeError:
    pass
else:
    print 'did not get expected AttributeError'

b.blah = 1
print b.blah == 1
print 'blah' in dir(b)

# setting attributes on unbound methods
try:
    F.a.blah
except AttributeError:
    pass
else:
    print 'did not get expected AttributeError'

F.a.blah = 1
print F.a.blah == 1
print 'blah' in dir(F.a)

# setting attributes on bound methods is illegal
f1 = F()
try:
    f1.a.snerp = 1
except TypeError:
    pass
else:
    print 'did not get expected TypeError'

# but accessing attributes on bound methods is fine
print f1.a.blah
print 'blah' in dir(f1.a)

f2 = F()
print f1.a.blah == f2.a.blah

F.a.wazoo = F
f1.a.wazoo is f2.a.wazoo

# try setting __dict__ illegally
try:
    F.a.__dict__ = (1, 2, 3)
except TypeError:
    pass
else:
    print 'did not get expected TypeError'

F.a.__dict__ = {'one': 111, 'two': 222, 'three': 333}
print f1.a.two == 222

from UserDict import UserDict
d = UserDict({'four': 444, 'five': 555})
F.a.__dict__ = d

try:
    f2.a.two
except AttributeError:
    pass
else:
    print 'did not get expected AttributeError'

print f2.a.four is f1.a.four is F.a.four