python – @staticmethod返回值
在
Python 3.6中,我试图在AbstractBaseClass中定义一个属性;我的第一次尝试是这样的(后来我发现我可以省略@staticmethod):
class AnAbstractClass(ABC): @property @staticmethod @abstractmethod def my_property(): pass 但是,PyCharm向我展示了对房产装饰者的警告: 据我所知,@ staticmethod装饰器不会返回可调用但不同的东西. 这里发生了什么? 解决方法
要了解您获得警告的原因,您需要了解
decorators和
descriptors.
装饰 装饰器是一个可调用的,它可以替换它正在装饰的东西,并将它分配给命名空间中的相同名称.通常,装饰器用于函数和类来添加一些功能,比如类型检查或线程或其他东西,但实际上它们可以返回任何东西. 由于装饰器的输出不必与输入的类型相同,或者执行任何相同的处理,因此装饰器的顺序非常重要.装饰器按照从最靠近函数的那个??到列表顶部的那个顺序应用.在你的情况下,abstractmethod,然后staticmethod,然后属性. 叙 描述符定义了一个相当复杂的协议,允许使用它们提供的绑定行为来定制对象.出于您的目的,您需要知道函数是描述符,并且将它们放入类对象中使用它.当您调用在该类的实例上的类中定义的任何描述符时,描述符协议使用描述符的__get__方法将描述符绑定到实例.描述符本身甚至不必是可调用的,也不是__get__的返回值,即使在大多数情况下它是预期的.对于函数,__ get__返回一个闭包,该闭包自动将self作为第一个位置参数传递. 例如,给定一个带有方法def b(self,arg):的类A,以及一个名为a的类的实例,执行a.b(arg)将变为A.b .__ get __(a,A)(arg).因此,虽然b被定义为具有两个位置参数,但是当在实例上调用时,它只需要一个明确地传递.但是,当您通过类调用b时,例如A.b(a,arg),它只是一个普通函数,您需要手动传递所有参数,包括self. 把它们放在一起
abstractmethod创建了一个相当普通的类方法,但它与元类
你的代码似乎遵循了这个禁令.事实上,抽象方法与你的警告无关,但无论如何在这里提一下似乎是个好主意. staticmethod返回一个绕过正常绑定行为的可调用对象,以创建一个不关心调用它的类或实例的方法.特别是,使用staticmethod .__ get__绑定的方法会将其参数传递给您的函数,而不是先自我预设(即,__ get__基本上只返回原始函数).你可以想象这对于希望接收自身参数的东西来说是一个问题,比如属性的setter. 与abstractmethod和staticmethod不同,属性创建数据描述符.这意味着它返回一个同时具有__get__绑定和__set__绑定(以及__del__绑定)的对象.属性的__get__方法与普通函数的__get__方法非常相似,但专门应用于getter函数.属性非常关心它被调用的实例,因为当然你希望不同的实例具有属性包装的属性的不同值. 所以你的代码中包含的是staticmethod,后跟属性.第一个装饰器返回一个函数,该函数在绑定时不会将self添加到其参数列表中,而第二个装饰器则执行.没有什么可以阻止你调用装饰器,但IDE警告告诉你,你不会成功调用结果对象.如果您尝试在AnyAbstractClass的具体实现上访问my_property,您可能会得到一个TypeError,告诉您my_property不接受任何位置参数,但是给出了一个,因为property .__ get__会将self添加到静态方法的参数列表中,不接受任何论点. 请记住,将staticmethod应用于属性的结果也不会对您有所帮助.属性实例根本不可调用.它完全通过__get __,__ set__和__del__方法运行,而staticmethod假定你传入一个可调用的方法. 解 正如您已经正确发现的那样,静态方法和属性不能很好地混合.就其本质而言,属性应始终了解其运行的实例.执行此操作的正确方法是添加自身参数并允许进行常规方法绑定. 属性和staticmethod都可以很好地与abstractmethod一起使用(只要首先应用abstractmethod),因为它实际上不会改变你的原始函数.事实上,abstractmethod的文档特别提到属性abstract的getter,setter或deleter使整个属性变得抽象. TL; DR staticmethod返回一个可调用的描述符,但其__get__方法返回其自身的未绑定版本. property创建一个不可调用的描述符,其__get__方法调用属性的getter.使用结果属性将尝试将self传递给不接受它的静态方法. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |