Python 为什么类方法名的前缀是类名,而不是其他对象?

Python 为什么类方法名的前缀是类名,而不是其他对象?,python,python-3.x,Python,Python 3.x,在Python中,如果我定义一个简单类,如下所示: >>> class myClass: ... z = zip('abc', (97, 98, 99)) ... def meth(self): ... print(self) ... >>> 然后在提示下输入以下内容: >>> myClass.meth <function myClass.meth at 0x00639540> >>> myClass.

在Python中,如果我定义一个简单类,如下所示:

>>> class myClass:
...  z = zip('abc', (97, 98, 99))
...  def meth(self):
...   print(self)
...
>>>
然后在提示下输入以下内容:

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

我发现Python将函数对象表示为属于类(myClass.meth),但属性的字符串表示形式不是(它的名称前面没有myClass。),与在类外部定义时没有区别。原因是什么?

z
只是一个名称,它所持有的值是内置的
zip
类,它不属于
myClass

这是因为通过调用
myClass.meth
,您只需指向函数所在的内存位置

但是对于
myClass.z
,您只是调用
z
返回的内容。 与以下情况类似:

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

旁注:在代码片段中,
z
myClass
的一部分。为了简单起见,这与在构造函数中定义
self.z=zip('abc',(97,98,99))
是一样的。 为了弄清楚为什么我真的不喜欢这样做,我会检查一下

添加示例:
添加另一个可能对这个问题有启发的例子,请考虑这个

def some_fn():
返回“你好,世界”
A类(对象):
p=一些_fn
然后

A.p
>> 
不是

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

这似乎是在
类中定义函数的副作用。在全局范围定义方法并显式调用
type
不会将类名添加到函数名中

考虑以下代码:

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))
谁的输出是

meth: <function myClass.meth at 0x1055c6b90>
x: <function myClass.<lambda> at 0x1055c6dd0>
mymeth: <function mymeth at 0x1055c6b00>
mymeth: <function mymeth at 0x1055c6b00>
方法:
x:
mymeth:
mymeth:
注意事项:

  • 在class语句中,无论使用
    def
    还是lambda表达式,都会将类名添加到函数名中。这表示该行为不是
    def
    语句的一部分。此外,此输出是在实际创建
    对象本身之前生成的

  • 在class语句之外,对
    type
    的调用不会将类名添加到函数名中。这表明修改函数名的是
    class
    语句本身,而不是创建类的行为



  • 为什么会这样?据推测,在
    函数的输出中添加一个“完全限定”的方法名是有用的。为了调试的目的,我只是猜测一下。

    嗨。但“冰毒”也是一个名字。“z”和“meth”都是绑定到对象的名称。当在提示符下输入其中一个时,返回的描述是名称引用的对象,在这种情况下,我们将函数对象作为类的一部分接收回来,而不是zip对象。@learner类是可执行语句,因此使用
    myClass
    时执行
    z=zip()。函数仅在显式调用时执行,因此它们被绑定到类,但只有在类中,类名是函数位置的一部分时才执行。尝试
    myClass().meth
    ,您将获得所需的
    绑定方法myClass.meth
    。现在将
    x='asd'
    添加到
    myClass
    中,看看你得到了什么。我不确定我是否理解。。我们知道,在提示符下输入字符串不会像zip对象那样返回字符串表示形式,但是我添加了x='asd',它返回字符串本身('asd')。。这里的重点是什么@Learner显示它返回值,而不是类似于
    myClass.str
    。谢谢。。虽然说实话,我真的不能理解你的想法,这里没有存储在z或任何其他名称中的内容。“z”引用内存中的zip对象。当我们在提示符处输入这些绑定变量名称时,我们将返回它们所引用的任何内容。有些对象按原样返回(例如示例中的整数,字符串也是如此),但对于其他对象,例如zip对象和函数对象,返回一个文本表示(描述),关于这个描述,我要问:为什么它将函数对象描述为属于类(前面有类名和一个点),但zip对象不是….?我的措辞很糟糕。当我提到“z
    的内容”时,我指的是关于z
    输出的内容。从
    zip()
    ()的文档中,
    zip()
    输出一个迭代器对象,迭代器对象负责生成其输出。因此,所讨论的地址(
    )不必绑定到
    myClass
    ,因为它实际上指向python.Hi中的一个内置函数。感谢您确认我所问的问题。尽管我认为这不是问题“完全限定名称”是否显示(这可能不一致),函数确实有这样的归属/成员身份,而zip对象没有,Python显示的字符串rep简单地说明了这一点。我认为主要区别在于并非所有对象都有存储名称的属性;
    函数
    对象都有。这使得
    函数更容易提供一个比
    zip
    更自定义的名称,而不必动态地重新定义
    \uuuuuu repr\uuuuuu
    。谢谢。请告诉我,类对象是什么时候创建的?最终,是什么时候调用
    对象的。如果没有重写任何
    \uuuu call\uuuuu
    \uuuuuuuuu new\ucode>方法,则进程为:
    C()
    调用
    C.\uu调用
    ,解析为
    对象。\uu调用
    ,调用
    C.\uu新建
    ,解析为
    对象。\uu新建
    ,返回新对象。
    meth: <function myClass.meth at 0x1055c6b90>
    x: <function myClass.<lambda> at 0x1055c6dd0>
    mymeth: <function mymeth at 0x1055c6b00>
    mymeth: <function mymeth at 0x1055c6b00>