3

I've been reading the article on the data model of Python on its Reference website, and have been confused about this part:

When the attribute is a user-defined method object, a new method object is only created if the class from which it is being retrieved is the same as, or a derived class of, the class stored in the original method object; otherwise, the original method object is used as it is.

Essentially, I cannot really conjure up two scenarios where in one the method object is is the same as the original method object, and in the other a new method object is created. Here's the closest I can come:

class TestClass:
    def TestFunc():
        pass

class TestClass2:
    x_attr = TestClass().TestFunc
    y_attr = TestClass.TestFunc
    def __init__(self):
        print "x's class is " + repr(TestClass2.x_attr.__class__)
        print "y's class is " + repr(TestClass2.y_attr.__class__)

if __name__ == '__main__':
    tc = TestClass()
    tc2 = TestClass2()

    print "tc.TestFunc: ".ljust(20) + str(id(tc.TestFunc))              # retrieved from TestClass
    print "TestClass.TestFunc: ".ljust(20) + str(id(TestClass.TestFunc))# retrieved from TestClass
    print "tc2.x_attr: ".ljust(20) + str(id(tc2.x_attr))                # retrieved from TestClass2
    print "tc2.y_attr: ".ljust(20) + str(id(tc2.y_attr))                # retrieved from TestClass2

However, the output of the different test cases is not as I would expect by reading the passage from the Reference:

x's class is <type 'instancemethod'>
y's class is <type 'instancemethod'>
tc.TestFunc:        140591510137584
TestClass.TestFunc: 140591510137584
tc2.x_attr:         140591509970288
tc2.y_attr:         140591510137424

Specifically, I was expecting TestClass.TestFunc and tc2.y_attr (i.e. TestClass2.y_attr) to be the same based on what is cited from the Reference.

Furthermore, I was expecting to see the same outcome for the <tc.TestFunc, TestClass.TestFunc> comparison pair and the <tc2.x_attr, tc2.y_attr> comparison pair (i.e. each pair the same or neither the same).

Could you please clarify why this is and what exactly the Reference is trying to say?

Thank you!

P.S. Using Python 2.7.6 on Ubuntu 14.04.

2 Answers 2

0

If i understand it properly, i think you are looking at inheritance, composting methods from another class. Sometimes you need to override existing method if sed method is not utilizing the full scope of some class.

Have in mind that sometimes this type of overriding,inheritance and composting can differ from version to version of python.

I think example would be the best way to explain this. so we have classes test and test2:

class test(object):
    def testF(self):pass

inheritance:>

class test2(test):pass #> inherited testF() function from test
>>> test().testF() is test().testF()
True
>>> test2().testF() == test().testF()
True
>>> #but is test2 the same as test ? 
>>> test2() is test()
False
>>> id( test2() ) == id( test() )
True

Which is logical, if you think about it. Since they may have the same code, but they have different names so in globals() they have different identities, and they have the same ID in memory too since they are the same, aka inheritance. But the moment you start adding other methods to test2 they will stop being the same, and test2 will have pointer to all methods of test. In short, inheritance is used to specialize some classes. If you have class car, and a class Yugo, the Yugo class is just specialized class of car.
Now here comes the overriding, since classes can be inherited you can override the methods from parent class, and those methods become user-defined methods. If you have :

class car(object):
   maxGear = 5
   def getSpeed(self,gearValue):
       if self.maxGear < gearValue: raise WrongCarDudeError
       else: return gearValue*30 # km/h

And now you have Yugo car which is very slow car ( built for expenses not for speed ) 30 km per hour is to big a shift for Yugo car, what should we do now? Make another class of Yugo ? Than we have 2 classes at 2 memory addresses in computer ( loosing valuable space in computer and time of execution). But what can we do, we can override the getSpeed method, and don't copy the whole class.

class Yugo(car):
   def getSpeed(self,gearValue):
       if self.maxGear < gearValue: raise WrongCarDudeError
       else: return gearValue*20 # km/h

So now Yugo car class has maxGear as the other car class, but getSpeed method is not the same.

Now that said, the link you supplied is for overriding system methods __add__,__doc__,__bool__ etc. So if your class inherits from class int and you change the __add__ ( the + operator ) method.The method of your class will not be the same as __add__ method in int class.

If you have not learned yet inheritance vs composting i would suggest some researching. Since you have composted the test.testFunc() in global class test2 attribute. Think about it like this, if attribute has self and it is declared within __init__ function it is private ( it is unique for every new instance of that class ) if it is declared inside class but outside methods it is global, so it will pile up or be overwritten or just use memory as you create new instances.
So don't declare it inside class and outside of methods unless you really need to. Declaring global attributes is often used when storing IDs of specific instances like chassis number of the car (or bar code from a chocolate bar) . Then you would have yugoCar = Yugo(chassisNumber) and chevyCar = car(chassisNumber) and car.chassisNumbers would list the all chassis numbers from all your instances of Yugo and Car.

I hope this helped.

0

Specifically, I was expecting TestClass.TestFunc and tc2.y_attr (i.e. TestClass2.y_attr) to be the same based on what is cited from the Reference.

You have two different appearances of the expression: "TestClass.TestFunc" one in your __main__, and one in your class. Each of those expressions evaluates to a different instance of the method object, so they aren't equal. However, you'll find that TestClass2.y_attr is the same object as tc2.y_attr, as specified by the reference.

Furthermore, I was expecting to see the same outcome for the comparison pair and the comparison pair (i.e. each pair the same or neither the same).

The first pair only appears the same. In actual fact, the first print line constructs and then throws away a method object. The second print line creates a new method object using the exact same memory, and thus get the same id. But they aren't actually the same object.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.