繁体   English   中英

奇怪的行为问题

[英]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应该在实例化期间替换属性xdef x(self):声明。 为什么我可以获取和调用,分别导致整数和方法具有相同的属性? 我的猜测是,新样式类中的变量查找模式是鸭子类型的,以便将最相关的结果返回给调用者。 我很想听听整个故事。

Python不会为可调用和不可调用对象使用单独的空格:名称是名称就是名称。 根据Python规则, sx 必须引用完全相同的对象,无论您是否要调用它。 另一种表达方式:假设_aux是未使用的名称,

_aux = self.x
_aux()

self.x()

必须在Python中具有绝对相同的语义,尽管前一个中间值self.x已绑定到名称并随后被调用,这一事实。

具有可调用和不可调用的单个“统一”名称空间具有许多优点-例如,通过将名称与目标完全脱钩,从而使名称查找规则(对于裸名和合格名中的每一个)变得非常简单。所要查找的名称将被放置(无论是在查找结果之后还是稍后),以及根据查找首先被引用的对象的类型 (可调用或不可调用)规则。

特别是考虑到Python有多少种不同的可调用类型(函数,类,定义__call__的类实例,特殊类型(例如staticmethodclassmethod ,...!-)),任何其他规则都只会导致整个混乱。 (例如,还要注意,即使C ++,一种绝对不怕复杂性但允许类实例可调用的语言[[如果类重载operator() ]],也使用类似的统一命名空间规则-同样,如果规则在这方面有任何不同,则区分可调用对象和不可调用对象将是完全没有根据的噩梦!

您似乎对所看到的错误有误解。 实例化s对象时,其构造函数将方法x替换为整数,因此在s对象中, x是整数,而不是函数。 尝试将其作为方法调用会导致引发异常。

从方法调用在运行时解决的意义上说,Python是鸭子类型的-编译器对sx()没问题,因为x可能是作为方法动态创建的。 但是,当解释器实际将x作为方法调用时,它会注意到x是一个整数并且无法调用,因此TypeError

我不确定您的想法,但没有任何棘手的事情发生。 当您分配self.x = 1 ,方法x将不再可用。 从那时起, sx只是一个整数-如您所见,尝试将其作为方法调用会导致异常。

似乎x属性在类定义中定义为方法。 但是,实际上实例化一个对象会使用整数覆盖该名称-因此,会观察到行为。 实际上从来没有一次两个。 因此,这基本上是一些错误的代码。

这是您的代码正在执行的操作:

  1. 使用__init__x 2种方法创建名为S的类
  2. 创建S的实例并将其命名为s
    1. s为参数调用S.__init__
      1. sx设置为值1
  3. 打印sx
  4. 打印调用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM