Learnerer
Learnerer

Reputation: 583

Why are class method names prefixed with the class name, but not other objects?

In Python, if I define a simple class as follows:

>>> class myClass:
...  z = zip('abc', (97, 98, 99))
...  def meth(self):
...   print(self)
...
>>>

and then enter the following at the prompt:

>>> myClass.meth
<function myClass.meth at 0x00639540>
>>> myClass.z
<zip object at 0x006432B0>
>>>

I find that the function object is presented by Python as belonging to the class (myClass.meth), but the attribute's string representation is not (its name is not preceded by myClass.) and is no different than if it were defined outside the class. What's the reasoning for this?

Upvotes: 2

Views: 763

Answers (3)

chepner
chepner

Reputation: 531175

This appears to be a side effect of defining a function inside a class statement. Defining the method at the global scope and calling type explicitly doesn't add the class name to the function's name.

Consider the following code:

class myClass:
    def meth(self):
        print(self)
    print("meth:", repr(meth))
    x = lambda self: print(self)
    print("x:", repr(x))


def mymeth(self):
    print(self)

print("mymeth:", repr(mymeth))
C = type('C', (object,), {'mymeth': mymeth})
print("mymeth:", repr(C.mymeth))

whose output is

meth: <function myClass.meth at 0x1055c6b90>
x: <function myClass.<lambda> at 0x1055c6dd0>
mymeth: <function mymeth at 0x1055c6b00>
mymeth: <function mymeth at 0x1055c6b00>

Things to note:

  1. Inside the class statement, the class name is added to the function name, whether you use def or a lambda expression. This indicates that the behavior is not part of the def statement. Also, this output is produced before the class object itself is actually created.

  2. Outside the class statement, the call to type does not add the class name to the function name. This suggests that it's the class statement itself, not the act of creating a class, that modifies the function name.


As to why this is the case? Presumably, it was decided that it would be useful to add a "fully qualified" method name in the output of function.__repr__ for debugging purposes, but I'm just speculating.

Upvotes: 2

iamKevin
iamKevin

Reputation: 11

It's because by calling myclass.meth, you are simply pointing to the memory location where the function is located.

But for myClass.z, you are just calling the contents returned by z. Similar to if it were:

class myClass:
    x = 2
    z = zip('abc', (97, 98, 99))
    ...

Then myClass.x would be 2

SIDENOTE: In your code snippet, z is a part of myClass. For simplicity's sake, it is the same as if you'd define self.z = zip('abc', (97, 98, 99)) with in the constructor. To get a clear understanding of why if really not like doing that, I'd check Class vs Instance attributes

ADDED EXAMPLE:
Adding another example that might shine some light on the issue, consider this

def some_fn():
   return 'hello world'

class A(object):
   p = some_fn

Then

A.p
>> <function some_fn at 0x7f00fefbef80>

and NOT

>>> <function A.some_fn at ... >

Upvotes: 0

Guy
Guy

Reputation: 50819

z is just a name, the value it holds is the builtin zip class, which is not part of myClass.

Upvotes: 0

Related Questions