如何调用类中的函数并且没有参数?我已经知道@staticmethod
和@classmethod
了。这问题的问题是没有@staticmethod
的解决方案。
这是我在学习@staticmethod
和@classmethod
后出现的问题。我很好奇这样的函数是否会成为一个函数,如果它没有任何参数和装饰器就永远不会被调用。
class RRR:
def ss():
print "in ss"
def x(self):
ss()
def y(self):
self.ss()
def z(self):
RRR.ss()
我已经知道那些方法无法正常工作。但我只是向你展示结果。
>>> a = RRR()
>>> a.x()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in x
NameError: global name 'ss' is not defined
>>> a.y()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in y
TypeError: ss() takes no arguments (1 given)
>>> a.z()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 9, in z
TypeError: unbound method ss() must be called with RRR instance as first argument (got nothing instead)
我想知道如何调用像RRR.ss()
这样的函数?有没有其他可能的方法来调用这样的函数?
我已经知道,只需在@staticmethod
函数之前添加一行ss()
,就可以调用该函数,如self.ss()
或RRR.ss()
。
但是在这个问题中,我想问的是,不添加@staticmethod
,并保持RRR.ss
的声明代码不变,有没有办法调用RRR.ss
?或者该函数是一个永远不能被调用的函数?
我没有解决任何现实问题。我只是对这种功能的状态感到好奇。通过这样的声明,我创建了一个无用的函数,一个无法通过任何方式访问的函数?这只是一个理论问题。
谢谢!
答案 0 :(得分:2)
ss
不是一个方法;它是一个放在一个类中的可调用函数。在查找方法时,Python将该方法绑定到实例,注入第一个参数,该参数保证是正确类的实例(像classmethod
和staticmethod
这样的装饰器处理该参数)。这就是a.x
的情况;它是一个通过实例属性查找的类可调用,因此生成一个绑定方法。由于您的ss
不接受此参数,因此无法使用方法调用来调用它。然而,它可以从类中调用,例如使用a.__class__.__dict__['ss']()
或a.ss.im_func()
(这是解释Martijn Pieters提到的)。
答案 1 :(得分:0)
我已经知道了,之前只需添加一行@staticmethod ss()函数,然后可以调用函数,如self.ss()或 RRR.ss()。但在这个问题上,我想问的是,保持这个问题 RRR.ss的声明代码没有变化,有没有办法调用RRR.ss? 或者该函数是一个永远不能被调用的函数?
它不是永远不会被召唤的,只是它不在范围内。一个类定义了一个命名空间(把它想象成一个带有门的墙),该类体内的所有东西都在墙后面。要获得它或调用它,你需要通过门,这是一个类的实例或类本身。
这称为解析,即找出定义名称的位置以便使用它。默认情况下,当您运行任何代码时,它在特定范围内运行;要找出范围内可用的内容,您可以使用globals()
和locals()
作为全局本地范围:
Python 2.7.3 (default, Jan 2 2013, 16:53:07)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> globals()
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, '__package__': None}
>>> locals()
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, '__package__': None}
如您所见,当您第一次启动Python交互式提示时,它在范围内有一些内容。现在,当您创建一个类时,会发生以下情况:
>>> class Foo(object):
... def a():
... print 'Hello'
...
>>> globals()
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', 'Foo': <class '__main__.Foo'>, '__doc__': None, '__package__': None}
>>> locals()
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', 'Foo': <class '__main__.Foo'>, '__doc__': None, '__package__': None}
您注意到只有Foo
可用,而不是a
。为了让我到达a
,我必须通过使用Foo.
对其进行限定来指定其范围(.
是范围解析运算符)。
答案 2 :(得分:0)
这个例子应该清楚一点:
class Dog(object):
def __init__(self, name):
self.name = name
def get_name(self):
"""
Instance method
Gets passed the instance as the implicit first argument
"""
print "My name is '{}'".format(self.name)
@classmethod
def get_class(cls):
"""
Class method
Gets passed the class as the implicit first argument
"""
print "I'm the '{}' class".format(cls.__name__)
@staticmethod
def foo():
"""
Static method
Gets passed *no* implicit arguments. Basically just a
function attached to a class.
"""
print "I've got no arguments"
dog = Dog('spot')
dog.get_name()
Dog.get_class()
Dog.foo()
输出:
My name is 'spot'
I'm the 'Dog' class
I've got no arguments
你可以在实例(dog.foo()
或self.foo()
)上调用静态或类方法,但通常你不应该,因为你混淆了他们的事实不要将实例作为参数。
有关详细信息,请参阅@classmethod
和@staticmethod
装饰器上的文档。