[英]python - strange behavior question
>>> class S(object):
... def __init__(self):
... self.x = 1
... def x(self):
... return self.x
...
>>> s = S()
>>> s.x
1
>>> s.x()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable
在此示例中,为什么sx
是方法,但又是整数? 在我看来, self.x = 1
应该在实例化期间替换属性x
的def x(self):
声明。 为什么我可以获取和调用,分别导致整数和方法具有相同的属性? 我的猜测是,新样式类中的变量查找模式是鸭子类型的,以便将最相关的结果返回给调用者。 我很想听听整个故事。
Python不会为可调用和不可调用对象使用单独的空格:名称是名称就是名称。 根据Python规则, sx
必须引用完全相同的对象,无论您是否要调用它。 另一种表达方式:假设_aux
是未使用的名称,
_aux = self.x
_aux()
和
self.x()
必须在Python中具有绝对相同的语义,尽管前一个中间值self.x
已绑定到名称并随后被调用,这一事实。
具有可调用和不可调用的单个“统一”名称空间具有许多优点-例如,通过将名称与目标完全脱钩,从而使名称查找规则(对于裸名和合格名中的每一个)变得非常简单。所要查找的名称将被放置(无论是在查找结果之后还是稍后),以及根据查找首先被引用的对象的类型 (可调用或不可调用)规则。
特别是考虑到Python有多少种不同的可调用类型(函数,类,定义__call__
的类实例,特殊类型(例如staticmethod
和classmethod
,...!-)),任何其他规则都只会导致整个混乱。 (例如,还要注意,即使C ++,一种绝对不怕复杂性但也允许类实例可调用的语言[[如果类重载operator()
]],也使用类似的统一命名空间规则-同样,如果规则在这方面有任何不同,则区分可调用对象和不可调用对象将是完全没有根据的噩梦!
您似乎对所看到的错误有误解。 实例化s
对象时,其构造函数将方法x
替换为整数,因此在s
对象中, x
是整数,而不是函数。 尝试将其作为方法调用会导致引发异常。
从方法调用在运行时解决的意义上说,Python是鸭子类型的-编译器对sx()
没问题,因为x
可能是作为方法动态创建的。 但是,当解释器实际将x
作为方法调用时,它会注意到x
是一个整数并且无法调用,因此TypeError
。
我不确定您的想法,但没有任何棘手的事情发生。 当您分配self.x = 1
,方法x
将不再可用。 从那时起, sx
只是一个整数-如您所见,尝试将其作为方法调用会导致异常。
似乎x属性在类定义中定义为方法。 但是,实际上实例化一个对象会使用整数覆盖该名称-因此,会观察到行为。 实际上从来没有一次两个。 因此,这基本上是一些错误的代码。
这是您的代码正在执行的操作:
__init__
和x
2种方法创建名为S
的类 S
的实例并将其命名为s
s
为参数调用S.__init__
sx
设置为值1
sx
sx
的结果 现在,如果您在2.1.1中查看,您将看到您已经用整数覆盖了方法x
,这意味着您无法使用s
再次调用它(但它仍然在S
类中)
如果您已经做到了,但是仍然需要调用x
函数,请尝试:
>>> class S(object):
... def __init__(self):
... self.x = 1
... def x(self):
... return self.x
...
>>> s = S()
>>> s.x
1
>>> S.x(s)
1
>>>
我只是这样做了,所以您了解了为什么会丢失x as方法,以正确的方式进行操作并避免实例变量与类方法具有相同的名称
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.