如何从外部类访问类方法

时间:2019-01-02 20:41:26

标签: python

这是最简单的示例:

class Foo():
    def five(self):
        return 5

def bar():
    print Foo.five()

如您所见,我想从five调用bar,但是问题是类方法采用self作为参数。

我通过将Foo实例一直输入到bar来解决了这个问题,如下所示:

class Foo():

    def five(self):
        return 5


def bar(instance_of_Foo):
    print Foo.five(instance_of_Foo)


foobar = Foo()

bar(foobar)

此解决方案可以正常工作,因为我可以将Foo的实例输入到对bar()的调用中。问题在于,在实例化bar()之前需要调用Foo,因为Foo对象是线程的目标。

下面是一个更复杂的示例,演示了该问题:

from tkinter import *
import threading
import time

count = 0

def counter():
    global count
    while True:
        count += 1
        print count
        time.sleep(1)

class GUI():
    def __init__(self):
        self.root = Tk()

    def five(self):
        global count

        self.var = StringVar()
        self.var.set(count)

        self.label = Label(self.root, textvariable=self.var)
        self.label.pack()

        self.root.mainloop()

def update_gui():
    global count
    while True:
        GUI.var = count
        GUI.root.update()

threads = []
t = threading.Thread(target=update_gui)
threads.append(t)
t.start()

countbot = threading.Thread(target=counter)
threads.append(countbot)
countbot.start()

foobar = GUI()
foobar.five()

以上抛出此错误:

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 801, in __bootstrap_inner
    self.run()
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 754, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/Users/Henry/documents/python/blank3.py", line 36, in update_gui
    GUI.root.update()
AttributeError: class GUI has no attribute 'root'

这真的让我感到惊讶,因为GUI确实具有一个名为root的属性。

2 个答案:

答案 0 :(得分:3)

您需要做的就是将函数标记为类方法:

class Foo():

    @classmethod
    def five(cls):
        return 5

def bar():
    print Foo.five()

答案 1 :(得分:3)

首先,由于您既不依赖类也不依赖实例,所以简单的解决方案是make your method a static method

class Foo():

    @staticmethod
    def five():
        return 5

def bar():
    print Foo.five()

A class method也可以使用,但是除非有某些特定类的行为要根据可能的子类来更改(从已知子类中被调用的子类中派生信息),否则它是没有意义的。实际上,@classmethod实际上仅适用于备用构造函数,不适用于此处。

第二,在您的代码示例中,Foo没有名为self的属性,因为您从未构造过Foo的实例,因此从未调用__init__来分配class属性。如果您想执行类似的操作来使单例实例正常工作,请不要在__init__中执行;定义类后立即执行操作,例如:

class Foo():
    ...
Foo.singleton = Foo()

同样,它不是特别有用,因此,如果可能的话,我会避免使用它。