Python 如何从类外访问类方法
这是最简单的例子:Python 如何从类外访问类方法,python,Python,这是最简单的例子: class Foo(): def five(self): return 5 def bar(): print Foo.five() 如您所见,我想从bar调用five,但问题是类方法将self作为参数 我已经解决了这个问题,通过将Foo实例一直输入到bar,如下所示: class Foo(): def five(self): return 5 def bar(instance_of_Foo): prin
class Foo():
def five(self):
return 5
def bar():
print Foo.five()
如您所见,我想从bar
调用five
,但问题是类方法将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()
的调用中。问题是在实例化Foo
之前需要调用bar()
,因为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的属性。您需要做的就是将函数标记为classmethod:
class Foo():
@classmethod
def five(cls):
return 5
def bar():
print Foo.five()
您只需将函数标记为classmethod:
class Foo():
@classmethod
def five(cls):
return 5
def bar():
print Foo.five()
首先,由于您既不依赖类也不依赖实例,简单的解决方案是: 也可以工作,但这是毫无意义的,除非有一些特定于类的行为,您希望根据可能的子类进行更改(您可以通过了解调用它的子类来获取信息);实际上,
@classmethod
实际上只适用于备用构造函数,在这里不适用
其次,Foo
在您的代码示例中没有名为self
的属性,因为您从未构造过Foo
的实例,因此从未调用\uuuu init\uuuu
来分配类属性。如果您想做类似的事情来创建一个单例实例,请不要在\uuuuu init\uuuu
中这样做;定义类后立即执行,例如:
class Foo():
...
Foo.singleton = Foo()
同样,也不是特别有用,因此如果可能的话,我会避免使用它。首先,简单的解决方案是: 也可以工作,但这是毫无意义的,除非有一些特定于类的行为,您希望根据可能的子类进行更改(您可以通过了解调用它的子类来获取信息);实际上,
@classmethod
实际上只适用于备用构造函数,在这里不适用
其次,Foo
在您的代码示例中没有名为self
的属性,因为您从未构造过Foo
的实例,因此从未调用\uuuu init\uuuu
来分配类属性。如果您想做类似的事情来创建一个单例实例,请不要在\uuuuu init\uuuu
中这样做;定义类后立即执行,例如:
class Foo():
...
Foo.singleton = Foo()
同样,这不是特别有用,所以如果可能的话,我会避免使用它。首先为什么需要
Foo
?five
可以仅仅是一个函数而不是一个方法吗?@chepnerFoo
是证明这个问题的最简单的类的形式/例子,我想。是的,但是它不可能告诉我们正确的解决方案是将five
变成一个类方法,一个静态方法,还是需要其他方法。我认为它被简化得太多了。解决编辑问题:你说你需要访问self
,但描述一个self
毫无意义的场景。试着提供一个例子来说明为什么@classmethod
/@staticmethod
不合适。例如,查看编写的代码,我只需跳过bar
,并使用foobar=Foo()
,t=threading.thread(target=foobar.five)
创建线程。或者,如果bar
必须是一个对象,那么给它一个参数来调用five
,这样您就可以执行t=threading.Thread(target=bar,args=(foobar,)
。如果需要,您甚至可以将参数设置为Foo
的默认实例,这样就可以在不传递参数的情况下调用bar
,并且它将重用默认设置的Foo
。首先为什么需要Foo
?five
可以仅仅是一个函数而不是一个方法吗?@chepnerFoo
是证明这个问题的最简单的类的形式/例子,我想。是的,但是它不可能告诉我们正确的解决方案是将five
变成一个类方法,一个静态方法,还是需要其他方法。我认为它被简化得太多了。解决编辑问题:你说你需要访问self
,但描述一个self
毫无意义的场景。试着提供一个例子来说明为什么@classmethod
/@staticmethod
不合适。例如,查看编写的代码,我只需跳过bar
,并使用foobar=Foo()
,t=threading.thread(target=foobar.five)
创建线程。或者,如果bar
必须是一个对象,那么给它一个参数来调用five
,这样您就可以执行t=threading.Thread(target=bar,args=(foobar,)
。如果需要,您甚至可以将参数设置为Foo
的默认实例,这样就可以在不传递参数的情况下调用bar
,它将重用默认的Foo
。通常,classmethod
用于替代构造函数(您需要知道调用它来构造相应子类的真实子类);如果您只是为返回常量的函数命名空间,那么您最好坚持使用staticmethod
,避免接受(并忽略)cls
。我已经编辑了这个问题;事实上,Five是一个更复杂的方法,需要访问self。一般来说,classmethod
用于替代构造函数(您需要知道调用它来构造适当子类的真实子类);如果你只是给一个返回常量的函数命名,那么你最好坚持使用staticmethod
,避免接受(或忽略)cls
。我已经编辑了这个问题;实际上,5是一个muc