如何调用类中的函数并且没有参数?想要没有装饰者的解决方案

时间:2014-09-22 10:19:54

标签: python

如何调用类中的函数并且没有参数?我已经知道@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?或者该函数是一个永远不能被调用的函数?

我没有解决任何现实问题。我只是对这种功能的状态感到好奇。通过这样的声明,我创建了一个无用的函数,一个无法通过任何方式访问的函数?这只是一个理论问题。

谢谢!

3 个答案:

答案 0 :(得分:2)

代码中的

ss不是一个方法;它是一个放在一个类中的可调用函数。在查找方法时,Python将该方法绑定到实例,注入第一个参数,该参数保证是正确类的实例(像classmethodstaticmethod这样的装饰器处理该参数)。这就是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装饰器上的文档。