2

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?

0

3 Answers 3

2

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.

Sign up to request clarification or add additional context in comments.

4 Comments

Hi. Thanks for acknowledging the point I'm asking about. Though I dont think it's a matter of the "fully qualified name" being displayed or not (that would be rather inconsistent), It's that the function does actually have such belonging/membership, while the zip object not, and the string rep displayed back by Python simply illustrates that .
I think the main difference is that not all objects have an attribute that stores a name; function objects do. That makes it easier for function.__repr__ to provide a customized name than zip, without having to redefine __repr__ on the fly.
Thanks. Can u please tell me, when is a class object created?
Ultimately, when object.__new__ gets called. Assuming you haven't overriden any __call__ or __new__ methods, the progression is: C() calls C.__call__, which resolves to object.__call__, which calls C.__new__, which resolves to object.__new__, which returns a new object.
0

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

5 Comments

Hi. But "meth" is also a name. Both "z" and "meth" are names bound to objects. When either is entered at the prompt, the description returned is for the object the name references, and in which case we're receiving back the function object as being part of the class, but not the zip object ..
@Learnerer Classes are executable statement, so the z = zip() is executed when you use myClass. Functions are executed only when explicitly called, so they are bound to the class, but only when in the class, the class name is part of the function location. Try myClass().meth, you will get bound method myClass.meth as you expect. Now add x = 'asd' to myClass and see what you get.
I'm not sure I understand .. we know that entering strings at the prompt does not return string representation the way with a zip object.. , however I added x = 'asd' and it returns the string itself ('asd') .. what's the point here .. ?
@Learnerer To show it return the value, and not something like myClass.str.
Thanks.. though to be honest I really can't understand your idea here ..
0

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 ... >

2 Comments

There is no content stored in z, or any other name for that matter. "z" references the zip object in memory. When we enter those bound variables names at the prompt, we get back whatever they re referring to. Some objects are returned as they are (such as the integer in your example, so are strings too), but for other objects, such as zip objects and function objects, a text representation (description) is returned, and about that description I'm asking: why does it describe function objects as belonging to the class (preceded by the class name and a dot), but zip objects as not .. ?
Poor phrasing on my part. When I speak of "content of z" , i mean in respect to what z outputs. From the documentation of zip() (docs.python.org/3/library/functions.html#zip), the zip() outputs an iterator object which in turn, is responsible of producing its output. So the address in question (<zip object at 0x006432B0>) isn't bound to myClass because it is actually pointing to an in-built function in python.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.